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, 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;
  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, 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. Those play here, but the
                files are several times larger and older Macs may struggle. Pick 1080p
                for H.264, which plays anywhere. 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>
            </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>
      )}
    </>
  );
}

