"use client";

import { useEffect, useState, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { useRouter } from "next/navigation";
import { PROJECT_SIZES, SIZE_LABELS, type ProjectSize } from "../../types";

type Resource = "projects" | "experience" | "affiliates";

const RESOURCES: { key: Resource; label: string }[] = [
  { key: "projects", label: "Projects" },
  { key: "experience", label: "Work Experience" },
  { key: "affiliates", label: "Affiliates" },
];

// A record being edited; `_new` marks an unsaved draft (POST vs PUT).
type Row = Record<string, unknown> & { id?: string; _new?: boolean };

const TEMPLATES: Record<Resource, () => Row> = {
  projects: () => ({
    _new: true,
    name: "",
    label: "",
    size: "MediumSized",
    imageUrl: "",
    link: "",
    linkIsDemo: false,
    sourceCode: "",
    description: "",
    why: "",
    note: "",
    tags: [],
    loc: null,
    locEndpoint: "",
  }),
  experience: () => ({
    _new: true,
    company: "",
    role: "",
    fromDate: "",
    toDate: "",
    url: "",
    iconUrl: "",
    summary: "",
    tags: [],
    sortIndex: 0,
  }),
  affiliates: () => ({
    _new: true,
    name: "",
    link: "",
    icon: "",
    location: "",
    provides: [],
    good: [],
    bad: [],
    sortIndex: 0,
  }),
};

const inputCls =
  "w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm text-gray-100 outline-none focus:border-blue-500/50";
const labelCls = "text-xs font-bold text-gray-500 uppercase";

function toDateInput(value: unknown): string {
  if (!value) return "";
  const d = new Date(String(value));
  if (Number.isNaN(d.getTime())) return "";
  return d.toISOString().slice(0, 10);
}

export default function AdminPage() {
  const router = useRouter();

  const [authChecked, setAuthChecked] = useState(false);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [password, setPassword] = useState("");
  const [loginError, setLoginError] = useState("");
  const [loggingIn, setLoggingIn] = useState(false);

  const [resource, setResource] = useState<Resource>("projects");
  const [rows, setRows] = useState<Row[]>([]);
  const [loading, setLoading] = useState(false);
  const [toast, setToast] = useState<{ type: "success" | "error"; message: string } | null>(null);
  const [savingId, setSavingId] = useState<string | null>(null);

  const showToast = (type: "success" | "error", message: string) => {
    setToast({ type, message });
    setTimeout(() => setToast(null), 3500);
  };

  // --- auth ---
  useEffect(() => {
    fetch("/api/admin/session")
      .then((r) => r.json())
      .then((d) => setIsAuthenticated(Boolean(d.authenticated)))
      .catch(() => setIsAuthenticated(false))
      .finally(() => setAuthChecked(true));
  }, []);

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault();
    setLoggingIn(true);
    setLoginError("");
    try {
      const res = await fetch("/api/admin/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ password }),
      });
      if (res.ok) {
        setIsAuthenticated(true);
        setPassword("");
      } else {
        setLoginError("Invalid password");
      }
    } catch {
      setLoginError("Network error");
    } finally {
      setLoggingIn(false);
    }
  };

  const handleLogout = async () => {
    await fetch("/api/admin/logout", { method: "POST" });
    setIsAuthenticated(false);
  };

  // --- data ---
  const loadRows = useCallback(async (res: Resource) => {
    setLoading(true);
    try {
      const r = await fetch(`/api/admin/${res}`);
      if (r.ok) {
        const json = await r.json();
        const normalized = Array.isArray(json)
          ? json.map((item: Row) =>
              res === "experience"
                ? { ...item, fromDate: toDateInput(item.fromDate), toDate: toDateInput(item.toDate) }
                : item,
            )
          : [];
        setRows(normalized);
      } else if (r.status === 401) {
        setIsAuthenticated(false);
      } else {
        showToast("error", `Failed to load (${r.status})`);
      }
    } catch {
      showToast("error", "Failed to load data");
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (isAuthenticated) loadRows(resource);
  }, [isAuthenticated, resource, loadRows]);

  const update = (idx: number, field: string, value: unknown) => {
    setRows((prev) => prev.map((row, i) => (i === idx ? { ...row, [field]: value } : row)));
  };

  const addRow = () => setRows((prev) => [TEMPLATES[resource](), ...prev]);

  const saveRow = async (idx: number) => {
    const row = rows[idx];
    const isNew = row._new || !row.id;
    setSavingId(row.id || `new-${idx}`);
    try {
      const url = isNew ? `/api/admin/${resource}` : `/api/admin/${resource}/${row.id}`;
      const { _new, ...payload } = row;
      const res = await fetch(url, {
        method: isNew ? "POST" : "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (res.ok) {
        showToast("success", "Saved");
        await loadRows(resource);
      } else {
        const err = await res.json().catch(() => ({}));
        showToast("error", err.error || `Save failed (${res.status})`);
      }
    } catch {
      showToast("error", "Network error");
    } finally {
      setSavingId(null);
    }
  };

  const deleteRow = async (idx: number) => {
    const row = rows[idx];
    if (row._new || !row.id) {
      setRows((prev) => prev.filter((_, i) => i !== idx));
      return;
    }
    if (!confirm("Delete this entry permanently?")) return;
    try {
      const res = await fetch(`/api/admin/${resource}/${row.id}`, { method: "DELETE" });
      if (res.ok) {
        showToast("success", "Deleted");
        setRows((prev) => prev.filter((_, i) => i !== idx));
      } else {
        showToast("error", `Delete failed (${res.status})`);
      }
    } catch {
      showToast("error", "Network error");
    }
  };

  // --- login screen ---
  if (!authChecked) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-[#0a0a0a] text-gray-500">
        Checking session…
      </div>
    );
  }

  if (!isAuthenticated) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-[#0a0a0a] px-4 font-sans text-white">
        <motion.div
          initial={{ opacity: 0, scale: 0.95 }}
          animate={{ opacity: 1, scale: 1 }}
          className="w-full max-w-sm p-8 bg-white/5 backdrop-blur-3xl border border-white/10 rounded-2xl shadow-2xl"
        >
          <h1 className="text-2xl font-black mb-6 text-center text-white">ADMIN ACCESS</h1>
          <form onSubmit={handleLogin} className="space-y-4">
            <input
              type="password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              placeholder="Password"
              className="w-full bg-black/50 border border-white/10 rounded-xl px-4 py-3 focus:ring-2 focus:ring-purple-500/50 outline-none"
              autoFocus
            />
            {loginError && <p className="text-red-400 text-xs text-center">{loginError}</p>}
            <button
              type="submit"
              disabled={loggingIn}
              className="w-full bg-white text-black font-bold py-3 rounded-xl hover:opacity-90 disabled:opacity-50"
            >
              {loggingIn ? "Validating…" : "Unlock"}
            </button>
          </form>
        </motion.div>
      </div>
    );
  }

  // --- panel ---
  return (
    <div className="min-h-screen bg-[#0a0a0a] text-gray-200 font-sans">
      <div className="max-w-6xl mx-auto p-6">
        <header className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-10">
          <div>
            <h1 className="text-3xl font-black text-white">PORTFOLIO CMS</h1>
            <p className="text-gray-500 text-sm">Manage your projects, experience &amp; affiliates</p>
          </div>
          <div className="flex gap-3">
            <button onClick={() => router.push("/")} className="px-4 py-2 rounded-lg bg-white/5 hover:bg-white/10 border border-white/10 text-sm">
              View Site
            </button>
            <button onClick={handleLogout} className="px-4 py-2 rounded-lg bg-white/5 hover:bg-white/10 border border-white/10 text-sm">
              Logout
            </button>
          </div>
        </header>

        <div className="flex flex-col lg:flex-row gap-8">
          <aside className="lg:w-56 flex-shrink-0 space-y-2">
            {RESOURCES.map((r) => (
              <button
                key={r.key}
                onClick={() => setResource(r.key)}
                className={`w-full text-left px-4 py-3 rounded-xl border text-sm font-bold ${
                  resource === r.key
                    ? "bg-white text-black border-white"
                    : "bg-white/5 border-transparent text-gray-400 hover:bg-white/10"
                }`}
              >
                {r.label}
              </button>
            ))}
          </aside>

          <main className="flex-1 space-y-6">
            <div className="flex justify-between items-center">
              <h2 className="text-xl font-bold text-white">{RESOURCES.find((r) => r.key === resource)?.label}</h2>
              <button onClick={addRow} className="px-4 py-2 rounded-lg bg-green-600/20 text-green-400 border border-green-500/30 hover:bg-green-600/30 text-xs font-bold">
                + New Entry
              </button>
            </div>

            {loading ? (
              <div className="h-64 flex items-center justify-center text-gray-500 italic animate-pulse">Loading…</div>
            ) : rows.length === 0 ? (
              <div className="h-40 flex items-center justify-center text-gray-500 border border-white/10 rounded-2xl">
                Nothing here yet. Add a new entry.
              </div>
            ) : (
              <AnimatePresence>
                {rows.map((row, idx) => (
                  <motion.div
                    key={row.id || `new-${idx}`}
                    initial={{ opacity: 0, y: 10 }}
                    animate={{ opacity: 1, y: 0 }}
                    className="p-6 bg-white/5 border border-white/10 rounded-2xl space-y-4"
                  >
                    <div className="flex justify-between items-center border-b border-white/5 pb-2">
                      <span className="text-[10px] font-mono text-gray-500 uppercase">
                        {row._new ? "NEW" : (row.id as string)?.slice(0, 8)}
                      </span>
                      <div className="flex gap-3">
                        <button
                          onClick={() => saveRow(idx)}
                          disabled={savingId !== null}
                          className="text-xs font-bold px-3 py-1 rounded-lg bg-blue-600 hover:bg-blue-500 text-white disabled:opacity-50"
                        >
                          {savingId === (row.id || `new-${idx}`) ? "Saving…" : "Save"}
                        </button>
                        <button onClick={() => deleteRow(idx)} className="text-red-500/60 hover:text-red-400 text-xs">
                          Delete
                        </button>
                      </div>
                    </div>

                    {resource === "projects" && <ProjectFields row={row} idx={idx} update={update} />}
                    {resource === "experience" && <ExperienceFields row={row} idx={idx} update={update} />}
                    {resource === "affiliates" && <AffiliateFields row={row} idx={idx} update={update} />}
                  </motion.div>
                ))}
              </AnimatePresence>
            )}
          </main>
        </div>
      </div>

      {toast && (
        <motion.div
          initial={{ opacity: 0, y: 100 }}
          animate={{ opacity: 1, y: 0 }}
          className={`fixed bottom-8 left-1/2 -translate-x-1/2 px-8 py-4 rounded-2xl shadow-2xl border font-bold text-sm ${
            toast.type === "success" ? "bg-green-500 text-white border-green-400" : "bg-red-500 text-white border-red-400"
          }`}
        >
          {toast.message}
        </motion.div>
      )}
    </div>
  );
}

// ---------- field group components ----------

type FieldProps = { row: Row; idx: number; update: (idx: number, field: string, value: unknown) => void };

function Text({ row, idx, update, field, label, placeholder }: FieldProps & { field: string; label: string; placeholder?: string }) {
  return (
    <div className="space-y-1">
      <label className={labelCls}>{label}</label>
      <input
        type="text"
        value={(row[field] as string) ?? ""}
        onChange={(e) => update(idx, field, e.target.value)}
        className={inputCls}
        placeholder={placeholder}
      />
    </div>
  );
}

function Area({ row, idx, update, field, label }: FieldProps & { field: string; label: string }) {
  return (
    <div className="md:col-span-2 space-y-1">
      <label className={labelCls}>{label}</label>
      <textarea
        rows={3}
        value={(row[field] as string) ?? ""}
        onChange={(e) => update(idx, field, e.target.value)}
        className={inputCls}
      />
    </div>
  );
}

function Toggle({ row, idx, update, field, label }: FieldProps & { field: string; label: string }) {
  const on = Boolean(row[field]);
  return (
    <div className="flex items-center justify-between rounded-lg border border-white/10 bg-black/30 p-3">
      <label className={labelCls}>{label}</label>
      <button
        type="button"
        onClick={() => update(idx, field, !on)}
        className={`px-3 py-1 rounded-lg text-xs font-bold ${on ? "bg-green-500/20 text-green-300" : "bg-white/10 text-gray-400"}`}
      >
        {on ? "Yes" : "No"}
      </button>
    </div>
  );
}

function TagField({ row, idx, update, field, label, max }: FieldProps & { field: string; label: string; max?: number }) {
  const [draft, setDraft] = useState("");
  const list = (row[field] as string[]) || [];
  const add = () => {
    const v = draft.trim();
    if (!v) return;
    if (max && list.length >= max) return;
    update(idx, field, [...list, v]);
    setDraft("");
  };
  return (
    <div className="md:col-span-2 space-y-1">
      <label className={labelCls}>
        {label} {max ? <span className="text-gray-600">(max {max})</span> : null}
      </label>
      <div className="space-y-2 rounded-lg border border-white/10 bg-black/30 p-3">
        <div className="flex flex-wrap gap-2">
          {list.map((tag, i) => (
            <span key={`${tag}-${i}`} className="inline-flex items-center gap-1.5 rounded-full border border-white/10 bg-white/5 px-2.5 py-1 text-xs">
              {tag}
              <button
                type="button"
                onClick={() => update(idx, field, list.filter((_, j) => j !== i))}
                className="text-red-400/70 hover:text-red-400"
              >
                ×
              </button>
            </span>
          ))}
          {list.length === 0 && <span className="text-xs text-gray-600">None yet.</span>}
        </div>
        <div className="flex gap-2">
          <input
            type="text"
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                e.preventDefault();
                add();
              }
            }}
            className={inputCls}
            placeholder={max && list.length >= max ? "Max reached" : "Add…"}
            disabled={Boolean(max && list.length >= max)}
          />
          <button type="button" onClick={add} className="px-3 py-2 rounded-lg border border-green-500/40 text-green-300 hover:bg-green-500/15 text-xs font-bold">
            Add
          </button>
        </div>
      </div>
    </div>
  );
}

function ProjectFields({ row, idx, update }: FieldProps) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
      <Text row={row} idx={idx} update={update} field="name" label="Name" />
      <Text row={row} idx={idx} update={update} field="label" label="Label" placeholder="e.g. Dev Tool" />
      <div className="space-y-1">
        <label className={labelCls}>Size</label>
        <select
          value={(row.size as string) || "MediumSized"}
          onChange={(e) => update(idx, "size", e.target.value as ProjectSize)}
          className={inputCls}
        >
          {PROJECT_SIZES.map((s) => (
            <option key={s} value={s}>
              {SIZE_LABELS[s]}
            </option>
          ))}
        </select>
      </div>
      <Text row={row} idx={idx} update={update} field="link" label="Link" />
      <Text row={row} idx={idx} update={update} field="sourceCode" label="Source Code (GitHub/Gitea)" />
      <Text row={row} idx={idx} update={update} field="imageUrl" label="Image URL" />
      <Area row={row} idx={idx} update={update} field="description" label="Description" />
      <Area row={row} idx={idx} update={update} field="why" label="Why" />
      <Area row={row} idx={idx} update={update} field="note" label="Note" />
      <TagField row={row} idx={idx} update={update} field="tags" label="Tags" max={3} />
      <div className="space-y-1">
        <label className={labelCls}>LoC (manual)</label>
        <input
          type="number"
          value={row.loc === null || row.loc === undefined ? "" : (row.loc as number)}
          onChange={(e) => update(idx, "loc", e.target.value === "" ? null : Number(e.target.value))}
          className={inputCls}
          placeholder="Optional"
        />
      </div>
      <Text row={row} idx={idx} update={update} field="locEndpoint" label="LoC Endpoint (plaintext number)" />
      <Toggle row={row} idx={idx} update={update} field="linkIsDemo" label="Link is a live demo" />
    </div>
  );
}

function ExperienceFields({ row, idx, update }: FieldProps) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
      <Text row={row} idx={idx} update={update} field="company" label="Company" />
      <Text row={row} idx={idx} update={update} field="role" label="Role" />
      <div className="space-y-1">
        <label className={labelCls}>From</label>
        <input type="date" value={(row.fromDate as string) || ""} onChange={(e) => update(idx, "fromDate", e.target.value)} className={inputCls} />
      </div>
      <div className="space-y-1">
        <label className={labelCls}>Until (empty = Present)</label>
        <input type="date" value={(row.toDate as string) || ""} onChange={(e) => update(idx, "toDate", e.target.value)} className={inputCls} />
      </div>
      <Text row={row} idx={idx} update={update} field="url" label="Company URL" />
      <Text row={row} idx={idx} update={update} field="iconUrl" label="Icon URL" />
      <Area row={row} idx={idx} update={update} field="summary" label="Summary of Activities" />
      <TagField row={row} idx={idx} update={update} field="tags" label="Tags" max={6} />
      <div className="space-y-1">
        <label className={labelCls}>Sort Index</label>
        <input type="number" value={(row.sortIndex as number) ?? 0} onChange={(e) => update(idx, "sortIndex", Number(e.target.value))} className={inputCls} />
      </div>
    </div>
  );
}

function AffiliateFields({ row, idx, update }: FieldProps) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
      <Text row={row} idx={idx} update={update} field="name" label="Name" />
      <Text row={row} idx={idx} update={update} field="link" label="Affiliate Link" />
      <Text row={row} idx={idx} update={update} field="icon" label="Icon URL" />
      <Text row={row} idx={idx} update={update} field="location" label="Location" />
      <TagField row={row} idx={idx} update={update} field="provides" label="Provides" />
      <TagField row={row} idx={idx} update={update} field="good" label="Good" />
      <TagField row={row} idx={idx} update={update} field="bad" label="Bad" />
      <div className="space-y-1">
        <label className={labelCls}>Sort Index</label>
        <input type="number" value={(row.sortIndex as number) ?? 0} onChange={(e) => update(idx, "sortIndex", Number(e.target.value))} className={inputCls} />
      </div>
    </div>
  );
}
