import { useEffect, useMemo, useState } from "react";
import { apiGet, apiPost } from "../api";
import { Empty, Loading, PageHead } from "../components/ui";
import {
  IconCalendar,
  IconCheck,
  IconChevron,
  IconClock,
  IconDisc,
  IconEmby,
  IconMusic,
  IconPlay,
  IconRefresh,
  IconSettings,
  IconTrash,
} from "../components/icons";
import { useToast } from "../lib/toast";

interface PrerollSettings {
  preroll_enabled: boolean;
  preroll_active_dir: string;
  preroll_inactive_dir: string;
  preroll_state_file: string;
  preroll_weekday: number;
  preroll_time: string;
}

interface PrerollTaskStatus {
  enabled: boolean;
  next_run_at: string | null;
  due_now: boolean;
  schedule_error: string | null;
  runtime: {
    running: boolean;
    last_message: string | null;
  };
  state: {
    last_rotation?: string | null;
    active_file?: string | null;
  };
}

interface CleanupTask {
  id: string;
  section: "emby" | "navidrome" | string;
  section_title: string;
  title: string;
  description: string;
  supports_run: boolean;
  supports_automation: boolean;
  requires?: string | null;
  run_label: string;
  settings: {
    automation_enabled: boolean;
    weekday: number;
    time: string;
    retention_days: number;
  };
  status: {
    last_run_at?: string;
    last_status?: string;
    last_result?: { message?: string } | null;
  };
  next_run_at: string | null;
  schedule_error: string | null;
}

const WEEKDAYS = [
  { value: 0, label: "Monday" },
  { value: 1, label: "Tuesday" },
  { value: 2, label: "Wednesday" },
  { value: 3, label: "Thursday" },
  { value: 4, label: "Friday" },
  { value: 5, label: "Saturday" },
  { value: 6, label: "Sunday" },
];

const SECTION_ORDER = ["emby", "navidrome"];

export default function Tasks() {
  const toast = useToast();
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [prerollSaving, setPrerollSaving] = useState(false);
  const [prerollBusy, setPrerollBusy] = useState(false);
  const [tasks, setTasks] = useState<CleanupTask[]>([]);
  const [expanded, setExpanded] = useState<Record<string, boolean>>({ preroll: true });
  const [prerollSettings, setPrerollSettings] = useState<PrerollSettings | null>(null);
  const [prerollStatus, setPrerollStatus] = useState<PrerollTaskStatus | null>(null);

  async function load() {
    setLoading(true);
    try {
      const [preroll, cleanup] = await Promise.all([
        apiGet<{ settings: PrerollSettings; status: PrerollTaskStatus }>("/api/tasks/preroll"),
        apiGet<{ tasks: CleanupTask[] }>("/api/tasks/cleanup"),
      ]);
      setPrerollSettings(preroll.settings);
      setPrerollStatus(preroll.status);
      setTasks(cleanup.tasks);
      setExpanded((current) => {
        const next = { ...current };
        for (const task of cleanup.tasks) {
          if (!(task.id in next)) next[task.id] = false;
        }
        return next;
      });
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    load();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const sections = useMemo(() => {
    const grouped = new Map<string, { title: string; tasks: CleanupTask[] }>();
    for (const task of tasks) {
      if (!grouped.has(task.section)) grouped.set(task.section, { title: task.section_title, tasks: [] });
      grouped.get(task.section)!.tasks.push(task);
    }
    const orderedKeys = [...SECTION_ORDER.filter((key) => grouped.has(key)), ...[...grouped.keys()].filter((key) => !SECTION_ORDER.includes(key))];
    return orderedKeys.map((key) => ({ key, ...grouped.get(key)! }));
  }, [tasks]);

  function setPreroll<K extends keyof PrerollSettings>(key: K, value: PrerollSettings[K]) {
    setPrerollSettings((current) => (current ? { ...current, [key]: value } : current));
  }

  function setTask(taskId: string, patch: Partial<CleanupTask["settings"]>) {
    setTasks((current) => current.map((task) => (task.id === taskId ? { ...task, settings: { ...task.settings, ...patch } } : task)));
  }

  async function savePreroll() {
    if (!prerollSettings) return;
    setPrerollSaving(true);
    try {
      await apiPost("/api/settings", prerollSettings);
      toast("System task settings saved", "ok");
      await load();
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setPrerollSaving(false);
    }
  }

  async function saveCleanupTasks() {
    setSaving(true);
    try {
      const payload = Object.fromEntries(tasks.map((task) => [task.id, task.settings]));
      const res = await apiPost<{ tasks: CleanupTask[] }>("/api/tasks/cleanup/settings", { emby_tasks: payload });
      setTasks(res.tasks);
      toast("Task automation saved", "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setSaving(false);
    }
  }

  async function runPrerollNow() {
    setPrerollBusy(true);
    try {
      const res = await apiPost<{ status: PrerollTaskStatus; result: { message: string } }>("/api/tasks/preroll/run");
      setPrerollStatus(res.status);
      toast(res.result.message || "Preroll rotated", "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setPrerollBusy(false);
    }
  }

  async function runTask(taskId: string, dryRun: boolean) {
    try {
      await apiPost("/api/tasks/cleanup/settings", { emby_tasks: Object.fromEntries(tasks.map((task) => [task.id, task.settings])) });
      const res = await apiPost<{ tasks: CleanupTask[]; result: { message: string } }>(`/api/tasks/cleanup/${taskId}/run`, { dryRun });
      setTasks(res.tasks);
      toast(res.result.message || "Task completed", "ok");
    } catch (e: any) {
      toast(e.message, "err");
    }
  }

  function taskIcon(section: string) {
    if (section === "emby") return <IconEmby />;
    if (section === "navidrome") return <IconMusic />;
    return <IconDisc />;
  }

  function requirementHint(task: CleanupTask) {
    if (task.requires === "emby_server_data") {
      return "This one needs Emby's internal server-data path mounted into HomelabToolkit before it can safely inspect or delete files.";
    }
    if (task.requires === "music_root") {
      return "This task needs the configured music root mounted into HomelabToolkit so it can inspect and update your library files.";
    }
    return null;
  }

  if (loading || !prerollSettings) return <Loading />;

  return (
    <>
      <div className="row between" style={{ alignItems: "flex-start" }}>
        <PageHead title="Tasks" icon={<IconTrash />} />
        <div className="row gap-sm">
          <button className="btn btn-sm" onClick={load}>
            <IconRefresh /> Reload
          </button>
          <button className="btn btn-primary" onClick={saveCleanupTasks} disabled={saving}>
            {saving ? <span className="spinner" /> : <IconCheck />} Save Task Automation
          </button>
        </div>
      </div>

      <div className="section-label">System</div>
      <div className="task-stack" style={{ marginBottom: 28 }}>
        <div className="panel task-panel">
          <button className="task-toggle" onClick={() => setExpanded((current) => ({ ...current, preroll: !current.preroll }))}>
            <div className="stat-icon" style={{ width: 32, height: 32, borderRadius: 9 }}>
              <IconCalendar />
            </div>
            <div className="task-meta grow">
              <div className="task-title-row">
                <h3>Rotate Emby prerolls</h3>
                <span className={`badge ${prerollStatus?.enabled ? "badge-ok" : ""}`}>{prerollStatus?.enabled ? "scheduled" : "disabled"}</span>
              </div>
              <div className="task-summary">
                Weekly on {WEEKDAYS.find((day) => day.value === prerollSettings.preroll_weekday)?.label ?? "Monday"} at {prerollSettings.preroll_time}
              </div>
            </div>
            <IconChevron className={`nav-caret ${expanded.preroll ? "open" : ""}`} />
          </button>
          {expanded.preroll ? (
            <div className="panel-body col task-body" style={{ gap: 14 }}>
              <div className="row gap-sm" style={{ flexWrap: "wrap" }}>
                <button className="btn btn-sm btn-primary" onClick={runPrerollNow} disabled={prerollBusy || prerollStatus?.runtime.running}>
                  {prerollBusy || prerollStatus?.runtime.running ? <span className="spinner" /> : <IconPlay />} Run now
                </button>
                <button className="btn btn-sm" onClick={savePreroll} disabled={prerollSaving}>
                  {prerollSaving ? <span className="spinner" /> : <IconSettings />} Save schedule
                </button>
                {prerollStatus?.next_run_at ? <span className="badge">Next run: {prerollStatus.next_run_at}</span> : null}
                {prerollStatus?.state?.last_rotation ? <span className="badge">Last run: {prerollStatus.state.last_rotation}</span> : null}
              </div>
              <label className="chip" style={{ cursor: "pointer", width: "fit-content" }}>
                <input type="checkbox" checked={prerollSettings.preroll_enabled} onChange={(e) => setPreroll("preroll_enabled", e.target.checked)} /> Enable automation
              </label>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: 14 }}>
                <div className="field">
                  <label className="field-label">
                    <IconCalendar /> Weekday
                  </label>
                  <select className="input" value={prerollSettings.preroll_weekday} onChange={(e) => setPreroll("preroll_weekday", Number(e.target.value))}>
                    {WEEKDAYS.map((day) => (
                      <option key={day.value} value={day.value}>
                        {day.label}
                      </option>
                    ))}
                  </select>
                </div>
                <div className="field">
                  <label className="field-label">
                    <IconClock /> Time
                  </label>
                  <input className="input" type="time" value={prerollSettings.preroll_time} onChange={(e) => setPreroll("preroll_time", e.target.value)} />
                </div>
              </div>
              <div className="field">
                <label className="field-label">Active preroll folder</label>
                <input className="input" value={prerollSettings.preroll_active_dir} onChange={(e) => setPreroll("preroll_active_dir", e.target.value)} />
              </div>
              <div className="field">
                <label className="field-label">Inactive preroll folder</label>
                <input className="input" value={prerollSettings.preroll_inactive_dir} onChange={(e) => setPreroll("preroll_inactive_dir", e.target.value)} />
              </div>
              <div className="field">
                <label className="field-label">State file</label>
                <input className="input" value={prerollSettings.preroll_state_file} onChange={(e) => setPreroll("preroll_state_file", e.target.value)} />
              </div>
              {prerollStatus?.schedule_error ? <p className="hint" style={{ margin: 0, color: "var(--bad)" }}>Schedule error: {prerollStatus.schedule_error}</p> : null}
              {prerollStatus?.runtime.last_message ? <p className="hint" style={{ margin: 0 }}>Last result: {prerollStatus.runtime.last_message}</p> : null}
            </div>
          ) : null}
        </div>
      </div>

      {sections.map((section) => (
        <div key={section.key} style={{ marginBottom: 28 }}>
          <div className="section-label">{section.title}</div>
          <div className="task-stack">
            {section.tasks.map((task) => {
              const hint = requirementHint(task);
              return (
                <div className="panel task-panel" key={task.id}>
                  <button className="task-toggle" onClick={() => setExpanded((current) => ({ ...current, [task.id]: !current[task.id] }))}>
                    <div className="stat-icon" style={{ width: 32, height: 32, borderRadius: 9 }}>
                      {taskIcon(task.section)}
                    </div>
                    <div className="task-meta grow">
                      <div className="task-title-row">
                        <h3>{task.title}</h3>
                        <span className={`badge ${task.supports_run ? "badge-ok" : "badge-warn"}`}>{task.supports_run ? "ready" : "needs mount"}</span>
                        {task.settings.automation_enabled && task.supports_automation ? <span className="badge badge-accent">automation on</span> : null}
                      </div>
                      <div className="task-summary">
                        {task.description}
                        {task.next_run_at ? ` · Next run ${task.next_run_at}` : ""}
                      </div>
                    </div>
                    <IconChevron className={`nav-caret ${expanded[task.id] ? "open" : ""}`} />
                  </button>
                  {expanded[task.id] ? (
                    <div className="panel-body col task-body" style={{ gap: 14 }}>
                      <div className="row gap-sm" style={{ flexWrap: "wrap" }}>
                        <button className="btn btn-sm" onClick={() => runTask(task.id, true)} disabled={!task.supports_run}>
                          <IconPlay /> Preview
                        </button>
                        <button className="btn btn-sm btn-primary" onClick={() => runTask(task.id, false)} disabled={!task.supports_run}>
                          <IconTrash /> {task.run_label}
                        </button>
                        {task.status?.last_run_at ? <span className="badge">Last run: {task.status.last_run_at}</span> : null}
                        {task.status?.last_status ? <span className={`badge ${task.status.last_status === "ok" ? "badge-ok" : "badge-bad"}`}>{task.status.last_status}</span> : null}
                      </div>
                      {task.supports_automation ? (
                        <>
                          <label className="chip" style={{ cursor: "pointer", width: "fit-content" }}>
                            <input
                              type="checkbox"
                              checked={task.settings.automation_enabled}
                              onChange={(e) => setTask(task.id, { automation_enabled: e.target.checked })}
                            />{" "}
                            Enable weekly automation
                          </label>
                          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 14 }}>
                            <div className="field">
                              <label className="field-label">Weekday</label>
                              <select className="input" value={task.settings.weekday} onChange={(e) => setTask(task.id, { weekday: Number(e.target.value) })}>
                                {WEEKDAYS.map((day) => (
                                  <option key={day.value} value={day.value}>
                                    {day.label}
                                  </option>
                                ))}
                              </select>
                            </div>
                            <div className="field">
                              <label className="field-label">Time</label>
                              <input className="input" type="time" value={task.settings.time} onChange={(e) => setTask(task.id, { time: e.target.value })} />
                            </div>
                            {"retention_days" in task.settings ? (
                              <div className="field">
                                <label className="field-label">Retention days</label>
                                <input
                                  className="input"
                                  type="number"
                                  min={1}
                                  max={3650}
                                  value={task.settings.retention_days}
                                  onChange={(e) => setTask(task.id, { retention_days: Number(e.target.value) || 1 })}
                                />
                              </div>
                            ) : null}
                          </div>
                        </>
                      ) : (
                        <p className="hint" style={{ margin: 0 }}>
                          This task cannot be automated from the current deployment.
                        </p>
                      )}
                      {task.schedule_error ? <p className="hint" style={{ margin: 0, color: "var(--bad)" }}>Schedule error: {task.schedule_error}</p> : null}
                      {task.status?.last_result?.message ? <p className="hint" style={{ margin: 0 }}>Last result: {task.status.last_result.message}</p> : null}
                      {hint ? <p className="hint" style={{ margin: 0 }}>{hint}</p> : null}
                    </div>
                  ) : null}
                </div>
              );
            })}
          </div>
        </div>
      ))}

      {!tasks.length ? <Empty icon={<IconTrash />}>No cleanup tasks available.</Empty> : null}
    </>
  );
}
