import { useState } from "react";
import { qk } from "../lib/queryKeys";
import { useTranslation } from "react-i18next";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Lock, Pencil, Plus, Trash2 } from "lucide-react";
import Modal from "./Modal";
import { useConfirm } from "./ConfirmProvider";
import { api, type DownloadProfile, type DownloadSpec } from "../lib/api";
import { inputCls } from "./ui/form";

const HEIGHTS = [null, 2160, 1440, 1080, 720, 480, 360];

const BLANK: DownloadSpec = {
  mode: "av",
  max_height: 720,
  container: "mp4",
  audio_format: "m4a",
  vcodec: null,
  embed_subs: false,
  embed_chapters: true,
  embed_thumbnail: true,
  sponsorblock: false,
};

function Check({
  label,
  checked,
  onChange,
}: {
  label: string;
  checked: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <label className="flex items-center gap-2 text-sm cursor-pointer select-none">
      <input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
      {label}
    </label>
  );
}

export default function ProfileEditor({ onClose }: { onClose: () => void }) {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const confirm = useConfirm();
  const profilesQ = useQuery({ queryKey: qk.downloadProfiles(), queryFn: api.downloadProfiles });
  const profiles = profilesQ.data ?? [];
  const builtins = profiles.filter((p) => p.is_builtin);
  const mine = profiles.filter((p) => !p.is_builtin);

  const [editing, setEditing] = useState<DownloadProfile | null>(null);
  const [name, setName] = useState("");
  const [spec, setSpec] = useState<DownloadSpec>(BLANK);
  const [formOpen, setFormOpen] = useState(false);

  const invalidate = () => qc.invalidateQueries({ queryKey: qk.downloadProfiles() });
  const startNew = () => {
    setEditing(null);
    setName("");
    setSpec(BLANK);
    setFormOpen(true);
  };
  const startEdit = (p: DownloadProfile) => {
    setEditing(p);
    setName(p.name);
    setSpec({ ...BLANK, ...p.spec });
    setFormOpen(true);
  };

  const save = useMutation({
    mutationFn: () =>
      editing
        ? api.updateDownloadProfile(editing.id, { name, spec })
        : api.createDownloadProfile({ name, spec }),
    onSuccess: () => {
      invalidate();
      setFormOpen(false);
    },
  });
  const del = useMutation({
    mutationFn: (id: number) => api.deleteDownloadProfile(id),
    onSuccess: invalidate,
  });

  const onDelete = async (p: DownloadProfile) => {
    if (
      await confirm({
        title: t("downloads.profiles.delete"),
        message: t("downloads.profiles.deleteConfirm", { name: p.name }),
        confirmLabel: t("downloads.profiles.delete"),
        danger: true,
      })
    ) {
      del.mutate(p.id);
    }
  };

  const patch = (p: Partial<DownloadSpec>) => setSpec((s) => ({ ...s, ...p }));
  const set = (k: keyof DownloadSpec) => (e: React.ChangeEvent<HTMLSelectElement>) =>
    patch({ [k]: e.target.value === "" ? null : e.target.value } as Partial<DownloadSpec>);

  return (
    <Modal title={t("downloads.profiles.title")} onClose={onClose} maxWidth="max-w-xl">
      {/* Existing formats */}
      <div className="space-y-1.5 mb-4">
        <div className="text-xs uppercase tracking-wide text-muted">
          {t("downloads.profiles.builtin")}
        </div>
        {builtins.map((p) => (
          <div
            key={p.id}
            className="flex items-center gap-2 text-sm px-3 py-1.5 rounded-lg glass-card"
          >
            <Lock className="w-3.5 h-3.5 text-muted shrink-0" />
            <span className="flex-1 truncate">{p.name}</span>
          </div>
        ))}
        {mine.length > 0 && (
          <div className="text-xs uppercase tracking-wide text-muted pt-2">
            {t("downloads.profiles.yours")}
          </div>
        )}
        {mine.map((p) => (
          <div
            key={p.id}
            className="flex items-center gap-2 text-sm px-3 py-1.5 rounded-lg glass-card"
          >
            <span className="flex-1 truncate">{p.name}</span>
            <button
              onClick={() => startEdit(p)}
              title={t("downloads.actions.rename")}
              className="p-1 rounded hover:bg-surface text-muted hover:text-fg"
            >
              <Pencil className="w-3.5 h-3.5" />
            </button>
            <button
              onClick={() => onDelete(p)}
              title={t("downloads.profiles.delete")}
              className="p-1 rounded hover:bg-surface text-muted hover:text-red-400"
            >
              <Trash2 className="w-3.5 h-3.5" />
            </button>
          </div>
        ))}
      </div>

      {!formOpen ? (
        <button
          onClick={startNew}
          className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm font-medium bg-accent text-accent-fg hover:opacity-90 transition"
        >
          <Plus className="w-4 h-4" /> {t("downloads.profiles.new")}
        </button>
      ) : (
        <div className="rounded-xl border border-border p-4 space-y-3">
          <div>
            <label className="block text-sm font-medium mb-1">{t("downloads.profiles.name")}</label>
            <input
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder={t("downloads.profiles.namePlaceholder")}
              className={inputCls}
            />
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <label className="block text-sm font-medium mb-1">
                {t("downloads.profiles.mode")}
              </label>
              <select value={spec.mode} onChange={set("mode")} className={inputCls}>
                <option value="av">{t("downloads.profiles.modeAv")}</option>
                <option value="v">{t("downloads.profiles.modeV")}</option>
                <option value="a">{t("downloads.profiles.modeA")}</option>
              </select>
            </div>
            {spec.mode !== "a" ? (
              <div>
                <label className="block text-sm font-medium mb-1">
                  {t("downloads.profiles.quality")}
                </label>
                <select
                  value={spec.max_height ?? ""}
                  onChange={(e) =>
                    patch({ max_height: e.target.value === "" ? null : Number(e.target.value) })
                  }
                  className={inputCls}
                >
                  {HEIGHTS.map((h) => (
                    <option key={h ?? "best"} value={h ?? ""}>
                      {h ? `${h}p` : t("downloads.profiles.best")}
                    </option>
                  ))}
                </select>
              </div>
            ) : (
              <div>
                <label className="block text-sm font-medium mb-1">
                  {t("downloads.profiles.audioFormat")}
                </label>
                <select
                  value={spec.audio_format ?? "m4a"}
                  onChange={set("audio_format")}
                  className={inputCls}
                >
                  <option value="m4a">M4A</option>
                  <option value="mp3">MP3</option>
                  <option value="opus">Opus</option>
                </select>
              </div>
            )}
            {spec.mode !== "a" && (
              <>
                <div>
                  <label className="block text-sm font-medium mb-1">
                    {t("downloads.profiles.container")}
                  </label>
                  <select
                    value={spec.container ?? "mp4"}
                    onChange={set("container")}
                    className={inputCls}
                  >
                    <option value="mp4">MP4</option>
                    <option value="mkv">MKV</option>
                    <option value="webm">WebM</option>
                  </select>
                </div>
                <div>
                  <label className="block text-sm font-medium mb-1">
                    {t("downloads.profiles.vcodec")}
                  </label>
                  <select value={spec.vcodec ?? ""} onChange={set("vcodec")} className={inputCls}>
                    <option value="">{t("downloads.profiles.any")}</option>
                    <option value="h264">H.264</option>
                    <option value="vp9">VP9</option>
                    <option value="av1">AV1</option>
                  </select>
                </div>
              </>
            )}
          </div>
          <div className="space-y-1.5 pt-1">
            {spec.mode !== "a" && (
              <Check
                label={t("downloads.profiles.embedSubs")}
                checked={spec.embed_subs}
                onChange={(v) => patch({ embed_subs: v })}
              />
            )}
            <Check
              label={t("downloads.profiles.embedChapters")}
              checked={spec.embed_chapters}
              onChange={(v) => patch({ embed_chapters: v })}
            />
            <Check
              label={t("downloads.profiles.embedThumbnail")}
              checked={spec.embed_thumbnail}
              onChange={(v) => patch({ embed_thumbnail: v })}
            />
            <Check
              label={t("downloads.profiles.sponsorblock")}
              checked={spec.sponsorblock}
              onChange={(v) => patch({ sponsorblock: v })}
            />
          </div>
          <div className="flex justify-end gap-2 pt-1">
            <button
              onClick={() => setFormOpen(false)}
              className="px-3 py-1.5 rounded-lg text-sm text-muted hover:text-fg hover:bg-surface transition"
            >
              {t("downloads.actions.cancel")}
            </button>
            <button
              onClick={() => save.mutate()}
              disabled={!name.trim() || save.isPending}
              className="px-3 py-1.5 rounded-lg text-sm font-medium bg-accent text-accent-fg hover:opacity-90 disabled:opacity-50 transition"
            >
              {editing ? t("downloads.profiles.save") : t("downloads.profiles.create")}
            </button>
          </div>
        </div>
      )}
    </Modal>
  );
}
