"use client";
import {useRef,useState} from 'react';
import {MousePointer2,Plus,Cable,Check,X,Trash2,Undo2,Redo2,Settings2} from 'lucide-react';
import {toast} from 'sonner';
import {Plan,Point,siteKinds,siteLabels,uid} from '@/lib/plan';
import {SiteNode,SiteRoute,sitePoints,siteLength,nodeHeight} from '@/lib/geometry';
import {Choice,Field} from './plan-controls';
type Selection={type:'node'|'route'|'building';id:string}|null;
const fmt=(n:number)=>n.toLocaleString('hu-HU',{maximumFractionDigits:2});
export function PlotEditor({plan,change,buildingId,onBuilding,undo,redo,canUndo,canRedo}:{plan:Plan;change:(fn:(p:Plan)=>void)=>void;buildingId:string;onBuilding:(id:string)=>void;undo:()=>void;redo:()=>void;canUndo:boolean;canRedo:boolean}){
 const [tool,setTool]=useState('select'),[kind,setKind]=useState<SiteNode['kind']>('supply'),[selection,setSelection]=useState<Selection>(null),[from,setFrom]=useState(''),[to,setTo]=useState(''),[via,setVia]=useState<Point[]>([]),[cursor,setCursor]=useState<Point|null>(null),[preview,setPreview]=useState<Plan|null>(null),[panel,setPanel]=useState(false);
 const svg=useRef<SVGSVGElement>(null),drag=useRef<{selection:NonNullable<Selection>;start:Point;handle?:number}|null>(null);
 const shown=preview||plan,scale=Math.min(840/plan.plot.w,560/plan.plot.h),a=plan.plot.nodes.some(n=>n.id===from)?from:plan.plot.nodes[0]?.id||'',b=plan.plot.nodes.some(n=>n.id===to&&n.id!==a)?to:plan.plot.nodes.find(n=>n.id!==a)?.id||'';
 const selectedNode=plan.plot.nodes.find(n=>selection?.type==='node'&&n.id===selection.id),selectedRoute=plan.plot.routes.find(r=>selection?.type==='route'&&r.id===selection.id),building=plan.buildings.find(b=>b.id===(selection?.type==='building'?selection.id:buildingId))||plan.buildings[0];
 const point=(e:React.PointerEvent):Point=>{const p=svg.current!.createSVGPoint();p.x=e.clientX;p.y=e.clientY;const q=p.matrixTransform(svg.current!.getScreenCTM()!.inverse());return{x:Math.max(0,Math.min(plan.plot.w,Math.round((q.x-70)/scale*10)/10)),y:Math.max(0,Math.min(plan.plot.h,Math.round((q.y-70)/scale*10)/10))}};
 function pick(e:React.PointerEvent,s:NonNullable<Selection>,handle?:number){if(tool!=='select')return;e.stopPropagation();setSelection(s);setPanel(true);drag.current={selection:s,start:point(e),handle};svg.current!.setPointerCapture(e.pointerId);if(s.type==='building')onBuilding(s.id)}
 function moved(p:Point){const d=drag.current!;const next=structuredClone(plan);const dx=p.x-d.start.x,dy=p.y-d.start.y;const shift=(p:Point)=>({x:Math.max(0,Math.min(plan.plot.w,p.x+dx)),y:Math.max(0,Math.min(plan.plot.h,p.y+dy))});if(d.selection.type==='node'){const n=next.plot.nodes.find(n=>n.id===d.selection.id)!;Object.assign(n,shift(n))}if(d.selection.type==='building'){const n=next.buildings.find(n=>n.id===d.selection.id)!;Object.assign(n,shift(n));n.x=Math.min(n.x,Math.max(0,plan.plot.w-n.w));n.y=Math.min(n.y,Math.max(0,plan.plot.h-n.h))}if(d.selection.type==='route'){const r=next.plot.routes.find(r=>r.id===d.selection.id)!;r.via=r.via.map((v,i)=>d.handle===undefined||d.handle===i?shift(v):v)}return next}
 function down(e:React.PointerEvent){const p=point(e);if(tool==='point'){const id=uid();change(next=>next.plot.nodes.push({id,name:siteLabels[kind]+' '+(plan.plot.nodes.length+1),kind,...p,height:kind==='supply'?0:1.5}));setSelection({type:'node',id});setPanel(true)}else if(tool==='draw')setVia(v=>[...v,p]);else setSelection(null)}
 function move(e:React.PointerEvent){const p=point(e);setCursor(p);if(drag.current)setPreview(moved(p))}
 function up(e:React.PointerEvent){if(drag.current){const next=moved(point(e));if(JSON.stringify(next)!==JSON.stringify(plan))change(p=>Object.assign(p,next));drag.current=null;setPreview(null);if(svg.current?.hasPointerCapture(e.pointerId))svg.current.releasePointerCapture(e.pointerId)}}
 function connect(direct=false){if(!a||!b||a===b||!plan.plot.nodes.some(n=>n.id===a)||!plan.plot.nodes.some(n=>n.id===b)){toast.error('Válassz két különböző pontot.');return}const id=uid();change(p=>p.plot.routes.push({id,name:'Telki nyomvonal '+(p.plot.routes.length+1),from:a,to:b,via:direct?[]:via,mode:'underground',level:-.7,cable:'5 × 10 mm²'}));setVia([]);setTool('select');setSelection({type:'route',id});setPanel(true)}
 function nodePatch(key:string,value:unknown){change(p=>Object.assign(p.plot.nodes.find(n=>n.id===selectedNode!.id)!,{[key]:value}))}
 function routePatch(key:string,value:unknown){change(p=>Object.assign(p.plot.routes.find(r=>r.id===selectedRoute!.id)!,{[key]:value}))}
 const options=plan.plot.nodes.map(n=>[n.id,n.name] as [string,string]);
 const deviceOptions:[string,string][]=[['','Önálló telki pont'],...plan.buildings.flatMap(b=>b.floors.flatMap(f=>f.devices.filter(d=>d.kind==='panel').map(d=>[d.id,b.name+' / '+f.name+' / '+d.name] as [string,string])))];
 const draft:SiteRoute={id:'draft',name:'',from:a,to:b,via:[...via,...(cursor?[cursor]:[])],level:-.7,mode:'underground',cable:''};
 return <div className="plot-editor"><div className="toolbar"><button className={tool==='select'?'active':''} onClick={()=>{setTool('select');setVia([])}} title="Kijelölés és mozgatás"><MousePointer2/> Kijelölés</button><button className={tool==='point'?'active':''} onClick={()=>setTool('point')}><Plus/> Pont elhelyezése</button><button className={tool==='connections'||tool==='draw'?'active':''} onClick={()=>setTool('connections')}><Cable/> Összekötés</button><div className="toolbar-spacer"/><button aria-label="Telki visszavonás" disabled={!canUndo} onClick={undo}><Undo2/></button><button aria-label="Telki újra" disabled={!canRedo} onClick={redo}><Redo2/></button><button className="plot-properties-toggle" aria-label="Telki tulajdonságok" onClick={()=>setPanel(!panel)}><Settings2/></button></div>
 {tool==='point'&&<div className="contextbar"><Choice label="Pont típusa" value={kind} onChange={v=>setKind(v as SiteNode['kind'])} items={siteKinds.map(k=>[k,siteLabels[k]])}/><p>Kattints a telken a kívánt helyre.</p></div>}
 {(tool==='connections'||tool==='draw')&&<div className="contextbar"><Choice label="Kezdőpont" value={a} onChange={setFrom} items={options.length?options:[['','Előbb helyezz el pontokat']]}/><Choice label="Végpont" value={b} onChange={setTo} items={options.filter(([id])=>id!==a).length?options.filter(([id])=>id!==a):[['','Nincs másik pont']]}/>{tool==='connections'?<><button disabled={!a||!b||a===b} onClick={()=>connect(true)}>Közvetlen kötés</button><button disabled={!a||!b||a===b} onClick={()=>{setVia([]);setTool('draw')}}>Töréspontok rajzolása</button></>:<><button onClick={()=>connect()}><Check/> Befejezés</button><button onClick={()=>{setVia([]);setTool('connections')}}><X/> Mégse</button></>}</div>}
 <div className="plot-body"><div className="plot-main"><div className="canvas"><svg ref={svg} viewBox="0 0 1000 720" aria-label="Telki villamos hálózat" onPointerDown={down} onPointerMove={move} onPointerUp={up} onPointerCancel={()=>{drag.current=null;setPreview(null)}} style={{touchAction:'none',cursor:tool==='select'?'default':'crosshair'}}><rect width="1000" height="720" fill="var(--plan-bg,#f4f7f9)"/><g transform={'translate(70 70) scale('+scale+')'}><rect width={plan.plot.w} height={plan.plot.h} fill="var(--plot-fill,#edf4ef)" stroke="#90b3a3" strokeWidth={1/scale} strokeDasharray={6/scale+' '+4/scale}/>
 {shown.buildings.map(b=><g key={b.id} onPointerDown={e=>pick(e,{type:'building',id:b.id})} style={{cursor:'grab'}}><rect x={b.x} y={b.y} width={b.w} height={b.h} fill={b.id===building.id?'var(--plan-selection,#e0eee7)':'var(--plan-room,#fff)'} stroke="#82969d" strokeWidth={2/scale}/><text x={b.x+b.w/2} y={b.y+b.h/2} fontSize={15/scale} fill="var(--foreground)" textAnchor="middle">{b.name}</text><text x={b.x+b.w/2} y={b.y+b.h/2+22/scale} fontSize={12/scale} fill="var(--muted-foreground)" textAnchor="middle">{b.floors.length} szint</text></g>)}
 {shown.plot.routes.map(r=><g key={r.id} onPointerDown={e=>pick(e,{type:'route',id:r.id})}><polyline points={sitePoints(r,shown).map(p=>p.x+','+p.y).join(' ')} fill="none" stroke="transparent" strokeWidth={18/scale}/><polyline points={sitePoints(r,shown).map(p=>p.x+','+p.y).join(' ')} fill="none" stroke={selection?.id===r.id?'#329e87':r.mode==='underground'?'#be7435':'#5285b2'} strokeWidth={3/scale} strokeDasharray={r.mode==='underground'?7/scale+' '+5/scale:undefined}/>{selection?.id===r.id&&r.via.map((p,i)=><circle key={i} cx={p.x} cy={p.y} r={6/scale} fill="#fff" stroke="#256459" strokeWidth={2/scale} onPointerDown={e=>pick(e,{type:'route',id:r.id},i)}/>)}</g>)}
 {tool==='draw'&&<polyline points={sitePoints(draft,shown).map(p=>p.x+','+p.y).join(' ')} fill="none" stroke="#258574" strokeWidth={2/scale} strokeDasharray={5/scale+' '+5/scale}/>}
 {shown.plot.nodes.map((n,i)=><g key={n.id} transform={'translate('+n.x+' '+n.y+')'} onPointerDown={e=>pick(e,{type:'node',id:n.id})} style={{cursor:'grab'}}><rect x={-13/scale} y={-13/scale} width={26/scale} height={26/scale} rx={4/scale} fill={selection?.id===n.id?'#d7ede5':'#fff'} stroke={n.kind==='supply'?'#be7435':'#256459'} strokeWidth={2/scale}/><text y={5/scale} textAnchor="middle" fontSize={13/scale} fill="#263b49">{['B','M','F','L','A'][siteKinds.indexOf(n.kind)]}</text><text x={18/scale} y={-5/scale} fontSize={13/scale} fill="var(--foreground)">{i+1}. {n.name}</text><text x={18/scale} y={12/scale} fontSize={11/scale} fill="var(--muted-foreground)">{fmt(nodeHeight(n,shown))} m</text></g>)}
 <text x={plan.plot.w/2} y={-15/scale} textAnchor="middle" fontSize={14/scale} fill="var(--muted-foreground)">{fmt(plan.plot.w)} m</text></g></svg><div className="canvas-caption">{tool==='draw'?'Jelöld a töréspontokat, majd kattints a Befejezés gombra.':'A pontok és épületek húzhatók. A kötés követi a végpontok helyét.'}</div></div><footer className="statusbar"><span>{plan.plot.nodes.length} pont · {plan.plot.routes.length} nyomvonal</span><span>Összesen {fmt(plan.plot.routes.reduce((s,r)=>s+siteLength(r,plan).total,0))} m · függőleges szakaszokkal</span></footer></div>
 <aside className={'plot-inspector '+(panel?'opened':'')}><button className="plot-properties-toggle iconbutton" onClick={()=>setPanel(false)} aria-label="Telki tulajdonságok bezárása"><X/></button><h2>{selectedNode?'Hálózati pont':selectedRoute?'Telki nyomvonal':'Telek és épület'}</h2>
 {selectedNode?<><Field label="Pont neve" value={selectedNode.name} onChange={v=>nodePatch('name',v)}/><Choice label="Pont típusa" value={selectedNode.kind} onChange={v=>nodePatch('kind',v)} items={siteKinds.map(k=>[k,siteLabels[k]])}/><div className="pair">{(['x','y'] as const).map(k=><Field key={k} label={k.toUpperCase()+' (m)'} type="number" min={0} step={.1} max={k==='x'?plan.plot.w:plan.plot.h} value={+selectedNode[k].toFixed(2)} onChange={v=>nodePatch(k,Math.max(0,Math.min(k==='x'?plan.plot.w:plan.plot.h,+v)))}/>)}</div><Choice label="Kapcsolódó alaprajzi elosztó" value={selectedNode.deviceId||''} onChange={v=>nodePatch('deviceId',v)} items={deviceOptions}/>{selectedNode.deviceId?<p>Kapcsolt magasság: <b>{fmt(nodeHeight(selectedNode,plan))} m</b>, a szintmagasság és a beépítési magasság összege.</p>:<Field label="Magasság a telek 0 szintjéhez (m)" type="number" step={.1} min={-30} max={110} value={selectedNode.height} onChange={v=>nodePatch('height',Math.max(-30,Math.min(110,+v)))}/>}<button className="danger" onClick={()=>{change(p=>{p.plot.routes=p.plot.routes.filter(r=>r.from!==selectedNode.id&&r.to!==selectedNode.id);p.plot.nodes=p.plot.nodes.filter(n=>n.id!==selectedNode.id)});setSelection(null)}}><Trash2/> Pont és kötései törlése</button></>:selectedRoute?<><Field label="Nyomvonal neve" value={selectedRoute.name} onChange={v=>routePatch('name',v)}/><Choice label="Kezdőpont" value={selectedRoute.from} onChange={v=>routePatch('from',v)} items={options.filter(([id])=>id!==selectedRoute.to)}/><Choice label="Végpont" value={selectedRoute.to} onChange={v=>routePatch('to',v)} items={options.filter(([id])=>id!==selectedRoute.from)}/><Choice label="Vezetés módja" value={selectedRoute.mode} onChange={v=>routePatch('mode',v)} items={[["underground","Föld alatt"],["surface","Felszínen / falon"],["overhead","Magasban"]]}/><Field label="Nyomvonal magassága (m)" type="number" min={-30} max={100} step={.1} value={selectedRoute.level} onChange={v=>routePatch('level',Math.max(-30,Math.min(100,+v)))}/><p>Negatív érték = mélység. A pontok magassága ugyanahhoz a telek-0 szinthez viszonyul.</p><Field label="Kábel jelölése" value={selectedRoute.cable} onChange={v=>routePatch('cable',v)}/><LengthDetails values={siteLength(selectedRoute,plan)}/><h3>Töréspontok</h3>{selectedRoute.via.map((v,i)=><div className="bend-row" key={i}><Field label={(i+1)+'. X (m)'} value={+v.x.toFixed(2)} type="number" min={0} step={.1} onChange={x=>routePatch('via',selectedRoute.via.map((p,j)=>j===i?{...p,x:Math.max(0,Math.min(plan.plot.w,+x))}:p))}/><Field label={(i+1)+'. Y (m)'} value={+v.y.toFixed(2)} type="number" min={0} step={.1} onChange={y=>routePatch('via',selectedRoute.via.map((p,j)=>j===i?{...p,y:Math.max(0,Math.min(plan.plot.h,+y))}:p))}/><button aria-label={'Töréspont törlése '+(i+1)} onClick={()=>routePatch('via',selectedRoute.via.filter((_,j)=>i!==j))}><X/></button></div>)}<button onClick={()=>{const pts=sitePoints(selectedRoute,plan),p=pts[pts.length-2],q=pts[pts.length-1];routePatch('via',[...selectedRoute.via,{x:(p.x+q.x)/2,y:(p.y+q.y)/2}])}}><Plus/> Töréspont hozzáadása</button><button className="danger" onClick={()=>{change(p=>{p.plot.routes=p.plot.routes.filter(r=>r.id!==selectedRoute.id)});setSelection(null)}}><Trash2/> Nyomvonal törlése</button></>:<><Field label="Telek neve" value={plan.plot.name} onChange={v=>change(p=>{p.plot.name=v})}/><div className="pair">{(['w','h'] as const).map((k,i)=><Field key={k} label={i?'Mélység (m)':'Szélesség (m)'} type="number" min={5} max={100} value={plan.plot[k]} onChange={v=>change(p=>{p.plot[k]=Math.max(5,Math.min(100,+v))})}/>)}</div><Field label="Épület neve" value={building.name} onChange={v=>change(p=>{p.buildings.find(b=>b.id===building.id)!.name=v})}/><div className="pair">{(['x','y','w','h'] as const).map((k,i)=><Field key={k} label={['X (m)','Y (m)','Szélesség (m)','Mélység (m)'][i]} value={+building[k].toFixed(2)} type="number" min={i<2?0:1} max={100} step={.1} onChange={v=>change(p=>{p.buildings.find(b=>b.id===building.id)![k]=Math.min(100,Math.max(i<2?0:1,+v))})}/>)}</div><p>A magasságok közös telekszinthez viszonyulnak. Az összekötéshez előbb helyezz el legalább két hálózati pontot.</p></>}
 </aside></div></div>
}
export function LengthDetails({values}:{values:{horizontal:number;vertical:number;total:number}}){return <div className="length-details"><div><span>Vízszintes nyomvonal</span><b>{fmt(values.horizontal)} m</b></div><div><span>Fel- és leállások</span><b>{fmt(values.vertical)} m</b></div><div className="length-total"><span>Teljes geometriai hossz</span><b>{fmt(values.total)} m</b></div><p>Ráhagyás nélkül; az egyes szakaszok egyszer számítanak.</p></div>}
