import { useEffect, useMemo, useState, type ReactNode } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import {
  getJSON,
  getJSONAuth,
  postJSON,
  putJSON,
  uploadFile,
  type Category,
} from "../../../api";
import { getToken } from "../../../admin/token";
import { useAdminT } from "../../../admin/useAdminT";
import { resourceTypeDisplay } from "../../../resourceTypeLabels";
import { adminUiPrefix } from "../../../adminPaths";
import { useAdminRouterMode } from "../../../adminRouterMode";

const types = [
  "image",
  "video",
  "music",
  "ppt",
  "pdf",
  "text",
  "link",
  "archive",
] as const;

export function AdminResourceForm() {
  const { id } = useParams();
  const isNew = !id || id === "new";
  const t = useAdminT();
  const mode = useAdminRouterMode();
  const token = getToken();
  const nav = useNavigate();

  const [cats, setCats] = useState<Category[]>([]);
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [rtype, setRtype] = useState<string>("image");
  const [language, setLanguage] = useState("zh-CN");
  const [categoryId, setCategoryId] = useState(1);
  const [coverImage, setCoverImage] = useState("");
  const [fileUrl, setFileUrl] = useState("");
  const [previewUrl, setPreviewUrl] = useState("");
  const [externalUrl, setExternalUrl] = useState("");
  const [bodyText, setBodyText] = useState("");
  const [badgeLabel, setBadgeLabel] = useState("");
  const [isPublic, setIsPublic] = useState(true);
  const [isDownloadable, setIsDownloadable] = useState(true);
  const [isRecommended, setIsRecommended] = useState(false);
  const [sortOrder, setSortOrder] = useState(0);
  const [status, setStatus] = useState("published");
  const [tags, setTags] = useState("");
  const [err, setErr] = useState<string | null>(null);

  useEffect(() => {
    getJSON<Category[]>("/api/categories?lang=zh-CN")
      .then(setCats)
      .catch(() => setCats([]));
  }, []);

  useEffect(() => {
    if (isNew || !id) return;
    getJSONAuth<any>(`/api/admin/resources/${id}`, token)
      .then((r) => {
        setTitle(r.title || "");
        setDescription(r.description || "");
        setRtype(r.type || "image");
        setLanguage(r.language || "zh-CN");
        setCategoryId(r.categoryId || 1);
        setCoverImage(r.coverImage || "");
        setFileUrl(r.fileUrl || "");
        setPreviewUrl(r.previewUrl || "");
        setExternalUrl(r.externalUrl || "");
        setBodyText(r.bodyText || "");
        setBadgeLabel(r.badgeLabel || "");
        setIsPublic(!!r.isPublic);
        setIsDownloadable(!!r.isDownloadable);
        setIsRecommended(!!r.isRecommended);
        setSortOrder(r.sortOrder || 0);
        setStatus(r.status || "draft");
        setTags((r.tags || []).join(", "));
      })
      .catch((e) => setErr(String(e)));
  }, [id, isNew, token]);

  const payload = useMemo(
    () => ({
      title,
      description,
      type: rtype,
      language,
      categoryId,
      coverImage,
      fileUrl,
      previewUrl,
      externalUrl,
      bodyText,
      badgeLabel,
      isPublic,
      isDownloadable,
      isRecommended,
      sortOrder,
      status,
      tags: tags
        .split(",")
        .map((x) => x.trim())
        .filter(Boolean),
    }),
    [
      title,
      description,
      rtype,
      language,
      categoryId,
      coverImage,
      fileUrl,
      previewUrl,
      externalUrl,
      bodyText,
      badgeLabel,
      isPublic,
      isDownloadable,
      isRecommended,
      sortOrder,
      status,
      tags,
    ],
  );

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between gap-3">
        <h1 className="text-2xl font-bold">
          {isNew ? t("newResource") : t("adminEditResource")}
        </h1>
        <Link
          to={mode === "basename" ? ".." : `${adminUiPrefix}/resources`}
          className="text-sm text-neutral-400 hover:text-white"
        >
          ← {t("backToList")}
        </Link>
      </div>
      {err ? <div className="text-red-300">{err}</div> : null}

      <div className="grid gap-3 md:grid-cols-2">
        <Field label={t("title")}>
          <input
            className="input"
            value={title}
            onChange={(e) => setTitle(e.target.value)}
          />
        </Field>
        <Field label={t("category")}>
          <select
            className="input"
            value={categoryId}
            onChange={(e) => setCategoryId(Number(e.target.value))}
          >
            {cats.map((c) => (
              <option key={c.id} value={c.id}>
                {c.name}
              </option>
            ))}
          </select>
        </Field>
        <Field label={t("type")}>
          <select
            className="input"
            value={rtype}
            onChange={(e) => setRtype(e.target.value)}
          >
            {types.map((x) => (
              <option key={x} value={x}>
                {resourceTypeDisplay(t, x)}
              </option>
            ))}
          </select>
        </Field>
        <Field label={t("language")}>
          <select
            className="input"
            value={language}
            onChange={(e) => setLanguage(e.target.value)}
          >
            <option value="zh-CN">{t("lang_zh_CN")}</option>
            <option value="en">{t("lang_en")}</option>
            <option value="ja">{t("lang_ja")}</option>
            <option value="ko">{t("lang_ko")}</option>
            <option value="vi">{t("lang_vi")}</option>
            <option value="id">{t("lang_id")}</option>
            <option value="ms">{t("lang_ms")}</option>
          </select>
        </Field>
        <Field label={t("status")}>
          <select
            className="input"
            value={status}
            onChange={(e) => setStatus(e.target.value)}
          >
            <option value="draft">{t("draft")}</option>
            <option value="published">{t("published")}</option>
            <option value="archived">{t("archived")}</option>
          </select>
        </Field>
        <Field label={t("sortOrderLabel")}>
          <input
            className="input"
            type="number"
            value={sortOrder}
            onChange={(e) => setSortOrder(Number(e.target.value))}
          />
        </Field>
      </div>

      <Field label={t("description")}>
        <textarea
          className="input min-h-[90px]"
          value={description}
          onChange={(e) => setDescription(e.target.value)}
        />
      </Field>
      <Field label={t("body")}>
        <textarea
          className="input min-h-[120px]"
          value={bodyText}
          onChange={(e) => setBodyText(e.target.value)}
        />
      </Field>

      <div className="grid gap-3 md:grid-cols-2">
        <Field label={t("cover")}>
          <div className="flex gap-2">
            <input
              className="input flex-1"
              value={coverImage}
              onChange={(e) => setCoverImage(e.target.value)}
            />
            <UploadButton
              token={token}
              accept="image/*"
              onUploaded={(u) => {
                setCoverImage(u);
              }}
            />
          </div>
        </Field>
        <Field label={t("fileUrl")}>
          <p className="mb-1 text-xs text-neutral-500">
            {rtype === "video" ? t("adminVideoFileHint") : null}
          </p>
          <div className="flex gap-2">
            <input
              className="input flex-1"
              value={fileUrl}
              onChange={(e) => setFileUrl(e.target.value)}
            />
            <UploadButton
              token={token}
              accept={
                rtype === "video"
                  ? "video/*,.mp4,.webm,.mov,.mkv,.m4v,.ogv"
                  : undefined
              }
              onUploaded={(u, file) => {
                setFileUrl(u);
                if (file?.type.startsWith("video/")) setRtype("video");
              }}
            />
          </div>
        </Field>
        <Field label={t("previewUrlLabel")}>
          <div className="flex gap-2">
            <input
              className="input flex-1"
              value={previewUrl}
              onChange={(e) => setPreviewUrl(e.target.value)}
            />
            <UploadButton
              token={token}
              accept={
                rtype === "video"
                  ? "video/*,.mp4,.webm,.mov,.mkv,.m4v,.ogv"
                  : undefined
              }
              onUploaded={(u, file) => {
                setPreviewUrl(u);
                if (file?.type.startsWith("video/")) setRtype("video");
              }}
            />
          </div>
        </Field>
        <Field label={t("externalUrl")}>
          <input
            className="input"
            value={externalUrl}
            onChange={(e) => setExternalUrl(e.target.value)}
          />
        </Field>
      </div>

      <Field label={`${t("recommended")} / ${t("badge")}`}>
        <div className="flex flex-col gap-2">
          <label className="flex items-center gap-2 text-sm text-neutral-300">
            <input
              type="checkbox"
              checked={isRecommended}
              onChange={(e) => setIsRecommended(e.target.checked)}
            />
            {t("recommended")}
          </label>
          <input
            className="input"
            value={badgeLabel}
            onChange={(e) => setBadgeLabel(e.target.value)}
          />
        </div>
      </Field>

      <div className="flex flex-wrap gap-4">
        <label className="flex items-center gap-2 text-sm text-neutral-300">
          <input
            type="checkbox"
            checked={isPublic}
            onChange={(e) => setIsPublic(e.target.checked)}
          />
          {t("public")}
        </label>
        <label className="flex items-center gap-2 text-sm text-neutral-300">
          <input
            type="checkbox"
            checked={isDownloadable}
            onChange={(e) => setIsDownloadable(e.target.checked)}
          />
          {t("downloadable")}
        </label>
      </div>

      <Field label={t("tagsCommaLabel")}>
        <input
          className="input"
          value={tags}
          onChange={(e) => setTags(e.target.value)}
        />
      </Field>

      <button
        type="button"
        className="rounded-xl bg-ark-gold px-6 py-3 font-semibold text-black"
        onClick={async () => {
          setErr(null);
          try {
            if (isNew) {
              await postJSON("/api/admin/resources", payload, token);
            } else {
              await putJSON(`/api/admin/resources/${id}`, payload, token);
            }
            nav(mode === "basename" ? ".." : `${adminUiPrefix}/resources`);
          } catch (e) {
            setErr(String(e));
          }
        }}
      >
        {t("save")}
      </button>

      <style>{`
        .input { width: 100%; border: 1px solid #1f1f1f; background: #070707; border-radius: 12px; padding: 10px 12px; }
      `}</style>
    </div>
  );
}

function Field({ label, children }: { label: string; children: ReactNode }) {
  return (
    <label className="block text-sm text-neutral-300">
      <div className="mb-1">{label}</div>
      {children}
    </label>
  );
}

function UploadButton({
  token,
  onUploaded,
  accept,
}: {
  token: string;
  onUploaded: (url: string, file?: File) => void;
  accept?: string;
}) {
  const t = useAdminT();
  return (
    <label className="inline-flex cursor-pointer items-center rounded-xl border border-ark-line px-3 py-2 text-xs hover:border-ark-gold">
      {t("uploadFile")}
      <input
        type="file"
        className="hidden"
        accept={accept}
        onChange={async (e) => {
          const f = e.target.files?.[0];
          if (!f) return;
          const r = await uploadFile(f, token);
          onUploaded(r.url, f);
          e.target.value = "";
        }}
      />
    </label>
  );
}
