import { useEffect, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import { Loader2, Check, Sparkles, Box, ArrowRight } from 'lucide-react';
import { base44 } from '@/api/base44Client';
import { useExperienceMode } from '@/lib/ExperienceMode';
import { makeDemoPieces, uid, DEMO_SVGS, pieceToLayer } from '@/lib/canvasDemo';
import CanvasTopBar from '@/components/canvas/CanvasTopBar';
import CanvasWorkflowStrip, { STAGES } from '@/components/canvas/CanvasWorkflowStrip';
import CreateDesignPanel from '@/components/canvas/CreateDesignPanel';
import UniversalCanvas from '@/components/canvas/UniversalCanvas';
import DesignPiecesPanel from '@/components/canvas/DesignPiecesPanel';
import CanvasActionBar from '@/components/canvas/CanvasActionBar';
import CoverDrawer from '@/components/canvas/CoverDrawer';
import FitPreview from '@/components/canvas/FitPreview';
import CompareCovers from '@/components/canvas/CompareCovers';

const DEMO_COVERS = [
  { name: 'Lower Leg Standard', limbType: 'leg', side: 'right', version: '1', previewImageUrl: 'https://picsum.photos/seed/leg-standard/400/520', decorationZones: [{ u: 0.16, v: 0.2, w: 0.68, h: 0.58 }], protectedZones: [{ u: 0.5, v: 0.92, w: 0.2, h: 0.08 }], brandingZones: [{ u: 0.08, v: 0.9, w: 0.12, h: 0.06 }] },
  { name: 'Lower Leg Muscular', limbType: 'leg', side: 'right', version: '1', previewImageUrl: 'https://picsum.photos/seed/leg-muscular/400/520', decorationZones: [{ u: 0.18, v: 0.18, w: 0.64, h: 0.6 }], protectedZones: [{ u: 0.5, v: 0.93, w: 0.2, h: 0.07 }], brandingZones: [{ u: 0.08, v: 0.9, w: 0.12, h: 0.06 }] },
  { name: 'Lower Leg Armour', limbType: 'leg', side: 'right', version: '1', previewImageUrl: 'https://picsum.photos/seed/leg-armour/400/520', decorationZones: [{ u: 0.2, v: 0.22, w: 0.6, h: 0.54 }], protectedZones: [{ u: 0.5, v: 0.92, w: 0.2, h: 0.08 }], brandingZones: [{ u: 0.1, v: 0.88, w: 0.12, h: 0.06 }] },
  { name: 'Arm Cover Standard', limbType: 'arm', side: 'right', version: '1', previewImageUrl: 'https://picsum.photos/seed/arm-standard/400/520', decorationZones: [{ u: 0.22, v: 0.22, w: 0.56, h: 0.5 }], protectedZones: [{ u: 0.5, v: 0.9, w: 0.2, h: 0.08 }], brandingZones: [{ u: 0.1, v: 0.88, w: 0.12, h: 0.06 }] }
];

const stageIdx = (s) => STAGES.findIndex(x => x[0] === s);

export default function UniversalDesignCanvas() {
  const { mode } = useExperienceMode();
  const advanced = mode === 'advanced';

  const [stage, setStage] = useState('create');
  const [design, setDesign] = useState({ name: 'Untitled Universal Design', sourceType: 'promptforge', character: 'Heroic', intendedApplicationMode: 'colour_texture', placementIntent: 'let_shire_choose', preferredIntensity: 'standard' });
  const [pieces, setPieces] = useState([]);
  const [focalId, setFocalId] = useState(null);
  const [selectedId, setSelectedId] = useState(null);
  const [past, setPast] = useState([]);
  const [future, setFuture] = useState([]);
  const [savedDesignId, setSavedDesignId] = useState(null);
  const [savedVersion, setSavedVersion] = useState(null);
  const [variantCreated, setVariantCreated] = useState(false);
  const [covers, setCovers] = useState([]);
  const [coversLoading, setCoversLoading] = useState(false);
  const [selectedCover, setSelectedCover] = useState(null);
  const [strategy, setStrategy] = useState('best_fit');
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [compareOpen, setCompareOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [busy, setBusy] = useState(false);
  const [me, setMe] = useState(null);

  const piecesRef = useRef(pieces); piecesRef.current = pieces;
  const snapshot = useRef(null);
  const dragging = useRef(false);

  useEffect(() => { base44.auth.me().then(setMe).catch(() => setMe(null)); }, []);

  const reached = (() => { let r = 0; if (pieces.length) r = 2; if (savedDesignId) r = 4; if (selectedCover) r = 5; if (variantCreated) r = 6; return r; })();

  const jump = (k) => { if (stageIdx(k) <= reached) setStage(k); };

  // ---- piece mutations ----
  const commit = (next) => { setPast(p => [...p, piecesRef.current].slice(-30)); setFuture([]); setPieces(Array.isArray(next) ? next : []); };
  const setLive = (next) => setPieces(Array.isArray(next) ? next : []);

  const addPiece = (data) => {
    const order = pieces.length ? Math.max(...pieces.map(p => p.order ?? 0)) + 1 : 0;
    const p = { id: uid(), cx: 0.5, cy: 0.45, w: 0.3, h: 0.3, rotation: 0, visible: true, locked: false, order, behaviour: 'keep_shape', placement: 'front_centre', effect: 'colour_texture', intensity: 'standard', mainColour: '#38e0f2', accentColour: '#a78bfa', backgroundColour: '#0b0f14', material: 'Matte', role: 'accent_detail', ...data };
    commit([...pieces, p]);
    setSelectedId(p.id);
    if (!focalId && (p.role === 'primary_emblem' || pieces.length === 0)) setFocalId(p.id);
  };

  const updatePiece = (id, patch) => commit(pieces.map(p => p.id === id ? { ...p, ...patch } : p));
  const rename = (id, name) => commit(pieces.map(p => p.id === id ? { ...p, name } : p));
  const removePiece = (id) => { commit(pieces.filter(p => p.id !== id)); if (focalId === id) setFocalId(null); if (selectedId === id) setSelectedId(null); };
  const duplicatePiece = (id) => { const p = pieces.find(x => x.id === id); if (!p) return; const order = Math.max(...pieces.map(x => x.order ?? 0)) + 1; const np = { ...p, id: uid(), name: `${p.name} copy`, order, cx: Math.min(0.9, p.cx + 0.05), cy: Math.min(0.9, p.cy + 0.05) }; commit([...pieces, np]); setSelectedId(np.id); };
  const orderPiece = (id, dir) => {
    const sorted = [...pieces].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
    const i = sorted.findIndex(p => p.id === id); const j = i + dir;
    if (j < 0 || j >= sorted.length) return;
    const a = sorted[i], b = sorted[j];
    commit(pieces.map(p => p.id === a.id ? { ...p, order: b.order } : p.id === b.id ? { ...p, order: a.order } : p));
  };
  const mirrorPiece = (id) => commit(pieces.map(p => p.id === id ? { ...p, mirrored: !p.mirrored } : p));
  const toggleLock = (id) => commit(pieces.map(p => p.id === id ? { ...p, locked: !p.locked } : p));
  const toggleVisible = (id) => commit(pieces.map(p => p.id === id ? { ...p, visible: p.visible === false ? true : false } : p));

  const undo = () => { if (!past.length) return; setFuture(f => [piecesRef.current, ...f].slice(0, 30)); setPieces(past[past.length - 1]); setPast(p => p.slice(0, -1)); };
  const redo = () => { if (!future.length) return; setPast(p => [...p, piecesRef.current].slice(-30)); setPieces(future[0]); setFuture(f => f.slice(1)); };

  const onCanvasChange = (next, live) => {
    if (live) { if (!dragging.current) { snapshot.current = piecesRef.current; dragging.current = true; } setLive(next); }
    else commit(next);
  };
  const onCanvasCommit = () => { if (snapshot.current) { setPast(p => [...p, snapshot.current].slice(-30)); setFuture([]); snapshot.current = null; } dragging.current = false; };

  // ---- demo + source ----
  const loadDemoDesign = () => {
    const dp = makeDemoPieces();
    setPieces(dp);
    setFocalId(dp.find(p => p.role === 'primary_emblem')?.id || dp[0]?.id || null);
    setSelectedId(null);
    setPast([]); setFuture([]);
    setDesign(d => ({ ...d, name: 'Arachnid Hero', sourceType: 'promptforge', character: 'Heroic', intendedApplicationMode: 'raised_emboss', originalPrompt: 'A bold arachnid-inspired heroic design with raised web lines and a central emblem.' }));
    setSavedDesignId(null); setSavedVersion(null); setVariantCreated(false); setSelectedCover(null);
    setStage('arrange');
  };

  const loadDemoCovers = async () => {
    setCoversLoading(true);
    try {
      let list = await base44.entities.CoverModel.list('-updated_date', 50).catch(() => []);
      if (!Array.isArray(list)) list = [];
      if (!list.length) {
        list = await Promise.all(DEMO_COVERS.map(c => base44.entities.CoverModel.create({ ...c, sourceFormat: 'stl', sourceFile: '', validationStatus: 'validated', active: true, boundingBox: { w: 90, h: 260, d: 80 }, connectorType: 'standard', ossiguardProfile: 'ossiguard-1' }).catch(() => null)));
        list = list.filter(Boolean);
      }
      setCovers(list);
    } finally { setCoversLoading(false); }
  };

  // ---- save ----
  const saveDesign = async () => {
    if (!pieces.length) return;
    setSaving(true);
    try {
      const focal = pieces.find(p => p.id === focalId);
      const preview = focal?.src || pieces[pieces.length - 1]?.src || DEMO_SVGS.emblem;
      const payload = {
        name: design.name || 'Untitled Universal Design', owner: me?.id || 'demo', sourceType: design.sourceType || 'promptforge',
        status: 'saved', masterPreviewImageUrl: preview, originalPrompt: design.originalPrompt, character: design.character,
        intendedApplicationMode: design.intendedApplicationMode || 'colour_texture', preferredIntensity: design.preferredIntensity || 'standard',
        placementIntent: focal?.placement || 'let_shire_choose', originalInspiredFlag: true, styleTags: ['Heroic'], archived: false
      };
      let id = savedDesignId; let version = savedVersion || 1;
      if (id) {
        version = (savedVersion || 1) + 1;
        await base44.entities.UniversalDesign.update(id, { ...payload, version });
        await base44.entities.UniversalDesignLayer.deleteMany({ universalDesignId: id }).catch(() => {});
      } else {
        const created = await base44.entities.UniversalDesign.create({ ...payload, version: 1 });
        id = created.id; version = 1;
      }
      const layers = pieces.map((p, i) => ({
        universalDesignId: id, artworkAssetId: p.src, name: p.name, order: p.order ?? i, visible: p.visible !== false, locked: !!p.locked,
        role: p.id === focalId ? 'primary_emblem' : p.role, applicationIntent: p.effect || 'colour_texture',
        aspectPolicy: ({ keep_shape: 'keep_shape', flexible: 'flexible', repeatable: 'repeatable', croppable: 'croppable', border_following: 'border_following', full_wrap: 'full_wrap', let_shire_choose: 'flexible' })[p.behaviour] || 'flexible',
        relativePosition: { u: p.cx, v: p.cy }, relativeScale: { u: p.w, v: p.h }, relativeRotation: p.rotation || 0,
        mayClip: p.behaviour === 'croppable' || p.behaviour === 'full_wrap', mayRepeat: p.behaviour === 'repeatable',
        protectedFromDistortion: p.behaviour === 'keep_shape' || p.id === focalId, focalPriority: p.id === focalId ? 1 : 0,
        colourIntent: p.mainColour, metadata: { placement: p.placement, intensity: p.intensity, material: p.material, accent: p.accentColour, background: p.backgroundColour, mirrored: !!p.mirrored }
      }));
      await base44.entities.UniversalDesignLayer.bulkCreate(layers).catch(() => {});
      setSavedDesignId(id); setSavedVersion(version); setVariantCreated(false); setStage('cover'); setDrawerOpen(true);
    } finally { setSaving(false); }
  };

  const createVariant = async () => {
    if (!savedDesignId || !selectedCover) return;
    setBusy(true);
    try {
      const adaptation = (await import('@/lib/adaptation')).computeAdaptation;
      const layers = pieces.map(p => pieceToLayer(p, focalId));
      const adapt = adaptation({ design, layers, cover: selectedCover, strategy, mirror: 'none' });
      await base44.entities.CoverDesignVariant.create({
        name: `${design.name} → ${selectedCover.name}`, owner: me?.id || 'demo', universalDesignId: savedDesignId,
        universalDesignVersion: savedVersion, coverModelId: selectedCover.id, status: 'adapted_preview',
        adaptationStrategy: strategy, adaptationVersion: 1, adaptationStatus: 'preview_ready', browserPreviewStatus: 'ready',
        geometryEngineStatus: 'not_submitted', targetLimbType: selectedCover.limbType, targetSide: selectedCover.side,
        coverVersion: selectedCover.version || '1', adaptedLayerData: adapt, sourceMasterLayerData: { version: savedVersion },
        brandingStatus: adapt.brandingStatus, mirrorMode: 'none', previewImageUrl: selectedCover.previewImageUrl,
        summary: adapt.summary, adaptationDetails: adapt.details, shireVaultPath: `/SHiRELimbs/CoverCanvas/Variants/${Date.now()}`
      }).catch(() => null);
      setVariantCreated(true); setStage('variant');
    } finally { setBusy(false); }
  };

  const pickCover = (c) => { setSelectedCover(c); setStrategy('best_fit'); setDrawerOpen(false); setStage('fit'); };
  const setMeta = (partial) => setDesign(d => ({ ...d, ...partial }));

  const hasSource = pieces.length > 0;
  const sourceThumb = pieces.find(p => p.role === 'primary_emblem')?.src || pieces[0]?.src;
  const selected = pieces.find(p => p.id === selectedId);

  const nextMap = { create: ['Arrange', () => setStage('arrange'), !!pieces.length], arrange: ['Set behaviour', () => setStage('behaviour'), !!pieces.length], behaviour: ['Save master', saveDesign, !!pieces.length], cover: ['Preview fit', () => setStage('fit'), !!selectedCover], fit: ['Create variant', createVariant, !!selectedCover] };
  const [nextLabel, onNext, canNext] = nextMap[stage] || [null, null, false];

  return (
    <div className="flex flex-col gap-3">
      <CanvasTopBar designName={design.name} onName={n => setMeta({ name: n })} saved={!!savedDesignId} savedVersion={savedVersion} fitted={!!selectedCover} promptforgeBusy={busy} onLoadDemo={loadDemoDesign} onLoadDemoCovers={loadDemoCovers} />
      <CanvasWorkflowStrip current={stage} reached={reached} onJump={jump} />

      {stage === 'fit' && selectedCover ? (
        <FitPreview pieces={pieces} focalId={focalId} design={design} cover={selectedCover} strategy={strategy} onStrategy={setStrategy} onAdjust={() => setStage('arrange')} onAnotherCover={() => { setDrawerOpen(true); setStage('cover'); }} onCompare={() => setCompareOpen(true)} advanced={advanced} />
      ) : stage === 'variant' ? (
        <div className="panel mx-auto max-w-lg p-8 text-center fade-in">
          <div className="mx-auto grid h-16 w-16 place-items-center rounded-2xl border border-emerald-400/40 bg-emerald-400/10 text-emerald-300"><Check size={30} /></div>
          <h2 className="mt-4 font-heading text-xl font-semibold text-white">Fitted version created</h2>
          <p className="mx-auto mt-2 max-w-sm text-sm text-slate-400">A CoverDesignVariant was saved and linked to your Universal Design. The master design is unchanged and still editable.</p>
          <div className="mt-5 flex flex-wrap justify-center gap-2">
            <Link to={`/cover-variants?design=${savedDesignId}`} className="btn-primary text-sm"><Box size={14} /> Open fitted version</Link>
            <button onClick={() => { setDrawerOpen(true); setStage('cover'); setVariantCreated(false); }} className="btn-secondary text-sm"><Sparkles size={14} /> Fit to another cover</button>
            <button onClick={() => setStage('arrange')} className="btn-ghost text-sm">Return to master design</button>
          </div>
          <p className="mt-5 text-[10px] text-amber-200">Simulation only — final surface fitting requires the Geometry Engine.</p>
        </div>
      ) : (
        <>
          <div className="grid gap-3 lg:grid-cols-[300px_1fr_320px]">
            <CreateDesignPanel onAddPiece={addPiece} onSetMeta={setMeta} hasSource={hasSource} sourceThumb={sourceThumb}
              onReplace={() => setStage('create')} onRemove={() => { setPieces([]); setFocalId(null); setSelectedId(null); setPast([]); setFuture([]); }} onPrepare={() => setStage('arrange')} />
            <div className="flex min-w-0 flex-col">
              <UniversalCanvas pieces={pieces} selectedId={selectedId} focalId={focalId} onSelect={setSelectedId} onChange={onCanvasChange} onCommit={onCanvasCommit} advanced={advanced} />
              <div className="mt-3 flex justify-center gap-2">
                {['create', 'arrange', 'behaviour'].includes(stage) && <button onClick={() => setStage('behaviour')} className="btn-ghost text-xs">Continue to behaviour <ArrowRight size={13} /></button>}
                {stage === 'save' && <p className="text-xs text-slate-400">Press <b className="text-cyan-200">Save Universal Design</b> below to store the master design.</p>}
              </div>
            </div>
            <DesignPiecesPanel pieces={pieces} selectedId={selectedId} focalId={focalId} onSelect={setSelectedId} onUpdate={updatePiece} onDelete={removePiece} onDuplicate={duplicatePiece} onSetFocal={setFocalId} onRename={rename} onOrder={orderPiece} />
          </div>
          <CanvasActionBar hasPieces={!!pieces.length} selected={selected} canSave={!!pieces.length} saving={saving} onSave={saveDesign} nextLabel={nextLabel} onNext={onNext} canNext={canNext} onUndo={past.length ? undo : null} onRedo={future.length ? redo : null} onDuplicate={duplicatePiece} onDelete={removePiece} onToggleLock={toggleLock} onToggleVisible={toggleVisible} onMirror={mirrorPiece} onOrder={orderPiece} />
        </>
      )}

      <CoverDrawer open={drawerOpen} onClose={() => setDrawerOpen(false)} covers={covers} loading={coversLoading} onPick={pickCover} onLoadDemo={loadDemoCovers} />
      <CompareCovers open={compareOpen} onClose={() => setCompareOpen(false)} covers={covers} pieces={pieces} focalId={focalId} design={design} strategy={strategy} />

      {!covers.length && !coversLoading && (
        <p className="text-center text-[10px] text-slate-600">No covers loaded yet — use <b>Demo covers</b> in the top bar, or open the Cover Library.</p>
      )}
    </div>
  );
}