"use client";

import { useCallback, useEffect, useState } from "react";

import { FileUploadField } from "@/components/admin/FileUploadField";

// ── styles (match ProjectScenes) ──────────────────────────────────────────────
const inp = "rounded-lg border border-[#262b40] bg-[#0c0e1a] px-2.5 py-1.5 text-sm text-gray-100 outline-none focus:border-indigo-500";
const btn = "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-500 disabled:opacity-50";
const ghost = "rounded-lg border border-[#262b40] px-2.5 py-1 text-xs text-gray-300 hover:bg-[#161a2e] disabled:opacity-50";
const lbl = "mb-1 block text-xs text-gray-400";
const del = "rounded-lg border border-red-500/30 px-2.5 py-1 text-xs text-red-300 hover:bg-red-500/10";

// ── types (snake_case — matches content-svc JSON) ─────────────────────────────
interface PresetScene { id?: string; scene_id: string; scene_key?: string | null; scene_title?: string | null; sort: number; default_duration_sec?: number | null }
interface StorySummary { id: string; project_id: string; name: string; description?: string | null; demo?: string | null; sort: number; is_published: boolean; scene_count: number }
interface StoryFull extends StorySummary { music_id?: string | null; scenes_spa?: string | null; scenes: PresetScene[] }
interface Scene { id: string; key: string; title: string; default_duration_sec?: number | null }

type Draft = {
  name: string; description: string; demo: string; is_published: boolean; sort: number;
  // Filled values the user's project starts with: content-element key → value, and
  // colour element key → hex. Serialized into scenes_spa = { values, colors }.
  values: Record<string, string>; colors: Record<string, string>; scenes: PresetScene[];
};

function emptyDraft(sort: number): Draft {
  return { name: "", description: "", demo: "", is_published: true, sort, values: {}, colors: {}, scenes: [] };
}

function parseSpa(spa?: string | null): { values: Record<string, string>; colors: Record<string, string> } {
  if (!spa) return { values: {}, colors: {} };
  try {
    const o = JSON.parse(spa);
    return {
      values: o && typeof o.values === "object" && o.values ? o.values : {},
      colors: o && typeof o.colors === "object" && o.colors ? o.colors : {},
    };
  } catch { return { values: {}, colors: {} }; }
}

function num(v: number | null | undefined) { return v === null || v === undefined ? "" : String(v); }
function toNum(v: string): number | null { return v.trim() === "" ? null : Number(v); }

export function ProjectPresetStories({ projectId }: { projectId: string }) {
  const [rows, setRows] = useState<StorySummary[]>([]);
  const [scenes, setScenes] = useState<Scene[]>([]);
  const [loading, setLoading] = useState(true);
  const [draft, setDraft] = useState<Draft | null>(null);
  const [editId, setEditId] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState<string | null>(null);
  const base = "/api/admin/resource/preset-stories";

  const load = useCallback(async () => {
    setLoading(true);
    const [r, sc] = await Promise.all([
      fetch(`${base}?project_id=${projectId}`, { cache: "no-store" }).then((x) => x.json()).catch(() => null),
      fetch(`/api/admin/resource/scenes?project_id=${projectId}`, { cache: "no-store" }).then((x) => x.json()).catch(() => null),
    ]);
    setRows(Array.isArray(r) ? r : r?.data ?? []);
    setScenes(Array.isArray(sc) ? sc : sc?.data ?? []);
    setLoading(false);
  }, [projectId]);
  useEffect(() => { load(); }, [load]);

  const openNew = () => { setEditId(null); setErr(null); setDraft(emptyDraft(rows.length)); };
  const openEdit = async (s: StorySummary) => {
    setErr(null);
    const full: StoryFull | null = await fetch(`${base}/${s.id}`, { cache: "no-store" }).then((x) => x.json()).catch(() => null);
    if (!full) { setErr("بارگذاری ویدیوی نمونه ناموفق بود"); return; }
    setEditId(s.id);
    const spa = parseSpa(full.scenes_spa);
    setDraft({
      name: full.name, description: full.description ?? "", demo: full.demo ?? "",
      is_published: full.is_published, sort: full.sort,
      values: spa.values, colors: spa.colors,
      scenes: (full.scenes ?? []).map((p) => ({ ...p })),
    });
  };

  const set = (p: Partial<Draft>) => setDraft((d) => (d ? { ...d, ...p } : d));

  const save = async () => {
    if (!draft) return;
    if (!draft.name.trim()) { setErr("نام ویدیوی نمونه الزامی است"); return; }
    setSaving(true); setErr(null);
    const hasFilled = Object.keys(draft.values).length > 0 || Object.keys(draft.colors).length > 0;
    const body = {
      project_id: projectId, name: draft.name.trim(), description: draft.description || null,
      demo: draft.demo || null, is_published: draft.is_published, sort: draft.sort ?? 0,
      scenes_spa: hasFilled ? JSON.stringify({ values: draft.values, colors: draft.colors }) : null,
      scenes: draft.scenes.map((s, i) => ({ scene_id: s.scene_id, sort: i, default_duration_sec: s.default_duration_sec ?? null })),
    };
    const res = await fetch(editId ? `${base}/${editId}` : base, {
      method: editId ? "PUT" : "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body),
    });
    const d = await res.json().catch(() => null);
    if (res.ok) { setDraft(null); setEditId(null); load(); }
    else setErr(d?.message ?? d?.error?.message ?? "ذخیرهٔ ویدیوی نمونه ناموفق بود");
    setSaving(false);
  };

  const remove = async (s: StorySummary) => {
    if (!confirm(`ویدیوی نمونهٔ «${s.name}» حذف شود؟`)) return;
    await fetch(`${base}/${s.id}`, { method: "DELETE" });
    load();
  };

  // ── scene-list editing ──────────────────────────────────────────────────────
  const addScene = () => {
    if (!draft) return;
    const first = scenes[0];
    set({ scenes: [...draft.scenes, { scene_id: first?.id ?? "", scene_key: first?.key, scene_title: first?.title, sort: draft.scenes.length, default_duration_sec: first?.default_duration_sec ?? null }] });
  };
  const setSceneAt = (i: number, p: Partial<PresetScene>) => {
    if (!draft) return;
    const a = [...draft.scenes]; a[i] = { ...a[i], ...p }; set({ scenes: a });
  };
  const removeSceneAt = (i: number) => { if (!draft) return; set({ scenes: draft.scenes.filter((_, j) => j !== i) }); };

  if (draft) {
    return (
      <div dir="rtl" className="space-y-4">
        <div className="flex items-center justify-between">
          <h3 className="text-sm font-semibold text-white">{editId ? "ویرایش ویدیوی نمونه" : "ویدیوی نمونهٔ جدید"}</h3>
          <button className={ghost} onClick={() => { setDraft(null); setEditId(null); setErr(null); }}>→ بازگشت به فهرست</button>
        </div>
        {err && <p className="rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-300">{err}</p>}

        <div className="grid gap-3 sm:grid-cols-2">
          <div><label className={lbl}>نام *</label><input className={`${inp} w-full`} value={draft.name} onChange={(e) => set({ name: e.target.value })} /></div>
          <div><label className={lbl}>ترتیب</label><input className={`${inp} w-full`} type="number" dir="ltr" value={num(draft.sort)} onChange={(e) => set({ sort: Number(e.target.value) || 0 })} /></div>
          <div className="sm:col-span-2"><label className={lbl}>توضیح</label><input className={`${inp} w-full`} value={draft.description} onChange={(e) => set({ description: e.target.value })} /></div>
          <div className="sm:col-span-2"><label className={lbl}>پیش‌نمایش (تصویر یا ویدیو)</label><FileUploadField value={draft.demo} onChange={(u) => set({ demo: u })} accept="video/*,image/*" /></div>
        </div>

        <div className="rounded-lg border border-[#1e2235] bg-[#0c0e1a] p-3">
          <label className="flex w-fit cursor-pointer items-center gap-2 text-sm text-gray-300">
            <input type="checkbox" checked={draft.is_published} onChange={(e) => set({ is_published: e.target.checked })} className="h-4 w-4 accent-indigo-500" />
            منتشر شده (برای کاربران نمایش داده شود)
          </label>
        </div>

        {/* Scene list */}
        <div className="space-y-2 rounded-lg border border-[#1e2235] bg-[#0c0e1a] p-3">
          <div className="flex items-center justify-between">
            <span className="text-xs font-medium text-gray-300">صحنه‌های این ویدیو (ترتیب + مدت)</span>
            <button className={ghost} type="button" onClick={addScene} disabled={scenes.length === 0}>+ افزودن صحنه</button>
          </div>
          {scenes.length === 0 && <p className="text-[11px] text-amber-300/80">این پروژه هنوز صحنه‌ای ندارد. ابتدا از «صحنه‌ها» صحنه تعریف کنید.</p>}
          {draft.scenes.length === 0 ? (
            <p className="text-[11px] text-gray-600">هنوز صحنه‌ای انتخاب نشده.</p>
          ) : draft.scenes.map((ps, i) => (
            <div key={i} className="flex items-center gap-2">
              <span className="text-[10px] text-gray-600">#{i}</span>
              <select className={`${inp} flex-1`} value={ps.scene_id} onChange={(e) => setSceneAt(i, { scene_id: e.target.value })}>
                {scenes.map((s) => <option key={s.id} value={s.id}>{s.title} ({s.key})</option>)}
              </select>
              <input className={`${inp} w-28`} type="number" step="0.1" dir="ltr" placeholder="مدت" value={num(ps.default_duration_sec)} onChange={(e) => setSceneAt(i, { default_duration_sec: toNum(e.target.value) })} />
              <button className={del} type="button" onClick={() => removeSceneAt(i)}>✕</button>
            </div>
          ))}
        </div>

        {/* Filled values — what the user's project starts with */}
        <PresetValueEditor
          projectId={projectId}
          sceneIds={draft.scenes.map((s) => s.scene_id).filter(Boolean)}
          values={draft.values}
          colors={draft.colors}
          onValue={(k, v) => set({ values: { ...draft.values, [k]: v } })}
          onColor={(k, v) => set({ colors: { ...draft.colors, [k]: v } })}
        />

        <div className="flex items-center justify-end gap-2 border-t border-[#1e2235] pt-3">
          <button className={ghost} onClick={() => { setDraft(null); setEditId(null); setErr(null); }}>انصراف</button>
          <button className={btn} onClick={save} disabled={saving}>{saving ? "در حال ذخیره…" : editId ? "ذخیرهٔ تغییرات" : "افزودن ویدیوی نمونه"}</button>
        </div>
      </div>
    );
  }

  return (
    <div dir="rtl" className="space-y-3">
      <div className="flex items-center justify-between gap-2">
        <p className="text-xs text-gray-500">ویدیوهای نمونهٔ آمادهٔ این قالب. کاربر می‌تواند یکی را انتخاب کند و پروژه‌اش از روی آن پر می‌شود.</p>
        <button className={btn} onClick={openNew}>+ ویدیوی نمونه</button>
      </div>
      {err && <p className="rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-300">{err}</p>}
      {loading ? (
        <p className="py-6 text-center text-sm text-gray-500">در حال بارگذاری…</p>
      ) : rows.length === 0 ? (
        <p className="rounded-lg border border-dashed border-[#262b40] py-6 text-center text-sm text-gray-600">هنوز ویدیوی نمونه‌ای ساخته نشده.</p>
      ) : (
        <ul className="space-y-1.5">
          {rows.map((s) => (
            <li key={s.id} className="flex items-center justify-between rounded-lg border border-[#1e2235] bg-[#0c0e1a] px-3 py-2">
              <div className="flex min-w-0 items-center gap-2">
                {s.demo
                  ? <span className="h-8 w-12 shrink-0 rounded bg-cover bg-center" style={{ backgroundImage: `url(${s.demo})` }} />
                  : <span className="grid h-8 w-12 shrink-0 place-items-center rounded bg-[#161a2e] text-[9px] text-gray-600">—</span>}
                <span className="truncate text-sm text-gray-200">{s.name}</span>
                <span className="rounded bg-[#1e2235] px-1.5 py-0.5 text-[10px] text-gray-400">{s.scene_count} صحنه</span>
                {!s.is_published && <span className="rounded bg-gray-500/15 px-1.5 py-0.5 text-[10px] text-gray-400">پیش‌نویس</span>}
              </div>
              <div className="flex shrink-0 items-center gap-2">
                <button className={ghost} onClick={() => openEdit(s)}>ویرایش</button>
                <button className={del} onClick={() => remove(s)}>حذف</button>
              </div>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

// ── Filled-value editor ───────────────────────────────────────────────────────
interface ContentEl { id: string; scene_id: string; key: string; title: string; type: string; default_value?: string | null }
interface SharedColorEl { id: string; element_key: string; title: string; default_color?: string | null }

const MEDIA_TYPES = new Set(["media", "audio", "voiceover"]);
const COLOR_TYPES = new Set(["fill", "color"]);
const isHex = (v: string) => /^#[0-9a-fA-F]{6}$/.test(v);

function PresetValueEditor({
  projectId, sceneIds, values, colors, onValue, onColor,
}: {
  projectId: string; sceneIds: string[];
  values: Record<string, string>; colors: Record<string, string>;
  onValue: (k: string, v: string) => void; onColor: (k: string, v: string) => void;
}) {
  const [groups, setGroups] = useState<{ sceneId: string; elements: ContentEl[] }[]>([]);
  const [shared, setShared] = useState<SharedColorEl[]>([]);
  const [loading, setLoading] = useState(false);
  const sceneKey = sceneIds.join(",");

  useEffect(() => {
    let cancelled = false;
    if (sceneIds.length === 0) { setGroups([]); return; }
    setLoading(true);
    Promise.all(sceneIds.map((sid) =>
      fetch(`/api/admin/resource/scene-elements?scene_id=${sid}`, { cache: "no-store" })
        .then((r) => r.json())
        .then((d) => ({ sceneId: sid, elements: (Array.isArray(d) ? d : d?.items ?? []) as ContentEl[] }))
        .catch(() => ({ sceneId: sid, elements: [] as ContentEl[] }))
    )).then((res) => { if (!cancelled) setGroups(res); }).finally(() => { if (!cancelled) setLoading(false); });
    fetch(`/api/admin/resource/shared-colors?project_id=${projectId}`, { cache: "no-store" })
      .then((r) => r.json())
      .then((d) => { if (!cancelled) setShared(Array.isArray(d) ? d : d?.data ?? []); })
      .catch(() => {});
    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sceneKey, projectId]);

  const renderInput = (el: ContentEl) => {
    const v = values[el.key] ?? "";
    const t = el.type.toLowerCase();
    if (MEDIA_TYPES.has(t)) return <FileUploadField value={v} onChange={(u) => onValue(el.key, u)} accept={t === "media" ? "image/*,video/*" : "audio/*"} />;
    if (COLOR_TYPES.has(t)) return (
      <div className="flex items-center gap-2">
        <input type="color" className="h-9 w-12 rounded border border-[#262b40] bg-[#0c0e1a]" value={isHex(v) ? v : "#000000"} onChange={(e) => onValue(el.key, e.target.value)} />
        <input className={`${inp} flex-1`} dir="ltr" value={v} onChange={(e) => onValue(el.key, e.target.value)} placeholder="#RRGGBB" />
      </div>
    );
    if (t === "textarea") return <textarea className={`${inp} w-full`} value={v} onChange={(e) => onValue(el.key, e.target.value)} rows={2} />;
    return <input className={`${inp} w-full`} type={t === "number" ? "number" : "text"} value={v} onChange={(e) => onValue(el.key, e.target.value)} placeholder={el.default_value ?? ""} />;
  };

  return (
    <div className="space-y-2 rounded-lg border border-[#1e2235] bg-[#0c0e1a] p-3">
      <p className="text-xs font-medium text-gray-300">مقادیر آماده — پروژهٔ کاربر با این مقادیر شروع می‌شود</p>
      {sceneIds.length === 0 ? (
        <p className="text-[11px] text-gray-600">ابتدا صحنه‌ها را بالا اضافه کنید تا ورودی‌ها این‌جا ظاهر شوند.</p>
      ) : loading ? (
        <p className="text-[11px] text-gray-500">در حال بارگذاری ورودی‌ها…</p>
      ) : (
        <div className="space-y-3">
          {groups.map((g, i) => (
            <div key={g.sceneId} className="space-y-1.5">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-gray-500">صحنه {i + 1}</p>
              {g.elements.length === 0 ? (
                <p className="text-[11px] text-gray-600">ورودی‌ای ندارد.</p>
              ) : g.elements.map((el) => (
                <div key={el.id} className="grid grid-cols-[110px_1fr] items-center gap-2">
                  <label className="truncate text-[11px] text-gray-400" title={el.key}>{el.title}</label>
                  {renderInput(el)}
                </div>
              ))}
            </div>
          ))}
          {shared.length > 0 && (
            <div className="space-y-1.5">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-gray-500">رنگ‌های مشترک</p>
              {shared.map((c) => {
                const v = colors[c.element_key] ?? "";
                const swatch = isHex(v) ? v : (c.default_color && isHex(c.default_color) ? c.default_color : "#000000");
                return (
                  <div key={c.id} className="grid grid-cols-[110px_1fr] items-center gap-2">
                    <label className="truncate text-[11px] text-gray-400" title={c.element_key}>{c.title}</label>
                    <div className="flex items-center gap-2">
                      <input type="color" className="h-9 w-12 rounded border border-[#262b40] bg-[#0c0e1a]" value={swatch} onChange={(e) => onColor(c.element_key, e.target.value)} />
                      <input className={`${inp} flex-1`} dir="ltr" value={v} onChange={(e) => onColor(c.element_key, e.target.value)} placeholder={c.default_color ?? "#RRGGBB"} />
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      )}
      <p className="text-[10px] text-gray-500">خالی بماند = مقدار پیش‌فرض قالب. مقداردهی = پروژهٔ کاربر از همین‌جا پر می‌شود.</p>
    </div>
  );
}
