import { useEffect, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import {
  ArrowLeft, Undo2, Redo2, RotateCcw, Move, Maximize2, RotateCw, SlidersHorizontal,
  Eye, EyeOff, Copy, Trash2, Lock, Unlock, RefreshCw, Check
} from 'lucide-react';
import CoverViewer from '@/components/studio/CoverViewer';
import { useExperienceMode } from '@/lib/ExperienceMode';

const VIEW_MODES = [
  ['studio', 'Studio'], ['wireframe', 'Wireframe'], ['geometry', 'Geometry'],
  ['protected', 'Protected Zones'], ['decoration', 'Decoration Zones'], ['connector', 'Connector Clearance'], ['print', 'Print Preview']
];

const EFFECTS = [
  ['colour_texture', 'Colour', 'Looks printed on the surface.'],
  ['raised_emboss', 'Raised', 'Stands above the cover.'],
  ['engraving', 'Engraved', 'Pressed into the cover.'],
  ['stencil', 'Cut-out', 'Creates approved openings.'],
  ['sculpted_relief', 'Sculpted', 'Becomes a shaped 3D feature.'],
];

// Preview-only millimetre defaults. The Geometry Engine decides final values.
const INTENSITY_MM = {
  raised_emboss: { subtle: 0.6, standard: 1.2, bold: 2.0 },
  engraving: { subtle: 0.4, standard: 0.8, bold: 1.2 },
  sculpted_relief: { subtle: 0.5, standard: 1.0, bold: 1.6 },
  stencil: { subtle: 0.5, standard: 1.0, bold: 1.5 },
  colour_texture: { subtle: 0, standard: 0, bold: 0 }
};

export default function GuidedStudio({
  project, cover, layers, selected, assets, setSelected,
  liveUpdate, commitTransform, update, updateProject,
  duplicate, deleteLayer, replaceArtwork, assetFor,
  viewMode, setViewMode, modes, protectedVisible, toggleProtected, lockAspect, setLockAspect,
  navigate, opError, setOpError
}) {
  const { setMode } = useExperienceMode();
  const [tool, setTool] = useState('move');
  const [moreOpen, setMoreOpen] = useState(false);
  const [piecesOpen, setPiecesOpen] = useState(false);
  const [saved, setSaved] = useState('saved');

  const safeLayers = Array.isArray(layers) ? layers : [];
  const sel = selected;
  const hasArtwork = safeLayers.length > 0;
  const projectId = project?.id;

  const selRef = useRef(sel);
  useEffect(() => { selRef.current = sel; }, [sel]);
  const hist = useRef({ past: [], future: [] });
  const dragging = useRef(false);

  const snap = (l) => l ? {
    id: l.id, positionX: l.positionX || 0, positionY: l.positionY || 0,
    scaleX: l.scaleX ?? 1, scaleY: l.scaleY ?? 1, rotation: l.rotation || 0
  } : null;

  const pushHist = () => {
    const s = snap(selRef.current);
    if (s) { hist.current.future = []; hist.current.past.push(s); if (hist.current.past.length > 50) hist.current.past.shift(); }
  };

  // Persist a transform change (position/scale/rotation) and reflect save state.
  const persist = async (layer) => {
    setSaved('saving');
    try { await commitTransform(layer); setSaved('saved'); } catch { setSaved('error'); }
  };
  // Persist a non-transform field (mirror/opacity/visibility) via the layer update.
  const persistField = async (changes) => {
    setSaved('saving');
    try { await update?.(selRef.current, changes); setSaved('saved'); } catch { setSaved('error'); }
  };

  const applyNow = async (patch) => {
    if (!sel) return;
    pushHist();
    liveUpdate(sel, patch);
    await persist({ ...sel, ...patch });
  };

  const beginSlider = () => { if (!dragging.current) { pushHist(); dragging.current = true; } };
  const endSlider = async () => {
    if (!dragging.current) return;
    dragging.current = false;
    await persist(selRef.current);
  };

  const undo = async () => {
    const prev = hist.current.past.pop();
    if (!prev) return;
    const cur = snap(selRef.current); if (cur) hist.current.future.unshift(cur);
    liveUpdate(selRef.current, prev);
    await persist({ ...selRef.current, ...prev });
  };
  const redo = async () => {
    const nxt = hist.current.future.shift();
    if (!nxt) return;
    const cur = snap(selRef.current); if (cur) hist.current.past.push(cur);
    liveUpdate(selRef.current, nxt);
    await persist({ ...selRef.current, ...nxt });
  };
  const resetPlacement = () => applyNow({ positionX: 0, positionY: 0, scaleX: 1, scaleY: 1, rotation: 0 });

  const effect = project?.simpleEffectChoice || project?.applicationMode || 'colour_texture';
  const intensity = project?.simpleEffectIntensity || 'standard';
  const updateProjectSafe = async (patch) => {
    setSaved('saving'); try { await updateProject(patch); setSaved('saved'); } catch { setSaved('error'); }
  };
  const setEffect = (eff) => {
    const mm = INTENSITY_MM[eff]?.[intensity] ?? 0;
    const patch = { simpleEffectChoice: eff, applicationMode: eff };
    if (eff === 'raised_emboss' || eff === 'engraving' || eff === 'sculpted_relief' || eff === 'stencil') {
      const gs = { ...(project?.geometrySettings || {}) };
      if (eff === 'raised_emboss') gs.embossHeight = mm;
      if (eff === 'engraving') gs.engravingDepth = mm;
      patch.geometrySettings = gs;
    }
    updateProjectSafe(patch);
  };
  const setIntensity = (i) => {
    const eff = effect;
    const mm = INTENSITY_MM[eff]?.[i] ?? 0;
    const patch = { simpleEffectIntensity: i };
    const gs = { ...(project?.geometrySettings || {}) };
    if (eff === 'raised_emboss') gs.embossHeight = mm;
    if (eff === 'engraving') gs.engravingDepth = mm;
    patch.geometrySettings = gs;
    updateProjectSafe(patch);
  };

  const onReplace = (e) => { const f = e.target.files?.[0]; if (f) replaceArtwork?.(f); };

  const savedLabel = saved === 'saving' ? 'Saving…' : saved === 'error' ? 'Could not save' : 'Saved';

  return (
    <div className="flex h-[calc(100vh-176px)] min-h-[560px] flex-col gap-3">
      <div className="flex items-center gap-3">
        <button onClick={() => navigate('/history')} className="btn-ghost"><ArrowLeft size={16} /> Back</button>
        <div className="min-w-0">
          <p className="truncate font-heading text-base font-semibold text-white">{project?.name || 'Untitled design'}</p>
          <p className="text-[11px] text-slate-500">{savedLabel} · Preview placement</p>
        </div>
        <div className="ml-auto flex items-center gap-2">
          <button onClick={undo} disabled={!hist.current.past.length} className="icon-button" title="Undo"><Undo2 size={16} /></button>
          <button onClick={redo} disabled={!hist.current.future.length} className="icon-button" title="Redo"><Redo2 size={16} /></button>
          <button onClick={resetPlacement} disabled={!sel} className="icon-button" title="Reset position"><RotateCcw size={16} /></button>
        </div>
      </div>

      <div className="relative min-h-0 flex-1">
        <CoverViewer
          cover={cover} mode={viewMode} onModeChange={setViewMode} modes={modes || VIEW_MODES}
          visibleProtected={protectedVisible}
          layers={layers} assets={assets} selected={selected}
          lockAspect={lockAspect}
          onLiveTransform={liveUpdate} onCommitTransform={commitTransform} onSelectLayer={setSelected}
        />
        {!projectId && <EmptyNote title="No project selected" body="Choose a design from My Designs, or start a new one." actions={[{ label: 'Start a new design', to: '/new-project' }]} />}
        {projectId && !cover && <EmptyNote title="No cover selected" body="Choose a cover to continue." actions={[{ label: 'Choose a cover', to: '/new-project' }]} />}
        {projectId && cover && !hasArtwork && (
          <EmptyNote title="No design added" body="Upload a picture, add a drawing, or create a PromptForge concept."
            actions={[{ label: 'Use a picture', to: `/image-apply?project=${projectId}` }, { label: 'Use a drawing', to: `/sketch-3d?project=${projectId}` }, { label: 'Describe an idea', to: `/promptforge?project=${projectId}` }]} />
        )}
      </div>

      {sel && hasArtwork && (
        <div className="panel p-3">
          <div className="flex flex-wrap items-center gap-2">
            <button onClick={() => setTool('move')} className={`tool-button ${tool === 'move' ? 'active-tool' : ''}`}><Move size={15} /> Move</button>
            <button onClick={() => setTool('size')} className={`tool-button ${tool === 'size' ? 'active-tool' : ''}`}><Maximize2 size={15} /> Size</button>
            <button onClick={() => setTool('turn')} className={`tool-button ${tool === 'turn' ? 'active-tool' : ''}`}><RotateCw size={15} /> Turn</button>
            <div className="ml-auto">
              <button onClick={() => setMoreOpen(o => !o)} className="btn-secondary"><SlidersHorizontal size={15} /> More controls</button>
            </div>
          </div>

          {tool === 'move' && (
            <div className="mt-3 flex flex-wrap items-center gap-2 text-xs text-slate-400">
              <span>Drag the design to move it. Use arrow keys to nudge.</span>
              <button onClick={() => applyNow({ positionX: 0, positionY: 0 })} className="tool-button">Centre</button>
            </div>
          )}
          {tool === 'size' && (
            <div className="mt-3 space-y-2">
              <input type="range" min={0.2} max={2} step={0.02} value={Math.abs(sel.scaleX || 1)}
                onChange={(e) => { beginSlider(); const v = Number(e.target.value); liveUpdate(sel, { scaleX: v, scaleY: v }); }}
                onPointerUp={endSlider} onKeyUp={endSlider} onBlur={endSlider}
                className="w-full accent-cyan-400" aria-label="Size" />
              <div className="flex gap-2">
                {[['Small', 0.5], ['Medium', 1], ['Large', 1.5]].map(([l, v]) => (
                  <button key={l} onClick={() => applyNow({ scaleX: v, scaleY: v })} className="tool-button">{l}</button>
                ))}
              </div>
            </div>
          )}
          {tool === 'turn' && (
            <div className="mt-3 space-y-2">
              <input type="range" min={0} max={360} step={1} value={sel.rotation || 0}
                onChange={(e) => { beginSlider(); liveUpdate(sel, { rotation: Number(e.target.value) }); }}
                onPointerUp={endSlider} onKeyUp={endSlider} onBlur={endSlider}
                className="w-full accent-cyan-400" aria-label="Rotation" />
              <div className="flex flex-wrap gap-2">
                <button onClick={() => applyNow({ rotation: 0 })} className="tool-button">Straighten</button>
                {[90, 180, 270].map(d => <button key={d} onClick={() => applyNow({ rotation: d })} className="tool-button">{d}°</button>)}
              </div>
            </div>
          )}
        </div>
      )}

      {moreOpen && (
        <div className="panel max-h-[42vh] overflow-y-auto p-4">
          <div className="mb-3 flex items-center justify-between">
            <h3 className="text-sm font-semibold text-white">More controls</h3>
            <button onClick={() => setMoreOpen(false)} className="icon-button">✕</button>
          </div>

          <div className="grid gap-4 sm:grid-cols-2">
            <label className="flex items-center justify-between rounded-lg border border-white/10 bg-black/20 p-3 text-sm text-slate-300">
              <span>Mirror</span>
              <input type="checkbox" checked={!!sel?.mirrored} onChange={e => persistField({ mirrored: e.target.checked })} className="h-5 w-5 accent-cyan-400" />
            </label>
            <label className="block text-sm text-slate-300">
              <span className="mb-1 block">Opacity</span>
              <input type="range" min={0.1} max={1} step={0.05} value={sel?.opacity ?? 1}
                onChange={(e) => { beginSlider(); liveUpdate(sel, { opacity: Number(e.target.value) }); }}
                onPointerUp={async () => { dragging.current = false; await persistField({ opacity: selRef.current?.opacity }); }}
                onKeyUp={async () => { dragging.current = false; await persistField({ opacity: selRef.current?.opacity }); }}
                className="w-full accent-cyan-400" />
            </label>
          </div>

          <p className="mt-4 mb-2 text-xs font-semibold uppercase tracking-wider text-slate-500">3D effect</p>
          <div className="grid gap-2 sm:grid-cols-3">
            {EFFECTS.map(([k, l, d]) => {
              const needsEngine = k === 'stencil' || k === 'sculpted_relief';
              return (
                <button key={k} onClick={() => setEffect(k)} disabled={needsEngine} title={needsEngine ? 'Requires the real Geometry Engine' : ''}
                  className={`rounded-lg border p-3 text-left transition ${effect === k ? 'border-cyan-400/50 bg-cyan-400/[0.08]' : 'border-white/10 hover:border-white/25'} disabled:cursor-not-allowed disabled:opacity-50`}>
                  <span className="block text-sm font-semibold text-white">{l}</span>
                  <span className="mt-0.5 block text-[11px] leading-4 text-slate-400">{d}</span>
                  {needsEngine && <span className="sim-badge mt-1">Geometry Engine</span>}
                </button>
              );
            })}
          </div>
          <div className="mt-3 flex gap-2">
            {['subtle', 'standard', 'bold'].map(i => (
              <button key={i} onClick={() => setIntensity(i)} className={`tool-button capitalize ${intensity === i ? 'active-tool' : ''}`}>{i}</button>
            ))}
          </div>

          <p className="mt-4 mb-2 text-xs font-semibold uppercase tracking-wider text-slate-500">Design piece</p>
          <div className="flex flex-wrap gap-2">
            <button onClick={() => duplicate?.(sel)} className="tool-button"><Copy size={14} /> Duplicate</button>
            <button onClick={() => { if (confirm('Remove this design piece?')) deleteLayer?.(sel); }} className="tool-button"><Trash2 size={14} /> Remove</button>
            <label className="tool-button cursor-pointer"><RefreshCw size={14} /> Change image<input type="file" accept="image/*" onChange={onReplace} className="hidden" /></label>
            <button onClick={() => setPiecesOpen(o => !o)} className="tool-button">{piecesOpen ? 'Hide pieces' : 'Design pieces'}</button>
            <button onClick={() => setMode('advanced')} className="tool-button">Switch to Advanced Studio</button>
          </div>

          {piecesOpen && (
            <div className="mt-3 space-y-1.5">
              {safeLayers.map(l => (
                <div key={l.id} className="flex items-center gap-2 rounded-lg border border-white/10 bg-black/20 p-2 text-sm">
                  <button onClick={() => setSelected?.(l)} className={`min-w-0 flex-1 truncate text-left ${sel?.id === l.id ? 'text-cyan-200' : 'text-slate-200'}`}>{l.name}</button>
                  <button onClick={() => update?.(l, { visible: !l.visible })} className="icon-button h-8 w-8" title={l.visible ? 'Hide' : 'Show'}>{l.visible ? <Eye size={14} /> : <EyeOff size={14} />}</button>
                  <button onClick={() => update?.(l, { locked: !l.locked })} className="icon-button h-8 w-8" title={l.locked ? 'Unlock' : 'Lock'}>{l.locked ? <Lock size={14} /> : <Unlock size={14} />}</button>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      <div className="flex justify-end">
        <button disabled={!projectId || !cover || !hasArtwork} onClick={() => navigate(`/validation?project=${projectId}`)} className="btn-primary">
          <Check size={17} /> Looks good — check my design
        </button>
      </div>

      {opError && <div className="warning-box flex items-center justify-between"><span>{opError}</span><button onClick={() => setOpError?.(null)} className="ml-3 underline">Dismiss</button></div>}
    </div>
  );
}

function EmptyNote({ title, body, actions }) {
  return (
    <div className="absolute inset-0 grid place-items-center bg-black/55 p-4 backdrop-blur-sm">
      <div className="max-w-sm text-center">
        <h3 className="font-heading text-lg font-semibold text-white">{title}</h3>
        <p className="mt-1 text-sm text-slate-400">{body}</p>
        <div className="mt-4 flex flex-wrap justify-center gap-2">
          {(actions || []).map(a => <Link key={a.to} to={a.to} className={actions.indexOf(a) === 0 ? 'btn-primary' : 'btn-secondary'}>{a.label}</Link>)}
        </div>
      </div>
    </div>
  );
}