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

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

  const shell = document.createElement("div");
  shell.dir = "rtl";
  shell.style.cssText = "min-height:100%;display:grid;place-items:center;background:#040914;color:#eef7ff;font-family:system-ui,sans-serif;padding:14px;box-sizing:border-box";
  shell.innerHTML = `<div style="width:min(1000px,100%)">
    <div style="display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:9px">
      <div><div style="font-size:clamp(22px,4vw,34px);font-weight:900;color:#ffd166">الحارس المُنهك: مدينة ثلاثية الأبعاد</div><div style="color:#b9cee2;font-size:14px">أنقذ المدنيين قبل نفاد الوقت والطاقة، وتفادَ الحرائق والحطام والمجرمين.</div></div>
      <button id="restart" style="border:0;border-radius:11px;background:#ef476f;color:white;font-weight:900;padding:12px 18px;cursor:pointer">إعادة / Retry (R)</button>
    </div>
    <div id="stage" style="height:min(68vh,620px);min-height:420px;position:relative;overflow:hidden;border:2px solid #29435f;border-radius:15px;background:#081321;touch-action:none">
      <div id="hud" style="position:absolute;z-index:2;inset:0 0 auto 0;padding:11px 15px;background:linear-gradient(#020713dd,transparent);pointer-events:none;text-shadow:0 2px 3px #000">
        <div style="display:flex;justify-content:space-between;gap:12px;font-weight:900"><span id="progress"></span><span id="clock"></span></div>
        <div style="width:min(330px,65%);height:16px;margin:9px auto 0;border:2px solid #dff;background:#111827;border-radius:9px;overflow:hidden"><div id="energy" style="height:100%;background:#06d6a0"></div></div>
        <div id="energyText" style="font-size:12px;text-align:center;font-weight:800"></div>
      </div>
      <div id="message" style="position:absolute;z-index:3;left:50%;top:21%;transform:translate(-50%,-50%);font-size:clamp(23px,5vw,42px);font-weight:900;color:#ffd166;text-shadow:0 3px 8px #000;pointer-events:none;white-space:nowrap"></div>
      <div id="result" style="display:none;position:absolute;z-index:4;inset:0;background:#020713dd;place-items:center;text-align:center;padding:20px"><div><h2 id="resultTitle" style="font-size:clamp(38px,7vw,62px);margin:0;color:#ef476f"></h2><p id="resultScore" style="font-size:25px"></p><button id="again" style="border:0;border-radius:12px;padding:14px 25px;background:#ffd166;color:#101827;font-weight:900;cursor:pointer">إعادة المحاولة</button></div></div>
      <div id="choices" style="display:none;position:absolute;z-index:5;inset:0;background:#020713e8;place-items:center;text-align:center;padding:18px"><div><h2 id="choiceTitle" style="color:#ffd166;font-size:31px;margin:0 0 10px"></h2><p>اختر ترقية للحي التالي</p><div style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap"><button data-up="battery">بطارية مطوّرة<br><small>طاقة +25</small></button><button data-up="dash">اندفاع اقتصادي<br><small>تكلفة -6</small></button><button data-up="shield">درع نجدة<br><small>ضربة إضافية</small></button></div></div></div>
    </div>
    <div style="display:flex;justify-content:center;gap:18px;flex-wrap:wrap;margin-top:9px;color:#c9d9e8;font-size:14px"><span>الحركة: WASD / الأسهم / السحب</span><span>الاندفاع: Space أو نقرة</span><span>الدائرة الزرقاء تستعيد الطاقة</span></div>
  </div>`;
  shell.querySelectorAll<HTMLButtonElement>("[data-up]").forEach(b => b.style.cssText = "padding:15px;border:0;border-radius:12px;background:#55d6ff;color:#07111d;font-weight:900;cursor:pointer");
  const disposeRender = render(shell, root);
  const stage = shell.querySelector<HTMLElement>("#stage")!;
  const restart = shell.querySelector<HTMLButtonElement>("#restart")!;
  const again = shell.querySelector<HTMLButtonElement>("#again")!;
  const choices = shell.querySelector<HTMLElement>("#choices")!;
  const result = shell.querySelector<HTMLElement>("#result")!;
  const progress = shell.querySelector<HTMLElement>("#progress")!;
  const clock = shell.querySelector<HTMLElement>("#clock")!;
  const energyBar = shell.querySelector<HTMLElement>("#energy")!;
  const energyText = shell.querySelector<HTMLElement>("#energyText")!;
  const messageEl = shell.querySelector<HTMLElement>("#message")!;

  const renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.outputColorSpace = THREE.SRGBColorSpace;
  renderer.domElement.style.cssText = "width:100%;height:100%;display:block;touch-action:none";
  stage.prepend(renderer.domElement);
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x071426);
  scene.fog = new THREE.Fog(0x071426, 28, 48);
  const camera = new THREE.PerspectiveCamera(46, 1, .1, 100);
  camera.position.set(0, 25, 24); camera.lookAt(0, 0, 0);
  scene.add(new THREE.HemisphereLight(0x9bdcff, 0x182238, 2.2));
  const sun = new THREE.DirectionalLight(0xffe6bd, 3.2); sun.position.set(-10, 20, 12); sun.castShadow = true; sun.shadow.mapSize.set(1024, 1024); scene.add(sun);
  const world = new THREE.Group(); scene.add(world);
  const dynamic = new THREE.Group(); scene.add(dynamic);
  const geo: THREE.BufferGeometry[] = [], mats: THREE.Material[] = [];
  const mat = (color:number, emissive=0) => { const m=new THREE.MeshStandardMaterial({color,emissive,roughness:.72,metalness:.08});mats.push(m);return m; };
  const box=(x:number,y:number,z:number,m:THREE.Material)=>{const g=new THREE.BoxGeometry(x,y,z);geo.push(g);return new THREE.Mesh(g,m)};
  const cylinder=(r:number,h:number,m:THREE.Material,n=16)=>{const g=new THREE.CylinderGeometry(r,r,h,n);geo.push(g);return new THREE.Mesh(g,m)};
  const groundMat=mat(0x142a3d), roadMat=mat(0x17202c), buildingMats=[mat(0x31506b),mat(0x59384b),mat(0x343864)];
  const ground=box(30,.4,22,groundMat);ground.position.y=-.25;ground.receiveShadow=true;world.add(ground);
  for(let i=-12;i<=12;i+=6){const road=box(2.3,.08,22,roadMat);road.position.set(i,0,0);world.add(road)}
  for(let z=-8;z<=8;z+=5.4) for(let x=-10;x<=10;x+=4.8){if(Math.abs(x)%6<1.4)continue;const h=2.2+Math.random()*4;const b=box(2.7,h,3.1,buildingMats[Math.floor(Math.random()*3)]);b.position.set(x,h/2,z);b.castShadow=b.receiveShadow=true;world.add(b);}
  const padMat=mat(0x17677a,0x0a6078);const pad=cylinder(1.7,.12,padMat,32);pad.position.set(-12,.08,8);world.add(pad);
  const ringGeo=new THREE.TorusGeometry(1.75,.08,8,36);geo.push(ringGeo);const ring=new THREE.Mesh(ringGeo,mat(0x55d6ff,0x55d6ff));ring.rotation.x=Math.PI/2;ring.position.set(-12,.18,8);world.add(ring);

  type Civ={mesh:THREE.Group;life:number}; type Hazard={mesh:THREE.Object3D;r:number}; type Thug={mesh:THREE.Group;stun:number};
  const districts=[{name:"حي الميناء",goal:6,limit:42},{name:"الحي الصناعي",goal:8,limit:45},{name:"قلب المدينة",goal:10,limit:48}];
  const hero=new THREE.Group();
  const body=box(.85,1.25,.7,mat(0xffd166));body.position.y=.9;body.castShadow=true;hero.add(body);
  const head=cylinder(.36,.55,mat(0xef476f),18);head.position.y=1.75;hero.add(head);
  const cape=box(.72,.9,.12,mat(0xef476f));cape.position.set(0,.88,.43);cape.rotation.x=-.22;hero.add(cape);
  const auraGeo=new THREE.TorusGeometry(.9,.08,8,24);geo.push(auraGeo);const aura=new THREE.Mesh(auraGeo,mat(0x6fffe9,0x6fffe9));aura.rotation.x=Math.PI/2;aura.position.y=.1;aura.visible=false;hero.add(aura);dynamic.add(hero);
  let civs:Civ[]=[], hazards:Hazard[]=[], thugs:Thug[]=[];
  let district=0,rescued=0,fallen=0,score=0,timer=42,spawn=0,dashCost=18,maxEnergy=100,energy=100,shield=0,dashTime=0,inv=0;
  let state:"play"|"upgrade"|"win"|"lose"="play",message="",messageTime=0,raf=0,last=performance.now(),pointer:THREE.Vector2|null=null,pointerStart:THREE.Vector2|null=null;
  const velocity=new THREE.Vector3(), keys=new Set<string>(); let audio:AudioContext|null=null;
  function sound(f:number,d=.15){try{audio ||= new AudioContext();audio.resume();const o=audio.createOscillator(),g=audio.createGain();o.frequency.value=f;g.gain.setValueAtTime(.04,audio.currentTime);g.gain.exponentialRampToValueAtTime(.001,audio.currentTime+d);o.connect(g).connect(audio.destination);o.start();o.stop(audio.currentTime+d)}catch{}}
  function clearEntities(){for(const c of civs)dynamic.remove(c.mesh);for(const h of hazards)dynamic.remove(h.mesh);for(const t of thugs)dynamic.remove(t.mesh);civs=[];hazards=[];thugs=[];}
  function person(color:number){const g=new THREE.Group(), torso=box(.55,.85,.45,mat(color)), head=cylinder(.24,.38,mat(0xffd2ad),14);torso.position.y=.55;head.position.y=1.22;g.add(torso,head);return g;}
  function createHazards(){for(let i=0;i<3+district*2;i++){const fire=i%2===0;let m:THREE.Object3D;if(fire){m=cylinder(.65,.8,mat(0xff5a24,0xaa1800),10);m.position.y=.4}else{m=box(1.3,.75,1.1,mat(0x657180));m.position.y=.38;m.rotation.y=Math.random()*3}m.position.x=-10+Math.random()*20;m.position.z=-7+Math.random()*14;dynamic.add(m);hazards.push({mesh:m,r:.95})}for(let i=0;i<district+1;i++){const m=person(0x9b5de5);m.position.set(-10+Math.random()*20,0,-7+Math.random()*14);dynamic.add(m);thugs.push({mesh:m,stun:0})}}
  function begin(){clearEntities();rescued=fallen=0;timer=districts[district].limit;spawn=.3;energy=maxEnergy;hero.position.set(0,0,8);velocity.set(0,0,0);inv=1;state="play";choices.style.display="none";result.style.display="none";message=districts[district].name;messageTime=2;createHazards();last=performance.now()}
  function reset(){district=0;score=0;dashCost=18;maxEnergy=100;shield=0;keys.clear();begin()}
  function doDash(){if(state!=="play"||dashTime>0||energy<dashCost)return;energy-=dashCost;dashTime=.24;if(velocity.length()<1)velocity.z=-18;else velocity.setLength(18);sound(180,.12)}
  function hit(){if(inv>0)return;if(shield>0){shield--;message="الدرع امتص الضربة!"}else{energy-=24;message="إصابة!"}messageTime=1;inv=1.2;sound(90,.28)}
  function spawnCiv(){const m=person(0x06d6a0),edge=Math.floor(Math.random()*4);m.position.set(edge<2?-13+Math.random()*26:edge===2?-13:13,0,edge<2?(edge?-9:9):-8+Math.random()*16);dynamic.add(m);civs.push({mesh:m,life:10-district});}
  function finish(){if(district===districts.length-1){state="win";result.style.display="grid";(shell.querySelector("#resultTitle") as HTMLElement).textContent="تم إنقاذ المدينة!";sound(700,.6)}else{state="upgrade";choices.style.display="grid";(shell.querySelector("#choiceTitle") as HTMLElement).textContent=`تم تأمين ${districts[district].name}!`;sound(560,.35)}}
  function choose(e:Event){const up=(e.currentTarget as HTMLElement).dataset.up;if(up==="battery")maxEnergy+=25;if(up==="dash")dashCost=Math.max(7,dashCost-6);if(up==="shield")shield++;district++;begin()}
  function lose(){state="lose";result.style.display="grid";(shell.querySelector("#resultTitle") as HTMLElement).textContent="فشلت المهمة";(shell.querySelector("#resultScore") as HTMLElement).textContent=`النتيجة: ${score}`;sound(75,.5)}
  function update(dt:number){messageTime-=dt;if(state!=="play")return;timer-=dt;spawn-=dt;dashTime-=dt;inv-=dt;let x=+(keys.has("ArrowRight")||keys.has("KeyD"))-+(keys.has("ArrowLeft")||keys.has("KeyA")),z=+(keys.has("ArrowDown")||keys.has("KeyS"))-+(keys.has("ArrowUp")||keys.has("KeyW"));if(pointer){x=pointer.x;z=pointer.y}const dir=new THREE.Vector3(x,0,z);if(dir.lengthSq())dir.normalize();const speed=dashTime>0?18:7.3;velocity.lerp(dir.multiplyScalar(speed),Math.min(1,dt*10));hero.position.addScaledVector(velocity,dt);hero.position.x=THREE.MathUtils.clamp(hero.position.x,-14,14);hero.position.z=THREE.MathUtils.clamp(hero.position.z,-10,10);if(velocity.lengthSq()>.1)hero.rotation.y=Math.atan2(velocity.x,velocity.z);aura.visible=dashTime>0;aura.rotation.z+=dt*7;const resting=hero.position.distanceTo(new THREE.Vector3(-12,0,8))<1.8;energy=THREE.MathUtils.clamp(energy+dt*(resting?25:dir.lengthSq()? -3.5:-1),0,maxEnergy);if(spawn<=0&&civs.length<5){spawn=1.45-district*.15;spawnCiv()}for(let i=civs.length-1;i>=0;i--){const c=civs[i];c.life-=dt;c.mesh.lookAt(0,c.mesh.position.y,0);c.mesh.position.addScaledVector(new THREE.Vector3().subVectors(new THREE.Vector3(0,0,0),c.mesh.position).normalize(),dt*.45);if(c.mesh.position.distanceTo(hero.position)<(dashTime>0?1.8:1.05)){dynamic.remove(c.mesh);civs.splice(i,1);rescued++;score+=100+Math.ceil(timer)*3;energy=Math.min(maxEnergy,energy+8);sound(470+rescued*18);continue}if(c.life<=0){dynamic.remove(c.mesh);civs.splice(i,1);fallen++;sound(100,.25)}}for(const h of hazards){if(h.mesh.position.distanceTo(hero.position)<h.r+0.45)hit();if((h.mesh as THREE.Mesh).geometry instanceof THREE.CylinderGeometry)h.mesh.scale.y=.8+Math.sin(performance.now()*.01+h.mesh.position.x)*.2}for(const t of thugs){if(t.stun>0){t.stun-=dt;continue}const d=new THREE.Vector3().subVectors(hero.position,t.mesh.position);d.y=0;t.mesh.position.addScaledVector(d.normalize(),dt*(1.3+district*.3));t.mesh.lookAt(hero.position.x,0,hero.position.z);if(t.mesh.position.distanceTo(hero.position)<(dashTime>0?1.7:.85)){if(dashTime>0){t.stun=2;t.mesh.position.addScaledVector(d,-2);score+=40;sound(260)}else hit()}}if(rescued>=districts[district].goal)finish();else if(timer<=0||fallen>=3||energy<=0)lose()}
  function draw(){const d=districts[district];progress.textContent=`${d.name} • الإنقاذ ${rescued}/${d.goal} • النقاط ${score}`;clock.textContent=`⏱ ${Math.max(0,Math.ceil(timer))} • سقوط ${fallen}/3`;energyBar.style.width=`${100*energy/maxEnergy}%`;energyBar.style.background=energy>maxEnergy*.3?"#06d6a0":"#ef476f";energyText.textContent=`الطاقة ${Math.ceil(energy)}/${maxEnergy}${shield?` • درع ${shield}`:""}`;messageEl.textContent=messageTime>0?message:"";hero.visible=!(inv>0&&Math.floor(inv*12)%2===0);camera.position.x+=(hero.position.x*.17-camera.position.x)*.04;camera.lookAt(hero.position.x*.16,0,0);renderer.render(scene,camera)}
  function resize(){const r=stage.getBoundingClientRect();renderer.setSize(r.width,r.height,false);camera.aspect=r.width/r.height;camera.updateProjectionMatrix()}
  function keyDown(e:KeyboardEvent){keys.add(e.code);if(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space"].includes(e.code))e.preventDefault();if(e.code==="Space"&&!e.repeat)doDash();if(e.code==="KeyR")reset()}
  const keyUp=(e:KeyboardEvent)=>keys.delete(e.code);
  function pDown(e:PointerEvent){pointerStart=new THREE.Vector2(e.clientX,e.clientY);pointer=new THREE.Vector2();renderer.domElement.setPointerCapture(e.pointerId)}
  function pMove(e:PointerEvent){if(!pointer||!pointerStart)return;pointer.set(e.clientX-pointerStart.x,e.clientY-pointerStart.y);if(pointer.length()>12)pointer.normalize();else pointer.set(0,0)}
  function pUp(){if(pointer&&pointer.length()<.2)doDash();pointer=null;pointerStart=null}
  function frame(now:number){const dt=Math.min(.033,(now-last)/1000);last=now;update(dt);draw();raf=requestAnimationFrame(frame)}
  addEventListener("keydown",keyDown);addEventListener("keyup",keyUp);addEventListener("resize",resize);restart.addEventListener("click",reset);again.addEventListener("click",reset);renderer.domElement.addEventListener("pointerdown",pDown);renderer.domElement.addEventListener("pointermove",pMove);renderer.domElement.addEventListener("pointerup",pUp);renderer.domElement.addEventListener("pointercancel",pUp);shell.querySelectorAll<HTMLElement>("[data-up]").forEach(b=>b.addEventListener("click",choose));
  resize();reset();raf=requestAnimationFrame(frame);
  return()=>{cancelAnimationFrame(raf);removeEventListener("keydown",keyDown);removeEventListener("keyup",keyUp);removeEventListener("resize",resize);restart.removeEventListener("click",reset);again.removeEventListener("click",reset);renderer.domElement.removeEventListener("pointerdown",pDown);renderer.domElement.removeEventListener("pointermove",pMove);renderer.domElement.removeEventListener("pointerup",pUp);renderer.domElement.removeEventListener("pointercancel",pUp);shell.querySelectorAll<HTMLElement>("[data-up]").forEach(b=>b.removeEventListener("click",choose));geo.forEach(g=>g.dispose());mats.forEach(m=>m.dispose());renderer.dispose();if(audio)audio.close();if(typeof disposeRender==="function")disposeRender();else shell.remove()};
}