import { render } from "tradjs/client";
import * as THREE from "three";

export default function mount() {
  const root = document.getElementById("game-root");
  if (!root) return () => {};

  render(
    <div style={{ minHeight: "100vh", background: "#05030a", color: "#fff4dc", fontFamily: "system-ui,sans-serif", display: "grid", placeItems: "center", padding: "12px", boxSizing: "border-box" }}>
      <main style={{ width: "min(96vw,980px)", textAlign: "center" }}>
        <h1 style={{ margin: "0 0 3px", color: "#ffc857", letterSpacing: "3px" }}>MINOTAUR MASTER MAZE</h1>
        <p style={{ margin: "0 0 8px", color: "#cabda9" }}>Claim three relics, bait the Minotaur into pillars, then escape the collapsing labyrinth.</p>
        <div id="game-view" style={{ position: "relative", width: "100%", aspectRatio: "16/10", overflow: "hidden", border: "2px solid #704b38", borderRadius: "10px", boxShadow: "0 16px 50px #000c", touchAction: "none", background: "#100914" }}>
          <div id="hud" style={{ position: "absolute", zIndex: 2, inset: "0 0 auto 0", display: "flex", justifyContent: "space-between", gap: "8px", padding: "9px 12px", background: "linear-gradient(#09030eee,transparent)", fontWeight: "900", fontSize: "clamp(11px,2vw,15px)", pointerEvents: "none", textShadow: "0 2px 4px #000" }}><span id="hud-left" /><span id="hud-mid" /><span id="hud-right" /></div>
          <div id="bossbar" style={{ position: "absolute", zIndex: 2, left: "20%", right: "20%", top: "42px", height: "12px", border: "1px solid #e7b77c", background: "#190b0d", borderRadius: "8px", overflow: "hidden", pointerEvents: "none" }}><div id="bossfill" style={{ height: "100%", width: "100%", background: "linear-gradient(90deg,#ff3b4d,#ff9f43)", transition: "width .25s" }} /></div>
          <div id="notice" style={{ display: "none", position: "absolute", zIndex: 3, inset: "50% auto auto 50%", transform: "translate(-50%,-50%)", width: "min(82%,580px)", padding: "20px", borderRadius: "12px", background: "#09030eef", border: "1px solid #b47a4f", fontWeight: "900", fontSize: "clamp(17px,4vw,31px)", pointerEvents: "none" }} />
          <div style={{ position: "absolute", zIndex: 2, left: "10px", bottom: "9px", color: "#dbcbb6", background: "#08030bc9", padding: "6px 9px", borderRadius: "7px", fontSize: "12px", pointerEvents: "none" }}>Gold: relic · Orange: Minotaur · Red cracks: unstable walls · Green: final gate</div>
        </div>
        <div style={{ display: "flex", justifyContent: "center", gap: "9px", alignItems: "center", flexWrap: "wrap", marginTop: "10px" }}>
          <button id="restart-game" style={{ border: 0, borderRadius: "8px", padding: "10px 18px", background: "#ffc857", color: "#20150d", fontWeight: "900", cursor: "pointer" }}>Restart (R)</button>
          <button id="dash-game" style={{ border: "1px solid #c87552", borderRadius: "8px", padding: "9px 15px", background: "#3b1718", color: "#ffe9d0", fontWeight: "850", cursor: "pointer" }}>Dash</button>
          <span style={{ color: "#bcae9d", fontSize: "14px" }}>Move: WASD/arrows · Dash: Space/Shift · Swipe/tap</span>
        </div>
      </main>
    </div>, root
  );

  const view = root.querySelector("#game-view") as HTMLDivElement;
  const restart = root.querySelector("#restart-game") as HTMLButtonElement;
  const dashButton = root.querySelector("#dash-game") as HTMLButtonElement;
  const leftHud = root.querySelector("#hud-left") as HTMLElement;
  const midHud = root.querySelector("#hud-mid") as HTMLElement;
  const rightHud = root.querySelector("#hud-right") as HTMLElement;
  const bossbar = root.querySelector("#bossbar") as HTMLElement;
  const bossfill = root.querySelector("#bossfill") as HTMLElement;
  const notice = root.querySelector("#notice") as HTMLElement;

  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x100914);
  scene.fog = new THREE.FogExp2(0x100914, .043);
  const camera = new THREE.PerspectiveCamera(51, 1, .1, 100);
  const renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.domElement.style.cssText = "width:100%;height:100%;display:block;touch-action:none";
  view.insertBefore(renderer.domElement, view.firstChild);
  scene.add(new THREE.HemisphereLight(0x9b74b8, 0x2a1008, 1.8));
  const sun = new THREE.DirectionalLight(0xffd39b, 1.7);
  sun.position.set(-7, 12, 7); sun.castShadow = true; scene.add(sun);
  const flame = new THREE.PointLight(0xff5b2e, 3, 11); flame.position.set(0, 3, 0); scene.add(flame);

  const COLS = 15, ROWS = 11;
  type Pos = { x:number; y:number };
  type Thing = Pos & { mesh:THREE.Object3D };
  const dirs:[number,number][] = [[1,0],[-1,0],[0,1],[0,-1]];
  const original = [
    "###############",
    "#.....#.......#",
    "#.###.#.#####.#",
    "#.#...#.....#.#",
    "#.#.#####.#.#.#",
    "#...#.....#...#",
    "###.#.###.###.#",
    "#...#.#.......#",
    "#.###.#.#####.#",
    "#.....#.......#",
    "###############"
  ];
  const arena = new THREE.Group(); scene.add(arena);
  const floorMat = new THREE.MeshStandardMaterial({ color:0x291b25, roughness:.92 });
  const wallMat = new THREE.MeshStandardMaterial({ color:0x57404a, roughness:.78 });
  const crackMat = new THREE.MeshStandardMaterial({ color:0x773329, emissive:0x351009, roughness:.7 });
  const heroMat = new THREE.MeshStandardMaterial({ color:0x55dff4, emissive:0x123f52, roughness:.35 });
  let grid:string[][] = [];
  let player:Pos = {x:1,y:1};
  let playerMesh:THREE.Mesh;
  let boss:Thing;
  let relics:Thing[] = [], pillars:Thing[] = [], wallMeshes = new Map<string,THREE.Mesh>();
  let exit:Thing;
  let state:"relics"|"battle"|"escape"|"won"|"lost" = "relics";
  let bossHP=3, relicCount=0, dashes=4, timeLeft=105, elapsed=0, collapse=0;
  let bossClock=0, chargeClock=0, charging=false, chargeDir:[number,number]=[0,0], lastDir:[number,number]=[1,0];
  let raf=0, last=performance.now(), pointer:{x:number;y:number;t:number}|null=null;
  let message="", messageUntil=0;
  const rankings:number[]=[];
  const key=(x:number,y:number)=>`${x},${y}`;
  const same=(a:Pos,b:Pos)=>a.x===b.x&&a.y===b.y;
  const place=(o:THREE.Object3D,p:Pos,h=.4)=>o.position.set(p.x-(COLS-1)/2,h,p.y-(ROWS-1)/2);
  const inside=(p:Pos)=>p.x>0&&p.x<COLS-1&&p.y>0&&p.y<ROWS-1;
  const open=(p:Pos)=>inside(p)&&grid[p.y][p.x]!=="#";
  function make(geo:THREE.BufferGeometry,color:number,emissive=0){const m=new THREE.Mesh(geo,new THREE.MeshStandardMaterial({color,emissive,roughness:.5,metalness:.08}));m.castShadow=true;m.receiveShadow=true;arena.add(m);return m;}
  function removeObject(o:THREE.Object3D){arena.remove(o);o.traverse(q=>{const m=q as THREE.Mesh;m.geometry?.dispose();const mat=m.material as THREE.Material|THREE.Material[];if(Array.isArray(mat))mat.forEach(v=>v.dispose());else mat?.dispose();});}
  function clearWorld(){while(arena.children.length)removeObject(arena.children[0]);wallMeshes.clear();}
  function show(text:string,ms=1200,color="#ffe6ba"){message=text;messageUntil=performance.now()+ms;notice.style.color=color;}
  function wall(x:number,y:number,cracked=false){const m=new THREE.Mesh(new THREE.BoxGeometry(.94,1.45,.94),cracked?crackMat:wallMat);place(m,{x,y},.58);m.castShadow=m.receiveShadow=true;arena.add(m);wallMeshes.set(key(x,y),m);}
  function breakWall(x:number,y:number){if(!inside({x,y})||grid[y][x]!=="#")return false;grid[y][x]=".";const m=wallMeshes.get(key(x,y));if(m){arena.remove(m);wallMeshes.delete(key(x,y));}return true;}
  function addThing(list:Thing[],p:Pos,geo:THREE.BufferGeometry,color:number,emissive=0,h=.4){const m=make(geo,color,emissive);place(m,p,h);const v={...p,mesh:m};list.push(v);return v;}
  function build(){
    clearWorld(); grid=original.map(r=>r.split("")); relics=[];pillars=[];
    const floor=new THREE.Mesh(new THREE.BoxGeometry(COLS,.22,ROWS),floorMat);floor.position.y=-.17;floor.receiveShadow=true;arena.add(floor);
    const cracks=new Set(["6,1","6,3","4,5","6,7","6,9","12,5","2,6"]);
    for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++)if(grid[y][x]==="#")wall(x,y,cracks.has(key(x,y)));
    player={x:1,y:1};playerMesh=make(new THREE.CapsuleGeometry(.25,.46,5,10),0x55dff4,0x123f52);(playerMesh.material as THREE.Material).dispose();playerMesh.material=heroMat;place(playerMesh,player,.49);
    addThing(relics,{x:5,y:3},new THREE.DodecahedronGeometry(.25),0xffd05c,0x704300,.43);
    addThing(relics,{x:9,y:5},new THREE.DodecahedronGeometry(.25),0xffd05c,0x704300,.43);
    addThing(relics,{x:13,y:9},new THREE.DodecahedronGeometry(.25),0xffd05c,0x704300,.43);
    [{x:3,y:5},{x:9,y:3},{x:11,y:7}].forEach(p=>addThing(pillars,p,new THREE.CylinderGeometry(.34,.44,1.2,8),0xc99868,0,.6));
    const body=make(new THREE.CapsuleGeometry(.42,.68,6,12),0xd64b30,0x3d0904);place(body,{x:13,y:1},.62);boss={x:13,y:1,mesh:body};
    const hornGeo=new THREE.ConeGeometry(.12,.5,8);const h1=new THREE.Mesh(hornGeo,new THREE.MeshStandardMaterial({color:0xffe0a6}));const h2=h1.clone();h1.position.set(-.28,.62,0);h2.position.set(.28,.62,0);h1.rotation.z=.55;h2.rotation.z=-.55;body.add(h1,h2);
    exit={x:13,y:9,mesh:make(new THREE.TorusGeometry(.46,.13,10,28),0x35df87,0x0b653b)};place(exit.mesh,exit,.5);exit.mesh.rotation.x=Math.PI/2;exit.mesh.visible=false;
    state="relics";bossHP=3;relicCount=0;dashes=4;timeLeft=105;elapsed=0;collapse=0;bossClock=0;chargeClock=0;charging=false;lastDir=[1,0];last=performance.now();
    restart.textContent="Restart (R)";notice.style.display="none";show("HUNT THE THREE SUN RELICS",1800);bossbar.style.display="none";
  }
  function finish(win:boolean){
    if(state==="won"||state==="lost")return;
    state=win?"won":"lost";notice.style.display="block";
    if(win){rankings.push(elapsed);rankings.sort((a,b)=>a-b);rankings.splice(5);const rank=rankings.indexOf(elapsed)+1;notice.style.color="#6ff0aa";notice.innerHTML=`ESCAPED THE MASTER MAZE!<div style="font-size:16px;color:#fff4dc;margin-top:9px">Time ${elapsed.toFixed(1)}s · Session rank #${rank}<br>Best times: ${rankings.map((v,i)=>`${i+1}. ${v.toFixed(1)}s`).join(" · ")}<br>Press R, Enter, or Play Again</div>`;restart.textContent="Play Again (R)";}
    else{notice.style.color="#ff6470";notice.innerHTML=`THE MINOTAUR CLAIMS THE MAZE<div style="font-size:16px;color:#fff4dc;margin-top:9px">Relics ${relicCount}/3 · Boss wounds ${3-bossHP}/3<br>Press R, Enter, or Retry</div>`;restart.textContent="Retry (R)";}
  }
  function collect(){
    const i=relics.findIndex(r=>same(r,player));if(i>=0){removeObject(relics[i].mesh);relics.splice(i,1);relicCount++;timeLeft+=7;show(`SUN RELIC ${relicCount}/3 · +7 SECONDS`,1000,"#ffd05c");}
    if(relicCount===3&&state==="relics"){state="battle";bossbar.style.display="block";show("BOSS PHASE: BAIT CHARGES INTO STONE PILLARS",2200,"#ff8b67");}
    if(state==="escape"&&same(player,exit))finish(true);
  }
  function hitPlayer(){if(state!=="won"&&state!=="lost")finish(false);}
  function step(dx:number,dy:number,boost=false){
    if(state==="won"||state==="lost")return;lastDir=[dx,dy];let count=boost&&dashes>0?2:1;if(count===2)dashes--;let moved=false;
    for(let i=0;i<count;i++){const n={x:player.x+dx,y:player.y+dy};if(!open(n))break;player=n;moved=true;collect();if(same(player,boss))hitPlayer();}
    if(count===2&&!moved)dashes++;
  }
  function chooseBossStep(){const choices=dirs.map(([dx,dy])=>({x:boss.x+dx,y:boss.y+dy})).filter(open);if(!choices.length)return;choices.sort((a,b)=>Math.abs(a.x-player.x)+Math.abs(a.y-player.y)-Math.abs(b.x-player.x)-Math.abs(b.y-player.y));const p=choices[0];boss.x=p.x;boss.y=p.y;if(same(boss,player))hitPlayer();}
  function beginCharge(){
    const dx=player.x-boss.x,dy=player.y-boss.y;
    if(Math.abs(dx)>Math.abs(dy))chargeDir=[Math.sign(dx),0];else chargeDir=[0,Math.sign(dy)];
    charging=true;chargeClock=0;show("CHARGE! DODGE BEHIND A PILLAR",650,"#ff6655");
  }
  function chargeStep(){
    const nx=boss.x+chargeDir[0],ny=boss.y+chargeDir[1];
    const pi=pillars.findIndex(p=>p.x===nx&&p.y===ny);
    if(pi>=0){removeObject(pillars[pi].mesh);pillars.splice(pi,1);bossHP--;charging=false;bossfill.style.width=`${bossHP/3*100}%`;show(`MINOTAUR STUNNED · ${bossHP} WOUNDS LEFT`,1300,"#ffe08a");for(const [dx,dy] of dirs)breakWall(nx+dx,ny+dy);if(bossHP<=0)startEscape();return;}
    if(grid[ny]?.[nx]==="#"){breakWall(nx,ny);boss.x=nx;boss.y=ny;return;}
    if(!inside({x:nx,y:ny})){charging=false;return;}
    boss.x=nx;boss.y=ny;if(same(boss,player))hitPlayer();
  }
  function startEscape(){
    state="escape";charging=false;boss.mesh.visible=false;exit.mesh.visible=true;timeLeft=Math.max(timeLeft,28);bossbar.style.display="none";
    [[6,1],[6,3],[4,5],[6,7],[6,9],[12,5]].forEach(([x,y])=>breakWall(x,y));
    show("MINOTAUR DEFEATED! THE MAZE COLLAPSES — ESCAPE!",2400,"#65f2a5");
  }
  function collapseMaze(){
    const candidates:Pos[]=[];for(let y=1;y<ROWS-1;y++)for(let x=1;x<COLS-1;x++)if(grid[y][x]==="."&&!same({x,y},player)&&!same({x,y},exit)&&Math.abs(x-player.x)+Math.abs(y-player.y)>2)candidates.push({x,y});
    if(candidates.length){const p=candidates[Math.floor(Math.random()*candidates.length)];grid[p.y][p.x]="#";wall(p.x,p.y,true);}
  }
  function frame(now:number){
    const dt=Math.min(.05,(now-last)/1000);last=now;
    if(state!=="won"&&state!=="lost"){
      elapsed+=dt;timeLeft-=dt;bossClock+=dt;
      if(timeLeft<=0){timeLeft=0;finish(false);}
      if(state==="relics"&&bossClock>.72){bossClock=0;chooseBossStep();}
      if(state==="battle"){
        if(charging){chargeClock+=dt;if(chargeClock>.105){chargeClock=0;chargeStep();}}
        else if(bossClock>Math.max(.75,1.55-(3-bossHP)*.28)){bossClock=0;beginCharge();}
      }
      if(state==="escape"){collapse+=dt;if(collapse>1.65){collapse=0;collapseMaze();}}
    }
    const px=player.x-(COLS-1)/2,pz=player.y-(ROWS-1)/2;
    playerMesh.position.lerp(new THREE.Vector3(px,.49,pz),.25);
    boss.mesh.position.lerp(new THREE.Vector3(boss.x-(COLS-1)/2,.62,boss.y-(ROWS-1)/2),charging?.42:.18);boss.mesh.rotation.y+=dt*(charging?8:2);
    relics.forEach((r,i)=>{r.mesh.rotation.y+=dt*2.2;r.mesh.position.y=.43+Math.sin(now/270+i)*.08;});
    pillars.forEach(p=>p.mesh.rotation.y+=dt*.25);exit.mesh.rotation.z+=dt*1.8;flame.intensity=2.6+Math.sin(now/120)*.5;
    camera.position.lerp(new THREE.Vector3(px+6.6,9.2,pz+7.8),.055);camera.lookAt(px,0,pz);
    leftHud.textContent=`${state==="relics"?"RELIC HUNT":state==="battle"?`MINOTAUR PHASE ${4-bossHP}`:state==="escape"?"FINAL ESCAPE":"MASTER MAZE"}`;
    midHud.textContent=`RELICS ${relicCount}/3 · DASH ${dashes}${state==="battle"?` · WOUNDS ${3-bossHP}/3`:""}`;
    rightHud.textContent=`TIME ${Math.ceil(timeLeft)} · BEST ${rankings.length?rankings[0].toFixed(1)+"s":"—"}`;rightHud.style.color=timeLeft<15?"#ff6470":"#fff4dc";
    if(state!=="won"&&state!=="lost"){if(now<messageUntil){notice.style.display="block";notice.textContent=message;}else notice.style.display="none";}
    renderer.render(scene,camera);raf=requestAnimationFrame(frame);
  }
  function resize(){const r=view.getBoundingClientRect();renderer.setSize(r.width,r.height,false);camera.aspect=r.width/r.height;camera.updateProjectionMatrix();}
  function reset(){build();}
  function dash(){step(...lastDir,true);}
  function onKey(e:KeyboardEvent){const moves:Record<string,[number,number]>={ArrowUp:[0,-1],w:[0,-1],W:[0,-1],ArrowDown:[0,1],s:[0,1],S:[0,1],ArrowLeft:[-1,0],a:[-1,0],A:[-1,0],ArrowRight:[1,0],d:[1,0],D:[1,0]};if(moves[e.key]){e.preventDefault();step(...moves[e.key],e.shiftKey);}if(e.code==="Space"){e.preventDefault();dash();}if(e.key.toLowerCase()==="r"||(e.key==="Enter"&&(state==="won"||state==="lost")))reset();}
  function down(e:PointerEvent){pointer={x:e.clientX,y:e.clientY,t:performance.now()};renderer.domElement.setPointerCapture(e.pointerId);}
  function up(e:PointerEvent){if(!pointer)return;const dx=e.clientX-pointer.x,dy=e.clientY-pointer.y,fast=performance.now()-pointer.t<280;pointer=null;if(Math.hypot(dx,dy)<14){dash();return;}const m:[number,number]=Math.abs(dx)>Math.abs(dy)?[Math.sign(dx),0]:[0,Math.sign(dy)];step(...m,fast&&Math.hypot(dx,dy)>65);}
  window.addEventListener("keydown",onKey);window.addEventListener("resize",resize);renderer.domElement.addEventListener("pointerdown",down);renderer.domElement.addEventListener("pointerup",up);restart.addEventListener("click",reset);dashButton.addEventListener("click",dash);resize();reset();raf=requestAnimationFrame(frame);
  return()=>{cancelAnimationFrame(raf);window.removeEventListener("keydown",onKey);window.removeEventListener("resize",resize);renderer.domElement.removeEventListener("pointerdown",down);renderer.domElement.removeEventListener("pointerup",up);restart.removeEventListener("click",reset);dashButton.removeEventListener("click",dash);clearWorld();floorMat.dispose();wallMat.dispose();crackMat.dispose();heroMat.dispose();renderer.dispose();renderer.domElement.remove();root.replaceChildren();};
}