"use client";

/**
 * Settings → Audit Slots (2026-11-10).
 * Admin / coordinator control of the audit-request time-slot rules that used to be hard-coded in
 * backend/src/audit-requests/services/audit-slots.service.ts: audits per time slot, daily cap, gap,
 * working hours, lunch, booking window, closed weekdays and closed dates (holidays).
 * The marketing request forms read these rules from the server, so changes apply within ~30 seconds.
 */
import React, { useEffect, useMemo, useState } from "react";
import toast from "react-hot-toast";
import {
  FiAlertTriangle,
  FiCalendar,
  FiClock,
  FiCoffee,
  FiLayers,
  FiLock,
  FiPlus,
  FiRotateCcw,
  FiSave,
  FiSliders,
  FiTrash2,
  FiXCircle,
} from "react-icons/fi";
import { AppToaster } from "../../../../components/AppToaster";
import {
  getSlotSettings,
  saveSlotSettings,
  type SlotSettings,
  type SlotSettingsResponse,
} from "@/lib/api/audit-request.api";

const WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const WEEKDAYS_LONG = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

const HALF_HOURS: string[] = Array.from({ length: 48 }, (_, i) => `${String(Math.floor(i / 2)).padStart(2, "0")}:${i % 2 ? "30" : "00"}`);
const toMin = (t: string) => {
  const [h, m] = t.split(":").map(Number);
  return h * 60 + m;
};
const label = (t: string) => {
  const m = toMin(t);
  const h = Math.floor(m / 60);
  return `${h % 12 || 12}:${String(m % 60).padStart(2, "0")} ${h >= 12 ? "PM" : "AM"}`;
};
const fmtDay = (d: string) =>
  new Date(d + "T00:00:00").toLocaleDateString("en-GB", { weekday: "short", day: "2-digit", month: "short", year: "numeric" });

export default function AuditSlotsSettingsPage() {
  const [data, setData] = useState<SlotSettingsResponse | null>(null);
  const [form, setForm] = useState<SlotSettings | null>(null);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [newDate, setNewDate] = useState("");
  const [newDateTo, setNewDateTo] = useState("");
  const [newReason, setNewReason] = useState("");
  const [showPast, setShowPast] = useState(false);

  const load = async () => {
    setLoading(true);
    try {
      const r = await getSlotSettings();
      setData(r);
      setForm(structuredClone(r.settings));
    } catch (e: any) {
      toast.error(e?.message || "Failed to load slot settings");
    } finally {
      setLoading(false);
    }
  };
  useEffect(() => {
    load();
  }, []);

  const dirty = useMemo(() => !!data && !!form && JSON.stringify(data.settings) !== JSON.stringify(form), [data, form]);
  const canEdit = !!data?.can_edit;
  const set = <K extends keyof SlotSettings>(k: K, v: SlotSettings[K]) => setForm((f) => (f ? { ...f, [k]: v } : f));

  // live preview of start times
  const startTimes = useMemo(() => {
    if (!form) return [];
    const out: string[] = [];
    for (let m = toMin(form.day_start); m <= toMin(form.last_start); m += 30) {
      if (m >= toMin(form.lunch_from) && m < toMin(form.lunch_to)) continue;
      out.push(`${String(Math.floor(m / 60)).padStart(2, "0")}:${String(m % 60).padStart(2, "0")}`);
    }
    return out;
  }, [form]);

  const today = data?.today ?? new Date().toISOString().slice(0, 10);
  const upcoming = (form?.closed_dates ?? []).filter((c) => c.date >= today);
  const past = (form?.closed_dates ?? []).filter((c) => c.date < today);

  const addClosed = () => {
    if (!form || !newDate) return toast.error("Pick a date first");
    const end = newDateTo && newDateTo > newDate ? newDateTo : newDate;
    const added: string[] = [];
    const d = new Date(newDate + "T00:00:00Z");
    const stop = new Date(end + "T00:00:00Z");
    let guard = 0;
    while (d <= stop && guard++ < 120) {
      added.push(d.toISOString().slice(0, 10));
      d.setUTCDate(d.getUTCDate() + 1);
    }
    const existing = new Set(form.closed_dates.map((c) => c.date));
    const fresh = added.filter((x) => !existing.has(x));
    if (!fresh.length) return toast("Already closed");
    set(
      "closed_dates",
      [...form.closed_dates, ...fresh.map((date) => ({ date, reason: newReason.trim() || undefined }))].sort((a, b) => a.date.localeCompare(b.date)),
    );
    setNewDate("");
    setNewDateTo("");
    setNewReason("");
    toast.success(`${fresh.length} date${fresh.length > 1 ? "s" : ""} closed — press Save to apply`);
  };

  const removeClosed = (date: string) => form && set("closed_dates", form.closed_dates.filter((c) => c.date !== date));

  const save = async () => {
    if (!form) return;
    if (toMin(form.last_start) < toMin(form.day_start)) return toast.error("Last start time must be after the first start time");
    if (toMin(form.lunch_to) < toMin(form.lunch_from)) return toast.error("Lunch end must be after lunch start");
    if (form.closed_weekdays.length >= 7) return toast.error("At least one weekday must stay open");
    setSaving(true);
    try {
      const r = await saveSlotSettings(form);
      setData(r);
      setForm(structuredClone(r.settings));
      toast.success("Slot settings saved — booking forms use them now");
    } catch (e: any) {
      toast.error(e?.message || "Save failed");
    } finally {
      setSaving(false);
    }
  };

  if (loading || !form || !data) {
    return (
      <div style={{ padding: 80, textAlign: "center", color: "#94a3b8" }}>
        <AppToaster />
        Loading slot settings…
      </div>
    );
  }

  const dis = !canEdit;

  return (
    <>
      <AppToaster />

      {/* Hero */}
      <div
        style={{
          position: "relative",
          overflow: "hidden",
          background: "linear-gradient(135deg,#0f766e 0%,#1e40af 55%,#7c3aed 100%)",
          borderRadius: 16,
          padding: "24px 28px",
          marginBottom: 18,
          color: "#fff",
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
          gap: 16,
          flexWrap: "wrap",
          boxShadow: "0 12px 30px -14px rgba(30,64,175,.6)",
        }}
      >
        <div aria-hidden style={{ position: "absolute", right: -40, top: -60, width: 220, height: 220, borderRadius: "50%", background: "rgba(255,255,255,.07)" }} />
        <div style={{ display: "flex", alignItems: "center", gap: 14, position: "relative" }}>
          <div style={{ width: 48, height: 48, borderRadius: 14, background: "rgba(255,255,255,.16)", display: "flex", alignItems: "center", justifyContent: "center" }}>
            <FiSliders size={23} />
          </div>
          <div>
            <h1 style={{ fontSize: 21, fontWeight: 700, margin: 0 }}>Audit slot settings</h1>
            <p style={{ fontSize: 13, margin: "4px 0 0", opacity: 0.85 }}>
              Open slots, daily limits, working hours and closed dates for audit requests · {data.timezone}
            </p>
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, position: "relative", flexWrap: "wrap" }}>
          {canEdit && (
            <button
              onClick={() => setForm(structuredClone(data.defaults))}
              style={heroBtn}
              title="Load the original built-in rules (press Save to apply)"
            >
              <FiRotateCcw size={14} /> Built-in defaults
            </button>
          )}
          {canEdit && dirty && (
            <button onClick={() => setForm(structuredClone(data.settings))} style={heroBtn}>
              <FiXCircle size={14} /> Discard
            </button>
          )}
          {canEdit && (
            <button
              onClick={save}
              disabled={!dirty || saving}
              style={{ ...heroBtn, background: dirty ? "#fff" : "rgba(255,255,255,.12)", color: dirty ? "#1e40af" : "#fff", fontWeight: 800, cursor: !dirty || saving ? "default" : "pointer" }}
            >
              <FiSave size={14} /> {saving ? "Saving…" : dirty ? "Save changes" : "Saved"}
            </button>
          )}
        </div>
      </div>

      {!data.saved && (
        <Banner tone="amber" icon={<FiAlertTriangle />}>
          Nothing saved yet. The booking forms use the built-in rules shown below. Press <b>Save changes</b> once to start managing them here.
        </Banner>
      )}
      {!canEdit && (
        <Banner tone="slate" icon={<FiLock />}>
          View only — admin, scheme or coordinator role is needed to change slot settings.
        </Banner>
      )}
      {data.saved && data.updated_at && (
        <div style={{ fontSize: 12, color: "#64748b", margin: "-4px 0 12px 2px" }}>
          Last saved {new Date(data.updated_at).toLocaleString("en-GB")} {data.updated_by ? `by ${data.updated_by}` : ""}
        </div>
      )}

      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(340px, 1fr))", gap: 16 }}>
        {/* Capacity */}
        <Card icon={<FiLayers />} grad={["#2563eb", "#7c3aed"]} title="Capacity" sub="How many audits can be booked">
          <Field label="Open slots per time" hint="Audits that may start at the same time (one per available auditor).">
            <Stepper value={form.slots_per_time} min={1} max={20} disabled={dis} onChange={(v) => set("slots_per_time", v)} />
          </Field>
          <Field label="Max audits per day" hint="A date shows as full once this many audits are booked.">
            <Stepper value={form.max_per_day} min={1} max={100} disabled={dis} onChange={(v) => set("max_per_day", v)} />
          </Field>
          <Field label="Gap between audits on the same slot" hint="Minimum minutes between two audits sharing one slot.">
            <Segmented value={String(form.gap_minutes)} disabled={dis} options={[{ v: "30", l: "30 min" }, { v: "60", l: "60 min" }]} onChange={(v) => set("gap_minutes", Number(v))} />
          </Field>
        </Card>

        {/* Hours */}
        <Card icon={<FiClock />} grad={["#0891b2", "#2563eb"]} title="Working hours" sub="Start times offered every 30 minutes">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <Field label="First start time">
              <TimeSelect value={form.day_start} disabled={dis} onChange={(v) => set("day_start", v)} />
            </Field>
            <Field label="Last start time">
              <TimeSelect value={form.last_start} disabled={dis} onChange={(v) => set("last_start", v)} />
            </Field>
            <Field label={<><FiCoffee size={12} /> Lunch from</>}>
              <TimeSelect value={form.lunch_from} disabled={dis} onChange={(v) => set("lunch_from", v)} />
            </Field>
            <Field label="Lunch to">
              <TimeSelect value={form.lunch_to} disabled={dis} onChange={(v) => set("lunch_to", v)} />
            </Field>
          </div>
          <div style={{ marginTop: 6 }}>
            <div style={{ fontSize: 11.5, fontWeight: 700, color: "#64748b", marginBottom: 6 }}>
              Preview — {startTimes.length} start times × {form.slots_per_time} slot{form.slots_per_time > 1 ? "s" : ""}
            </div>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 4 }}>
              {startTimes.map((t) => (
                <span key={t} style={{ fontSize: 10.5, fontWeight: 700, padding: "2px 7px", borderRadius: 6, background: "#eff6ff", color: "#1d4ed8", border: "1px solid #bfdbfe" }}>
                  {label(t)}
                </span>
              ))}
              {!startTimes.length && <span style={{ fontSize: 12, color: "#dc2626" }}>No start times — check the hours.</span>}
            </div>
          </div>
        </Card>

        {/* Window + weekdays */}
        <Card icon={<FiCalendar />} grad={["#059669", "#0f766e"]} title="Booking window & weekdays" sub="Which dates marketing can pick">
          <Field label="Booking window" hint={`Today plus this many days (today = ${fmtDay(today)}).`}>
            <Stepper value={form.window_days} min={0} max={60} disabled={dis} suffix="days" onChange={(v) => set("window_days", v)} />
          </Field>
          <Field label="Closed every week" hint="Tap a day to close / open it.">
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
              {WEEKDAYS.map((w, i) => {
                const closed = form.closed_weekdays.includes(i);
                return (
                  <button
                    key={w}
                    disabled={dis}
                    title={`${WEEKDAYS_LONG[i]} — ${closed ? "closed" : "open"}`}
                    onClick={() =>
                      set("closed_weekdays", closed ? form.closed_weekdays.filter((d) => d !== i) : [...form.closed_weekdays, i].sort())
                    }
                    style={{
                      width: 50,
                      padding: "8px 0",
                      borderRadius: 10,
                      border: `1.5px solid ${closed ? "#fecaca" : "#a7f3d0"}`,
                      background: closed ? "#fef2f2" : "#ecfdf5",
                      color: closed ? "#b91c1c" : "#047857",
                      fontSize: 12,
                      fontWeight: 800,
                      cursor: dis ? "default" : "pointer",
                    }}
                  >
                    {w}
                    <div style={{ fontSize: 9, fontWeight: 700, marginTop: 2, opacity: 0.8 }}>{closed ? "CLOSED" : "OPEN"}</div>
                  </button>
                );
              })}
            </div>
          </Field>
        </Card>
      </div>

      {/* Closed dates */}
      <div style={{ marginTop: 16 }}>
        <Card icon={<FiXCircle />} grad={["#ef4444", "#b91c1c"]} title="Closed dates" sub="Holidays and days with no audits — no slot can be booked on these dates">
          {canEdit && (
            <div style={{ display: "flex", gap: 10, flexWrap: "wrap", alignItems: "flex-end", padding: 12, borderRadius: 12, background: "#f8fafc", border: "1px dashed #cbd5e1", marginBottom: 14 }}>
              <Field label="From date">
                <input type="date" value={newDate} min={today} onChange={(e) => setNewDate(e.target.value)} style={input} />
              </Field>
              <Field label="To date (optional)">
                <input type="date" value={newDateTo} min={newDate || today} onChange={(e) => setNewDateTo(e.target.value)} style={input} />
              </Field>
              <div style={{ flex: "1 1 220px" }}>
                <Field label="Reason (optional)">
                  <input value={newReason} maxLength={200} onChange={(e) => setNewReason(e.target.value)} placeholder="e.g. National Day holiday" style={{ ...input, width: "100%" }} />
                </Field>
              </div>
              <button onClick={addClosed} style={{ display: "inline-flex", alignItems: "center", gap: 6, height: 38, padding: "0 16px", borderRadius: 9, border: "none", background: "linear-gradient(135deg,#ef4444,#b91c1c)", color: "#fff", fontWeight: 700, fontSize: 12.5, cursor: "pointer", marginBottom: 12 }}>
                <FiPlus size={14} /> Close date{newDateTo && newDateTo > newDate ? "s" : ""}
              </button>
            </div>
          )}

          {upcoming.length === 0 ? (
            <div style={{ fontSize: 13, color: "#94a3b8", padding: "6px 2px" }}>No upcoming closed dates.</div>
          ) : (
            <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))", gap: 8 }}>
              {upcoming.map((c) => (
                <ClosedChip key={c.date} c={c} today={today} canEdit={canEdit} onRemove={() => removeClosed(c.date)} />
              ))}
            </div>
          )}

          {past.length > 0 && (
            <div style={{ marginTop: 12 }}>
              <button onClick={() => setShowPast(!showPast)} style={{ background: "none", border: "none", color: "#64748b", fontSize: 12, fontWeight: 700, cursor: "pointer", padding: 0 }}>
                {showPast ? "Hide" : "Show"} {past.length} past closed date{past.length > 1 ? "s" : ""}
              </button>
              {showPast && (
                <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))", gap: 8, marginTop: 8, opacity: 0.7 }}>
                  {past.map((c) => (
                    <ClosedChip key={c.date} c={c} today={today} canEdit={canEdit} onRemove={() => removeClosed(c.date)} />
                  ))}
                </div>
              )}
            </div>
          )}
        </Card>
      </div>

      {canEdit && dirty && (
        <div style={{ position: "sticky", bottom: 12, marginTop: 16, display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, padding: "12px 16px", borderRadius: 12, background: "#0f172a", color: "#fff", boxShadow: "0 12px 30px -10px rgba(15,23,42,.6)", flexWrap: "wrap" }}>
          <span style={{ fontSize: 13 }}>You have unsaved changes.</span>
          <div style={{ display: "flex", gap: 8 }}>
            <button onClick={() => setForm(structuredClone(data.settings))} style={{ ...heroBtn, border: "1px solid rgba(255,255,255,.25)" }}>Discard</button>
            <button onClick={save} disabled={saving} style={{ ...heroBtn, background: "linear-gradient(135deg,#2563eb,#7c3aed)", border: "none", fontWeight: 800 }}>
              <FiSave size={14} /> {saving ? "Saving…" : "Save changes"}
            </button>
          </div>
        </div>
      )}
    </>
  );
}

// ───────────── small pieces ─────────────
const heroBtn: React.CSSProperties = {
  display: "inline-flex",
  alignItems: "center",
  gap: 7,
  padding: "9px 15px",
  borderRadius: 10,
  border: "1px solid rgba(255,255,255,.28)",
  background: "rgba(255,255,255,.12)",
  color: "#fff",
  fontSize: 13,
  fontWeight: 600,
  cursor: "pointer",
};
const input: React.CSSProperties = {
  height: 38,
  padding: "0 10px",
  borderRadius: 9,
  border: "1px solid #e2e8f0",
  fontSize: 13,
  color: "#0f172a",
  background: "#fff",
};

function Banner({ tone, icon, children }: { tone: "amber" | "slate"; icon: React.ReactNode; children: React.ReactNode }) {
  const c = tone === "amber" ? { bg: "#fffbeb", bd: "#fde68a", fg: "#92400e" } : { bg: "#f8fafc", bd: "#e2e8f0", fg: "#475569" };
  return (
    <div style={{ display: "flex", gap: 10, alignItems: "center", padding: "11px 14px", borderRadius: 12, background: c.bg, border: `1px solid ${c.bd}`, color: c.fg, fontSize: 13, marginBottom: 14 }}>
      {icon}
      <span>{children}</span>
    </div>
  );
}

function Card({ icon, grad, title, sub, children }: { icon: React.ReactNode; grad: [string, string]; title: string; sub?: string; children: React.ReactNode }) {
  return (
    <div style={{ background: "#fff", border: "1px solid #e2e8f0", borderRadius: 14, padding: 18, boxShadow: "0 4px 16px -10px rgba(15,23,42,.2)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: 14 }}>
        <div style={{ width: 36, height: 36, borderRadius: 10, background: `linear-gradient(135deg,${grad[0]},${grad[1]})`, color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 16, boxShadow: `0 4px 10px -4px ${grad[1]}` }}>
          {icon}
        </div>
        <div>
          <div style={{ fontSize: 15, fontWeight: 800, color: "#0f172a" }}>{title}</div>
          {sub && <div style={{ fontSize: 12, color: "#94a3b8" }}>{sub}</div>}
        </div>
      </div>
      {children}
    </div>
  );
}

function Field({ label, hint, children }: { label: React.ReactNode; hint?: string; children: React.ReactNode }) {
  return (
    <div style={{ marginBottom: 12 }}>
      <div style={{ fontSize: 12, fontWeight: 700, color: "#334155", marginBottom: 6, display: "flex", alignItems: "center", gap: 5 }}>{label}</div>
      {children}
      {hint && <div style={{ fontSize: 11, color: "#94a3b8", marginTop: 5 }}>{hint}</div>}
    </div>
  );
}

function Stepper({ value, min, max, onChange, disabled, suffix }: { value: number; min: number; max: number; onChange: (v: number) => void; disabled?: boolean; suffix?: string }) {
  const clamp = (v: number) => Math.max(min, Math.min(max, v));
  const btn: React.CSSProperties = { width: 38, height: 38, border: "none", background: "#f1f5f9", fontSize: 18, fontWeight: 700, color: "#334155", cursor: disabled ? "default" : "pointer" };
  return (
    <div style={{ display: "inline-flex", alignItems: "center", border: "1px solid #e2e8f0", borderRadius: 10, overflow: "hidden" }}>
      <button disabled={disabled || value <= min} onClick={() => onChange(clamp(value - 1))} style={btn} aria-label="Decrease">−</button>
      <input
        type="number"
        value={value}
        min={min}
        max={max}
        disabled={disabled}
        onChange={(e) => onChange(clamp(Number(e.target.value) || min))}
        style={{ width: 64, height: 38, border: "none", textAlign: "center", fontSize: 16, fontWeight: 800, color: "#1e40af", outline: "none", background: "#fff" }}
      />
      {suffix && <span style={{ fontSize: 12, color: "#64748b", paddingRight: 8 }}>{suffix}</span>}
      <button disabled={disabled || value >= max} onClick={() => onChange(clamp(value + 1))} style={btn} aria-label="Increase">+</button>
    </div>
  );
}

function Segmented({ value, options, onChange, disabled }: { value: string; options: { v: string; l: string }[]; onChange: (v: string) => void; disabled?: boolean }) {
  return (
    <div style={{ display: "inline-flex", padding: 3, borderRadius: 10, background: "#f1f5f9", border: "1px solid #e2e8f0" }}>
      {options.map((o) => {
        const on = o.v === value;
        return (
          <button
            key={o.v}
            disabled={disabled}
            onClick={() => onChange(o.v)}
            style={{ padding: "7px 16px", borderRadius: 8, border: "none", background: on ? "#fff" : "transparent", color: on ? "#1e40af" : "#64748b", fontSize: 12.5, fontWeight: 800, cursor: disabled ? "default" : "pointer", boxShadow: on ? "0 1px 4px rgba(15,23,42,.12)" : "none" }}
          >
            {o.l}
          </button>
        );
      })}
    </div>
  );
}

function TimeSelect({ value, onChange, disabled }: { value: string; onChange: (v: string) => void; disabled?: boolean }) {
  return (
    <select value={value} disabled={disabled} onChange={(e) => onChange(e.target.value)} style={{ ...input, width: "100%", fontWeight: 700 }}>
      {HALF_HOURS.map((t) => (
        <option key={t} value={t}>
          {label(t)}
        </option>
      ))}
    </select>
  );
}

function ClosedChip({ c, today, canEdit, onRemove }: { c: { date: string; reason?: string }; today: string; canEdit: boolean; onRemove: () => void }) {
  const isToday = c.date === today;
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "9px 12px", borderRadius: 11, background: "#fff", border: "1px solid #fecaca", borderLeft: "4px solid #ef4444" }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 800, color: "#0f172a" }}>
          {fmtDay(c.date)}
          {isToday && <span style={{ marginLeft: 6, fontSize: 10, fontWeight: 800, color: "#b91c1c", background: "#fee2e2", padding: "1px 6px", borderRadius: 99 }}>TODAY</span>}
        </div>
        <div style={{ fontSize: 11.5, color: "#64748b", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }} title={c.reason || ""}>
          {c.reason || "Closed"}
        </div>
      </div>
      {canEdit && (
        <button onClick={onRemove} title="Re-open this date" style={{ border: "none", background: "#fef2f2", color: "#b91c1c", width: 30, height: 30, borderRadius: 8, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}>
          <FiTrash2 size={14} />
        </button>
      )}
    </div>
  );
}
