import { useEffect, useState } from "react";
import {
  checkPrereqs, importTakeoutCsv, pickLibraryFolder, pickTakeoutFile, previewTakeoutImport,
} from "../api";
import { APPEARANCE_MODES, type Appearance } from "../hooks/useAppearance";
import {
  QUALITIES, STREAM_QUALITIES, SUB_LANGS,
  type ImportPreview, type Prereqs, type Quality,
} from "../types";
import TakeoutGuide from "./TakeoutGuide";
import {
  BTN_PRIMARY, CONTROL_H, Dialog, HELP, ICON_BTN, LABEL, SectionHeading, Segmented, SUBPANEL,
} from "./ui";

interface Props {
  onClose: () => void;
  onImported: (count: number) => void;
  appearance: Appearance;
  onAppearance: (a: Appearance) => void;
  quality: Quality;
  onQuality: (q: Quality) => void;
  streamQuality: Quality;
  onStreamQuality: (q: Quality) => void;
  subLang: string;
  onSubLang: (l: string) => void;
  onError: (message: string) => void;
}

const SELECT =
  `w-full ${CONTROL_H} cursor-pointer rounded-lg border border-slate-300 bg-white px-2 ` +
  "text-[12px] outline-none dark:border-slate-700 dark:bg-slate-800";

function StatusRow({ label, value }: { label: string; value: string | null }) {
  return (
    <div className="flex items-start justify-between gap-4 border-b border-slate-200 py-2 last:border-b-0 dark:border-slate-800">
      <span className={LABEL}>{label}</span>
      <span
        className={`text-right text-[12px] ${
          value ? "text-slate-600 dark:text-slate-300" : "text-red-600 dark:text-red-400"
        }`}
      >
        {value ?? "Not found"}
      </span>
    </div>
  );
}

export default function Settings({
  onClose, onImported, appearance, onAppearance, quality, onQuality,
  streamQuality, onStreamQuality, subLang, onSubLang, onError,
}: Props) {
  const [prereqs, setPrereqs] = useState<Prereqs | null>(null);
  const [pending, setPending] = useState<{ path: string; preview: ImportPreview } | null>(null);
  const [busy, setBusy] = useState(false);

  const load = () => checkPrereqs().then(setPrereqs).catch(() => setPrereqs(null));
  useEffect(() => { load(); }, []);

  const startImport = async () => {
    try {
      const path = await pickTakeoutFile();
      if (!path) return;
      setPending({ path, preview: await previewTakeoutImport(path) });
    } catch (e) {
      onError(String(e));
    }
  };

  const confirmImport = async () => {
    if (!pending) return;
    setBusy(true);
    try {
      const n = await importTakeoutCsv(pending.path);
      setPending(null);
      onImported(n);
    } catch (e) {
      setPending(null);
      onError(String(e));
    } finally {
      setBusy(false);
    }
  };

  const pickFolder = async () => {
    try {
      if (await pickLibraryFolder()) load();
    } catch (e) {
      onError(String(e));
    }
  };

  const missing = prereqs && (!prereqs.yt_dlp || !prereqs.ffmpeg);
  const p = pending?.preview;
  const destructive = !!p && (p.removed_channels > 0 || p.removed_downloads > 0);

  return (
    <>
      <div
        className="fixed inset-0 z-[70] flex items-center justify-center bg-slate-950/70 p-5"
        onClick={onClose}
      >
        <div
          role="dialog"
          aria-modal="true"
          onClick={(e) => e.stopPropagation()}
          className="flex max-h-[82vh] w-full max-w-lg flex-col rounded-2xl border border-slate-300
                     bg-white shadow-2xl dark:border-slate-700 dark:bg-slate-900"
        >
          <header className="flex items-center justify-between gap-2 border-b border-slate-200 px-5 py-4 dark:border-slate-800">
            <h2 className="text-[15px] font-semibold tracking-tight">Settings</h2>
            <button
              onClick={onClose}
              title="Close settings"
              aria-label="Close settings"
              className={`${ICON_BTN} text-slate-500 hover:bg-slate-100 hover:text-slate-900
                          dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-white`}
            >
              <svg viewBox="0 0 24 24" className="size-4" fill="none" stroke="currentColor" strokeWidth="2">
                <path strokeLinecap="round" d="M6 6l12 12M18 6L6 18" />
              </svg>
            </button>
          </header>

          <div className="min-h-0 flex-1 overflow-y-auto">
            <section className="border-b border-slate-200 px-5 py-4 dark:border-slate-800">
              <SectionHeading>Get your subscriptions</SectionHeading>
              <p className={`mt-1.5 ${HELP}`}>
                YouTube has no public API for someone else's subscription list, so FlightTube
                reads the export Google gives you. It takes about two minutes.
              </p>
              <div className={`mt-3 ${SUBPANEL}`}>
                <TakeoutGuide />
              </div>
            </section>

            <section className="border-b border-slate-200 px-5 py-4 dark:border-slate-800">
              <SectionHeading>Import</SectionHeading>
              <p className={`mt-1.5 ${HELP}`}>
                Importing <b>replaces</b> your current subscription list — the CSV becomes the
                whole truth. Channels no longer in it are removed along with their videos and
                downloads. You'll see exactly what goes before anything is deleted.
              </p>
              <button onClick={startImport} className={`${BTN_PRIMARY} mt-3 cursor-pointer`}>
                Import subscriptions.csv
              </button>
            </section>

            <section className="border-b border-slate-200 px-5 py-4 dark:border-slate-800">
              <SectionHeading>Download quality</SectionHeading>
              <p className={`mt-1.5 ${HELP}`}>
                Above 1080p YouTube only serves VP9 and AV1, and <b>4K AV1 currently plays
                back with visible artefacts in this player</b> — the downloaded file is
                fine, it is the built-in decoder that struggles. 1080p gets H.264, which
                plays cleanly and is several times smaller. Audio is AAC at every setting.
              </p>
              <label className="mt-2 grid grid-cols-[92px_1fr] items-center gap-2">
                <span className={LABEL}>Quality</span>
                <select
                  value={quality}
                  onChange={(e) => onQuality(e.target.value as Quality)}
                  className={SELECT}
                >
                  {QUALITIES.map((q) => (
                    <option key={q.value} value={q.value}>
                      {q.label}
                    </option>
                  ))}
                </select>
              </label>

              <label className="mt-2 grid grid-cols-[92px_1fr] items-center gap-2">
                <span className={LABEL}>Streaming</span>
                <select
                  value={streamQuality}
                  onChange={(e) => onStreamQuality(e.target.value as Quality)}
                  className={SELECT}
                >
                  {STREAM_QUALITIES.map((q) => (
                    <option key={q.value} value={q.value}>
                      {q.label}
                    </option>
                  ))}
                </select>
              </label>
              <p className={`mt-2 ${HELP}`}>
                Streaming quality applies when you play something you have not downloaded.
                Best lets the player adapt to your connection; a fixed height pins it.
              </p>

              <label className="mt-3 grid grid-cols-[92px_1fr] items-center gap-2">
                <span className={LABEL}>Subtitles</span>
                <select
                  value={subLang}
                  onChange={(e) => onSubLang(e.target.value)}
                  className={SELECT}
                >
                  {SUB_LANGS.map((l) => (
                    <option key={l.value} value={l.value}>
                      {l.label}
                    </option>
                  ))}
                </select>
              </label>
              <p className={`mt-2 ${HELP}`}>
                Shown automatically when a video has subtitles in this language, including
                YouTube's auto-generated ones, and saved alongside anything you download so
                they work offline. You can still switch tracks from the player.
              </p>
            </section>

            <section className="border-b border-slate-200 px-5 py-4 dark:border-slate-800">
              <SectionHeading>Appearance</SectionHeading>
              <div className="mt-2 flex items-center justify-between gap-3">
                <span className={LABEL}>Theme</span>
                <Segmented
                  value={appearance}
                  onChange={onAppearance}
                  options={APPEARANCE_MODES.map((m) => ({
                    value: m,
                    label: m[0].toUpperCase() + m.slice(1),
                  }))}
                />
              </div>
            </section>

            <section className="px-5 py-4">
              <SectionHeading>Status</SectionHeading>
              <div className="mt-2">
                <StatusRow label="yt-dlp" value={prereqs?.yt_dlp ?? null} />
                <StatusRow label="ffmpeg" value={prereqs?.ffmpeg ?? null} />
                <div className="flex items-start justify-between gap-4 py-2">
                  <span className={LABEL}>Library</span>
                  <button
                    onClick={pickFolder}
                    className="cursor-pointer break-all text-right text-[12px] text-sky-600
                               underline underline-offset-2 hover:text-sky-500 dark:text-sky-400"
                  >
                    {prereqs?.library_path ?? "…"}
                  </button>
                </div>
              </div>

              <p className={`mt-2 ${HELP}`}>
                yt-dlp and ffmpeg ship inside the app, so nothing needs installing. A copy
                on your system is used instead if one is present, which is how you can run
                a newer yt-dlp than the bundled one.
              </p>

              {missing && (
                <div className="mt-2 rounded-lg border border-red-500/30 bg-red-500/5 p-3">
                  <p className="text-[11px] leading-snug text-red-700 dark:text-red-300">
                    A bundled tool is missing, which should not happen. Reinstalling the app
                    will restore it; meanwhile <code>brew install yt-dlp ffmpeg</code> also
                    works.
                  </p>
                </div>
              )}
            </section>
          </div>
        </div>
      </div>

      {pending && p && (
        <Dialog
          title={destructive ? "Replace your subscriptions?" : "Import subscriptions"}
          onCancel={() => setPending(null)}
          onConfirm={busy ? undefined : confirmImport}
          confirmLabel={destructive ? "Replace" : "Import"}
          destructive={destructive}
        >
          <p>
            The file lists <b>{p.incoming}</b> subscription{p.incoming === 1 ? "" : "s"}, which
            will become your complete list.
          </p>
          {destructive ? (
            <ul className="mt-2 space-y-1">
              <li>
                <b>{p.removed_channels}</b> channel{p.removed_channels === 1 ? "" : "s"} no longer
                subscribed will be removed
              </li>
              <li>
                <b>{p.removed_videos}</b> of their video{p.removed_videos === 1 ? "" : "s"} will
                disappear from your feed
              </li>
              {p.removed_downloads > 0 && (
                <li className="text-red-600 dark:text-red-400">
                  <b>{p.removed_downloads}</b> downloaded file
                  {p.removed_downloads === 1 ? "" : "s"} will be deleted from disk
                </li>
              )}
            </ul>
          ) : (
            <p className="mt-2">Nothing currently stored will be removed.</p>
          )}
        </Dialog>
      )}
    </>
  );
}

