"use client";

import Link from "next/link";
import { useEffect, useMemo, useState, useTransition } from "react";
import { Button, Card, StatusBadge } from "@/components/ui";
import { Field, inputClass } from "@/components/ui/form";
import { Modal } from "./modal";
import { FieldEditor } from "@/components/features/page-editor/field-editor";
import { MediaPicker } from "@/components/features/page-editor/media-picker";
import type { FieldContext } from "@/components/features/page-editor/types";
import type { FieldDef } from "@/lib/blocks/defs";
import { deleteEntryAction, restoreEntryVersionAction, saveEntryAction, setEntryStatusAction } from "@/lib/actions/content";

export interface EntryEditorProps {
  base: string;
  typeKey: string;
  typeLabel: string;
  titleLabel: string;
  fields: FieldDef[];
  supportsCategories: boolean;
  supportsFeaturedImage: boolean;
  entry: { id: string; siteId: string; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; draftVersion: number; title: string; slug: string; data: Record<string, unknown>; categoryId: string | null; featuredMediaId: string | null; seoTitle: string; seoDescription: string; sortOrder: number; tags: string[] };
  categories: { id: string; name: string }[];
  versions: { version: number; createdAt: string; author: string }[];
  perms: { manage: boolean; edit: boolean };
}

export function EntryEditor(props: EntryEditorProps) {
  const { entry, perms } = props;
  const [title, setTitle] = useState(entry.title);
  const [slug, setSlug] = useState(entry.slug);
  const [data, setData] = useState(entry.data);
  const [categoryId, setCategoryId] = useState(entry.categoryId);
  const [featured, setFeatured] = useState(entry.featuredMediaId);
  const [seoTitle, setSeoTitle] = useState(entry.seoTitle);
  const [seoDescription, setSeoDescription] = useState(entry.seoDescription);
  const [sortOrder, setSortOrder] = useState(entry.sortOrder);
  const [tags, setTags] = useState(entry.tags.join(", "));
  const [expected, setExpected] = useState(entry.draftVersion);
  const [dirty, setDirty] = useState(false);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [status, setStatus] = useState<{ ok: boolean; text: string } | null>(null);
  const [pending, start] = useTransition();
  const [confirmDelete, setConfirmDelete] = useState(false);
  const [optionsOpen, setOptionsOpen] = useState(false);
  const [optTab, setOptTab] = useState<"general" | "seo" | "versions">("general");
  const readOnly = !perms.edit || entry.status === "ARCHIVED";
  const ctx: FieldContext = useMemo(() => ({ siteId: entry.siteId, forms: [], events: [], disabled: readOnly }), [entry.siteId, readOnly]);
  const touch = () => { setDirty(true); setStatus(null); };

  useEffect(() => {
    if (!dirty) return;
    const h = (e: BeforeUnloadEvent) => e.preventDefault();
    window.addEventListener("beforeunload", h);
    return () => window.removeEventListener("beforeunload", h);
  }, [dirty]);

  function save() {
    start(async () => {
      const res = await saveEntryAction({
        entryId: entry.id, expectedVersion: expected, data,
        meta: { title, slug, categoryId: categoryId ?? undefined, featuredMediaId: featured ?? undefined, seoTitle, seoDescription, sortOrder, tags: tags.split(",").map((t) => t.trim()).filter(Boolean) },
      });
      if (res.ok && res.data) { setExpected(res.data.version); setDirty(false); setErrors({}); setStatus({ ok: true, text: res.message ?? "Saved" }); }
      else if (!res.ok) { setErrors(res.fieldErrors ?? {}); setStatus({ ok: false, text: res.error }); }
    });
  }
  function act(fn: () => Promise<{ ok: boolean; error?: string }>) {
    if (dirty) return setStatus({ ok: false, text: "Save your changes first." });
    start(async () => { const r = await fn(); if (r.ok) window.location.reload(); else setStatus({ ok: false, text: r.error ?? "Something went wrong" }); });
  }

  const dataErrors = Object.fromEntries(Object.entries(errors).filter(([k]) => !["title", "slug", "categoryId", "seoTitle", "seoDescription", "sortOrder", "tags"].includes(k)));

  const tabBtn = (t: "general" | "seo" | "versions", label: string) => (
    <button key={t} type="button" role="tab" id={`eo-tab-${t}`} aria-selected={optTab === t} aria-controls={`eo-panel-${t}`} onClick={() => setOptTab(t)} className={`-mb-px border-b-2 px-4 py-2 text-sm ${optTab === t ? "border-primary font-medium text-primary" : "border-transparent text-muted-foreground"}`}>{label}</button>
  );
  const seg = (on: boolean) => `inline-flex h-9 min-w-12 items-center justify-center px-3 text-sm font-medium ${on ? "bg-success text-white" : "bg-muted text-muted-foreground"}`;
  const published = entry.status === "PUBLISHED";

  return (
    <div>
      <div className="mb-4">
        <p className="text-xs text-muted-foreground"><Link href={`${props.base}/libraries`} className="hover:underline">Libraries</Link> <span aria-hidden>›</span> <Link href={`${props.base}/libraries/${props.typeKey}`} className="hover:underline">{props.typeLabel}</Link></p>
        <h1 className="text-2xl font-semibold tracking-tight">{title || "Untitled"} <StatusBadge value={entry.status} /></h1>
      </div>
      {readOnly ? <p role="note" className="mb-4 rounded-md border border-border bg-muted p-3 text-sm">{entry.status === "ARCHIVED" ? "Archived entries are read-only. Restore to draft to edit." : "Published entries can only be changed by people who can manage content."}</p> : null}

      <Card className="space-y-4 p-5">
        <Field id="e-title" label={props.titleLabel} error={errors.title}>
          <input id="e-title" value={title} disabled={readOnly} maxLength={200} onChange={(e) => { setTitle(e.target.value); touch(); }} className={inputClass} aria-invalid={errors.title ? true : undefined} />
        </Field>
        <Field id="e-code" label="Entry code" help="Unique code of this entry. It cannot be changed."><input id="e-code" value={entry.id} readOnly className={`${inputClass} font-mono text-xs`} /></Field>
        <FieldEditor fields={props.fields} values={data} ctx={ctx} path="" errors={dataErrors} onChange={(next) => { setData(next); touch(); }} />
      </Card>

      <div className="fixed inset-x-0 bottom-0 z-20 border-t border-border bg-card/95 px-4 py-3 backdrop-blur lg:left-64">
        <div className="mx-auto flex max-w-5xl flex-wrap items-center justify-between gap-3">
          <div className="flex items-center gap-2">
            {perms.manage ? (confirmDelete ? (
              <><Button variant="danger" disabled={pending} onClick={() => start(async () => { const r = await deleteEntryAction(props.base, props.typeKey, entry.id); if (r && !r.ok) setStatus({ ok: false, text: r.error }); })}>Confirm delete</Button><Button variant="ghost" onClick={() => setConfirmDelete(false)}>Cancel</Button></>
            ) : <Button variant="secondary" onClick={() => setConfirmDelete(true)}>Delete</Button>) : null}
          </div>
          <div className="flex flex-wrap items-center gap-3">
            <span role="status" aria-live="polite" className={status ? (status.ok ? "text-sm text-success" : "text-sm text-danger") : dirty ? "text-xs text-warning" : "sr-only"}>{status?.text ?? (dirty ? "Unsaved changes" : "")}</span>
            <div className="flex items-center gap-2 text-sm">
              <span id="e-active">Active:</span>
              <div role="group" aria-labelledby="e-active" className="inline-flex overflow-hidden rounded-md border border-border">
                {perms.manage && entry.status !== "ARCHIVED" ? (
                  <>
                    <button type="button" className={seg(published)} aria-pressed={published} disabled={pending || published} onClick={() => act(() => setEntryStatusAction(entry.id, "PUBLISHED"))} title="Publish this entry">Yes</button>
                    <button type="button" className={seg(!published)} aria-pressed={!published} disabled={pending || !published} onClick={() => act(() => setEntryStatusAction(entry.id, "DRAFT"))} title="Unpublish this entry (back to draft)">No</button>
                  </>
                ) : (<><span className={seg(published)}>Yes</span><span className={seg(!published)}>No</span></>)}
              </div>
            </div>
            <Button variant="secondary" onClick={() => { setOptTab("general"); setOptionsOpen(true); }}>Entry Options</Button>
            <Button onClick={save} disabled={readOnly || pending || !dirty}>{pending ? "Saving…" : "Save"}</Button>
          </div>
        </div>
      </div>

      <Modal open={optionsOpen} onClose={() => setOptionsOpen(false)} title="Entry Options">
        <div role="tablist" aria-label="Entry options" className="mb-4 flex gap-1 border-b border-border">{tabBtn("general", "General")}{tabBtn("seo", "SEO")}{tabBtn("versions", "Versions")}</div>
        {optTab === "general" ? (
          <div role="tabpanel" id="eo-panel-general" aria-labelledby="eo-tab-general" className="space-y-4">
            <Field id="e-slug" label="Page URL" error={errors.slug}><input id="e-slug" value={slug} disabled={readOnly} onChange={(e) => { setSlug(e.target.value.toLowerCase()); touch(); }} className={inputClass} /></Field>
            {props.supportsCategories ? (
              <Field id="e-cat" label="Category" error={errors.categoryId}>
                <select id="e-cat" value={categoryId ?? ""} disabled={readOnly} onChange={(e) => { setCategoryId(e.target.value || null); touch(); }} className={inputClass}>
                  <option value="">None</option>
                  {props.categories.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
              </Field>
            ) : null}
            <Field id="e-tags" label="Tags" help="Comma-separated, up to 15." error={errors.tags}><input id="e-tags" value={tags} disabled={readOnly} onChange={(e) => { setTags(e.target.value); touch(); }} className={inputClass} /></Field>
            <Field id="e-sort" label="Sort order" help="Lower numbers appear first when a library is ordered by sort order." error={errors.sortOrder}><input id="e-sort" type="number" value={sortOrder} disabled={readOnly} onChange={(e) => { setSortOrder(Number(e.target.value)); touch(); }} className={inputClass} /></Field>
            {props.supportsFeaturedImage ? (
              <div className="space-y-1"><span className="block text-xs font-medium">Featured image</span><MediaPicker siteId={entry.siteId} label="featured image" value={featured} onChange={(v) => { setFeatured(v); touch(); }} disabled={readOnly} /></div>
            ) : null}
            {perms.manage ? (
              <div className="flex flex-wrap gap-2 border-t border-border pt-3">
                {entry.status === "ARCHIVED" ? <Button variant="secondary" disabled={pending || dirty} onClick={() => act(() => setEntryStatusAction(entry.id, "DRAFT"))}>Restore to draft</Button> : <Button variant="secondary" disabled={pending || dirty} onClick={() => act(() => setEntryStatusAction(entry.id, "ARCHIVED"))}>Archive</Button>}
              </div>
            ) : null}
          </div>
        ) : null}
        {optTab === "seo" ? (
          <div role="tabpanel" id="eo-panel-seo" aria-labelledby="eo-tab-seo" className="space-y-4">
            <Field id="e-seot" label="SEO title" error={errors.seoTitle}><input id="e-seot" value={seoTitle} disabled={readOnly} maxLength={70} onChange={(e) => { setSeoTitle(e.target.value); touch(); }} className={inputClass} /></Field>
            <Field id="e-seod" label="Meta description" error={errors.seoDescription}><textarea id="e-seod" rows={3} value={seoDescription} disabled={readOnly} maxLength={320} onChange={(e) => { setSeoDescription(e.target.value); touch(); }} className={inputClass} /></Field>
          </div>
        ) : null}
        {optTab === "versions" ? (
          <div role="tabpanel" id="eo-panel-versions" aria-labelledby="eo-tab-versions">
            <ol className="space-y-2 text-sm">
              {props.versions.map((v) => (
                <li key={v.version} className="flex items-center justify-between gap-2">
                  <span>v{v.version}{v.version === entry.draftVersion ? " (current)" : ""} <span className="block text-xs text-muted-foreground">{new Date(v.createdAt).toLocaleString("en-GB")} · {v.author}</span></span>
                  {!readOnly && v.version !== entry.draftVersion ? <Button variant="ghost" disabled={pending} onClick={() => act(() => restoreEntryVersionAction(entry.id, v.version))}>Restore</Button> : null}
                </li>
              ))}
            </ol>
          </div>
        ) : null}
        <div className="mt-5 flex justify-end"><Button variant="secondary" onClick={() => setOptionsOpen(false)}>Done</Button></div>
      </Modal>
    </div>
  );
}
