"use client";

/**
 * WaterLogAdminPanel — the main Water Log admin dashboard.
 *
 * Visual language: "Field Almanac." A rugged, light-themed almanac of
 * the day's water use. The aesthetic borrows from USDA agricultural
 * bulletins and old USGS survey markers — serif display type (Fraunces)
 * for titles, mono (Fragment Mono) for measurements, and a single
 * custom SVG (WaterGauge) that becomes the visual signature of the
 * whole feature.
 *
 *   - No purple-gradient SaaS look.
 *   - No glassmorphism. Strong borders, not soft shadows.
 *   - Field-notebook tone: precise, agricultural, slightly utilitarian.
 *   - Cream + forest + clay palette pulled from the project's existing
 *     `forest` / `sage` / `gold` tokens so the panel sits naturally
 *     inside the rest of /admin.
 *
 * The component is "use client" because it owns the filters and the
 * entry-adding modals. All DB access happens through server actions in
 * `src/actions/water-log/admin.ts`.
 */

import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import {
  createWaterHeadgate,
  createWaterUser,
  deleteWaterHeadgate,
  deleteWaterUser,
  getWaterEntries,
  regenerateHeadgateToken,
  resetWaterIrrigatorPin,
  type AdminEntry,
  type AdminHeadgate,
  type AdminIrrigator,
} from "@/actions/water-log/admin";
import {
  downloadWaterLogCSV,
  filterWaterLogEntries,
  formatDailyWaterReport,
  isInIrrigationSeason,
  shapeWaterLogEntry,
  type IrrigationSeasonSettings,
  type WaterLogFilter,
  type WaterLogReportRow,
} from "@/lib/water-log-reporting";
import { WaterGauge, SeasonMark } from "@/components/water/icons";
import { AdminButton } from "./design-system";
import { formatDate, formatDateTime } from "@/lib/format-date";

type Props = {
  initialUsers: AdminIrrigator[];
  initialHeadgates: AdminHeadgate[];
  initialEntries: AdminEntry[];
  brandId: string;
  canManage: boolean;
};

const DEFAULT_SEASON: IrrigationSeasonSettings = {
  seasonStartMonth: 3,
  seasonStartDay: 15,
  seasonEndMonth: 10,
  seasonEndDay: 15,
};

export default function WaterLogAdminPanel({
  initialUsers,
  initialHeadgates,
  initialEntries,
  brandId,
  canManage,
}: Props) {
  const router = useRouter();
  const [headgates, setHeadgates] = useState<AdminHeadgate[]>(initialHeadgates);
  const [users, setUsers] = useState<AdminIrrigator[]>(initialUsers);
  const [entries] = useState<AdminEntry[]>(initialEntries);
  const [toast, setToast] = useState<{ msg: string; kind: "ok" | "err" } | null>(null);

  // ── Forms ──────────────────────────────────────────────────────────
  const [showAddHg, setShowAddHg] = useState(false);
  const [newHg, setNewHg] = useState({ name: "", unit: "CFS", notes: "" });
  const [savingHg, setSavingHg] = useState(false);

  const [showAddUser, setShowAddUser] = useState(false);
  const [newUser, setNewUser] = useState({
    name: "",
    role: "irrigator" as "irrigator" | "water_admin",
    lang: "en",
    phone: "",
  });
  const [savingUser, setSavingUser] = useState(false);
  const [newPin, setNewPin] = useState<{ name: string; pin: string } | null>(null);
  const [resetPin, setResetPin] = useState<{ name: string; pin: string } | null>(
    null,
  );

  // ── Filters ────────────────────────────────────────────────────────
  const [filterDateFrom, setFilterDateFrom] = useState("");
  const [filterDateTo, setFilterDateTo] = useState("");
  const [filterHeadgate, setFilterHeadgate] = useState("");
  const [filterUser, setFilterUser] = useState("");
  const [filterVia, setFilterVia] = useState("");
  const [csvLoading, setCsvLoading] = useState(false);

  // `today` and the human-readable date are read from the clock; compute
  // them in the browser only to avoid hydration mismatches. The setStates
  // are wrapped in an async IIFE so the effect body does not call setState
  // synchronously (avoids the cascading-renders ESLint rule).
  const [today, setToday] = useState<string>("");
  const [todayLabel, setTodayLabel] = useState<string>("");
  useEffect(() => {
    void (async () => {
      const now = new Date();
      setToday(now.toISOString().slice(0, 10));
      setTodayLabel(formatDate(now));
    })();
  }, []);

  // ── Season + report settings (localStorage) ───────────────────────
  const [showReportSettings, setShowReportSettings] = useState(false);
  const [seasonStart, setSeasonStart] = useState<IrrigationSeasonSettings>(() => {
    if (typeof window === "undefined") return DEFAULT_SEASON;
    try {
      const saved = localStorage.getItem("wl_season_settings:v1");
      return saved ? { ...DEFAULT_SEASON, ...JSON.parse(saved) } : DEFAULT_SEASON;
    } catch {
      return DEFAULT_SEASON;
    }
  });
  const [recipientName, setRecipientName] = useState(() =>
    typeof window !== "undefined" ? localStorage.getItem("wl_recipient_name") ?? "" : "",
  );

  // ── Derived data ──────────────────────────────────────────────────
  const inSeason = useMemo(
    () => isInIrrigationSeason(new Date(), seasonStart),
    [seasonStart],
  );

  const todayEntries = useMemo(
    () =>
      today
        ? entries.filter((e) => (e.logged_date ?? e.logged_at.slice(0, 10)) === today)
        : [],
    [entries, today],
  );
  const todayTotal = todayEntries.reduce((s, e) => s + e.measurement, 0);

  const lastEntryByHeadgate = useMemo(() => {
    const map = new Map<string, AdminEntry>();
    for (const e of entries) {
      const existing = map.get(e.headgate_id);
      if (!existing || e.logged_at > existing.logged_at) {
        map.set(e.headgate_id, e);
      }
    }
    return map;
  }, [entries]);

  const filteredEntries = useMemo(() => {
    return entries.filter((e) => {
      if (filterDateFrom && e.logged_at < filterDateFrom) return false;
      if (filterDateTo && e.logged_at > filterDateTo + "T23:59:59.999Z") return false;
      if (filterHeadgate && e.headgate_id !== filterHeadgate) return false;
      if (filterUser && e.user_id !== filterUser) return false;
      if (filterVia && e.submitted_via !== filterVia) return false;
      return true;
    });
  }, [entries, filterDateFrom, filterDateTo, filterHeadgate, filterUser, filterVia]);

  // ── Toast helper ──────────────────────────────────────────────────
  function notify(msg: string, kind: "ok" | "err" = "ok") {
    setToast({ msg, kind });
    setTimeout(() => setToast(null), 2800);
  }

  // ── Handlers ──────────────────────────────────────────────────────
  async function handleAddHg(e: React.FormEvent) {
    e.preventDefault();
    if (!newHg.name.trim()) return;
    setSavingHg(true);
    const res = await createWaterHeadgate(brandId, newHg.name.trim(), newHg.unit, {
      notes: newHg.notes.trim() || null,
    });
    if (res.success && res.headgate) {
      setHeadgates((prev) => [res.headgate!, ...prev]);
      setNewHg({ name: "", unit: "CFS", notes: "" });
      setShowAddHg(false);
      notify("Headgate added");
    } else {
      notify(res.error ?? "Failed", "err");
    }
    setSavingHg(false);
  }

  async function handleDeleteHg(h: AdminHeadgate) {
    if (!window.confirm(`Delete "${h.name}"? Existing log entries will be preserved.`)) return;
    const res = await deleteWaterHeadgate(h.id);
    if (res.success) {
      setHeadgates((prev) => prev.filter((x) => x.id !== h.id));
      notify("Headgate removed");
    } else {
      notify(res.error ?? "Failed", "err");
    }
  }

  async function handleRegenerateToken(h: AdminHeadgate) {
    if (
      !window.confirm(
        `Regenerate QR token for "${h.name}"? Existing printed QR codes will stop working.`,
      )
    ) return;
    const res = await regenerateHeadgateToken(h.id);
    if (res.success && res.token) {
      setHeadgates((prev) =>
        prev.map((x) => (x.id === h.id ? { ...x, headgate_token: res.token! } : x)),
      );
      notify("Token regenerated");
    } else {
      notify(res.error ?? "Failed", "err");
    }
  }

  async function handleAddUser(e: React.FormEvent) {
    e.preventDefault();
    if (!newUser.name.trim()) return;
    setSavingUser(true);
    const res = await createWaterUser(
      brandId,
      newUser.name.trim(),
      newUser.role,
      newUser.lang,
      newUser.phone.trim() || null,
    );
    if (res.success && res.user && res.pin) {
      setUsers((prev) => [res.user!, ...prev]);
      setNewPin({ name: res.user.name, pin: res.pin });
      setNewUser({ name: "", role: "irrigator", lang: "en", phone: "" });
      setShowAddUser(false);
      notify("User created");
    } else {
      notify(res.error ?? "Failed", "err");
    }
    setSavingUser(false);
  }

  async function handleResetPin(u: AdminIrrigator) {
    if (!window.confirm(`Reset PIN for "${u.name}"? Their current PIN will stop working.`))
      return;
    const res = await resetWaterIrrigatorPin(u.id);
    if (res.success && res.pin) {
      setResetPin({ name: u.name, pin: res.pin });
      notify("PIN reset");
    } else {
      notify(res.error ?? "Failed", "err");
    }
  }

  async function handleDeleteUser(u: AdminIrrigator) {
    if (!window.confirm(`Deactivate "${u.name}"? Their existing log entries will be preserved.`))
      return;
    const res = await deleteWaterUser(u.id);
    if (res.success) {
      setUsers((prev) => prev.map((x) => (x.id === u.id ? { ...x, active: false } : x)));
      notify("User deactivated");
    } else {
      notify(res.error ?? "Failed", "err");
    }
  }

  async function handlePreviewReport() {
    const all = await getWaterEntries(brandId, 1000);
    const todayRows: WaterLogReportRow[] = all
      .filter(
        (e) => (e.logged_date ?? e.logged_at.slice(0, 10)) === today,
      )
      .map(shapeWaterLogEntry);
    const report = formatDailyWaterReport(todayRows, {
      recipientName: recipientName || undefined,
      previewMode: true,
    });
    if (!report) {
      notify(`No entries today — report would be skipped (season: ${inSeason ? "in" : "out"}).`);
      return;
    }
    // The browser's `alert` blocks; the modal preview is the better UX in
    // a future iteration, but alert is dependency-free today.
    window.alert(`Daily Report — ${inSeason ? "in season" : "out of season"}\n\n${report}`);
  }

  async function handleExportCSV() {
    setCsvLoading(true);
    try {
      const all = await getWaterEntries(brandId, 5000);
      const shaped: WaterLogReportRow[] = all.map(shapeWaterLogEntry);
      const filters: WaterLogFilter = {
        dateFrom: filterDateFrom || undefined,
        dateTo: filterDateTo || undefined,
        headgateId: filterHeadgate || undefined,
        userId: filterUser || undefined,
        submittedVia: filterVia || undefined,
      };
      const filtered = filterWaterLogEntries(shaped, filters);
      downloadWaterLogCSV(`water-log-${today}.csv`, filtered);
      notify(`Exported ${filtered.length} entries`);
    } finally {
      setCsvLoading(false);
    }
  }

  function persistSeason(s: IrrigationSeasonSettings) {
    setSeasonStart(s);
    try {
      localStorage.setItem("wl_season_settings:v1", JSON.stringify(s));
    } catch {}
  }

  // ── Render ────────────────────────────────────────────────────────
  return (
    <div className="relative">
      {/* Top tabs */}
      <div className="mb-6 flex flex-wrap items-center gap-2">
        <Link href="/admin/water-log/headgates">
          <AdminButton variant="secondary" size="sm" icon={<QrIcon />}>
            QR Codes
          </AdminButton>
        </Link>
        <Link href="/admin/water-log/settings">
          <AdminButton variant="secondary" size="sm" icon={<GearIcon />}>
            Settings
          </AdminButton>
        </Link>
        <Link href="/water/admin" target="_blank" rel="noopener noreferrer">
          <AdminButton variant="secondary" size="sm" icon={<FieldIcon />}>
            Field Admin ↗
          </AdminButton>
        </Link>
      </div>

      {/* ── Today's Summary ─────────────────────────────────────── */}
      <section className="relative overflow-hidden rounded-2xl border border-[#d4d9d3] bg-[#fdfaf2] shadow-[0_1px_0_rgba(0,0,0,0.04)]">
        {/* Subtle topographic pattern overlay */}
        <div
          aria-hidden
          className="pointer-events-none absolute inset-0 opacity-[0.18]"
          style={{
            backgroundImage:
              "repeating-linear-gradient(45deg, transparent 0 14px, rgba(26,77,46,0.06) 14px 15px), repeating-linear-gradient(-45deg, transparent 0 14px, rgba(202,138,4,0.04) 14px 15px)",
          }}
        />

        <div className="relative grid grid-cols-1 gap-6 p-6 md:grid-cols-[200px_1fr] md:gap-8">
          {/* Hero gauge */}
          <div className="flex flex-col items-center justify-center gap-2">
            <div className="text-[10px] font-mono uppercase tracking-[0.3em] text-[#1a4d2e]/70">
              Tuxedo Ditch Co.
            </div>
            <WaterGauge
              size={120}
              level={
                todayEntries.length === 0
                  ? null
                  : Math.min(1, todayTotal / Math.max(todayTotal, 100))
              }
              status="open"
              ariaLabel="Today's water level"
            />
            <div className="text-[10px] font-mono uppercase tracking-[0.3em] text-[#1a4d2e]/70">
              Vol. {todayTotal.toFixed(2)} {headgates[0]?.unit ?? "CFS"}
            </div>
          </div>

          <div className="flex flex-col gap-4">
            <div>
              <h2
                className="text-2xl font-semibold tracking-tight text-[#1a4d2e]"
                style={{ fontFamily: "var(--font-display, Georgia, serif)" }}
              >
                Today&apos;s Summary
              </h2>
              <p className="mt-1 flex items-center gap-2 text-sm text-[#57694e]">
                <SeasonMark inSeason={inSeason} size={14} />
                {inSeason ? (
                  <span className="font-medium text-[#1a4d2e]">In irrigation season</span>
                ) : (
                  <span className="font-medium text-[#a16207]">Outside irrigation season</span>
                )}
                <span className="text-[#57694e]/60">·</span>
                <span className="font-mono text-[#1d1d1f]">
                  {todayEntries.length} {todayEntries.length === 1 ? "entry" : "entries"}
                </span>
                <span className="text-[#57694e]/60">·</span>
                <span className="text-[#57694e]">
                  {todayLabel}
                </span>
              </p>
            </div>

            <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
              <StatTile
                label="Total volume"
                value={todayTotal.toFixed(2)}
                unit={headgates[0]?.unit ?? "CFS"}
                accent
              />
              <StatTile
                label="Headgates"
                value={headgates.filter((h) => h.active).length.toString()}
                unit={`of ${headgates.length}`}
              />
              <StatTile
                label="Active irrigators"
                value={users.filter((u) => u.active).length.toString()}
                unit={`of ${users.length}`}
              />
              <StatTile
                label="Last entry"
                value={
                  todayEntries.length
                    ? formatDateTime(todayEntries[0].logged_at).split(",").pop()?.trim() ?? "—"
                    : "—"
                }
                unit=""
                mono
              />
            </div>

            <div className="flex flex-wrap gap-2">
              <AdminButton
                variant="secondary"
                size="sm"
                icon={<ReportIcon />}
                onClick={handlePreviewReport}
              >
                Preview Report
              </AdminButton>
              <AdminButton
                variant={showReportSettings ? "primary" : "secondary"}
                size="sm"
                icon={<GearIcon />}
                onClick={() => setShowReportSettings((v) => !v)}
              >
                Report Settings
              </AdminButton>
            </div>

            {showReportSettings && (
              <ReportSettingsPanel
                season={seasonStart}
                onSeasonChange={persistSeason}
                recipientName={recipientName}
                onRecipientNameChange={(v) => {
                  setRecipientName(v);
                  try {
                    localStorage.setItem("wl_recipient_name", v);
                  } catch {}
                }}
              />
            )}
          </div>
        </div>
      </section>

      {/* ── Headgates ───────────────────────────────────────────── */}
      <SectionHeader
        index="§ 01"
        title="Headgates"
        subtitle="Physical gates in the ditch network. Each gets a printable QR code so field workers can scan to log a reading without typing the gate name."
        action={
          canManage ? (
            <AdminButton size="sm" onClick={() => setShowAddHg((v) => !v)}>
              {showAddHg ? "Cancel" : "+ Add Headgate"}
            </AdminButton>
          ) : null
        }
      />

      {showAddHg && canManage && (
        <form
          onSubmit={handleAddHg}
          className="mb-4 grid grid-cols-1 gap-3 rounded-xl border border-[#d4d9d3] bg-white p-4 sm:grid-cols-[1fr_120px_1fr_auto]"
        >
          <Input
            label="Name"
            value={newHg.name}
            onChange={(v) => setNewHg((s) => ({ ...s, name: v }))}
            placeholder="e.g. North Field Gate 1"
            required
            autoFocus
          />
          <Select
            label="Unit"
            value={newHg.unit}
            onChange={(v) => setNewHg((s) => ({ ...s, unit: v }))}
            options={["CFS", "GPM", "Inches", "AF/Day", "gal", "ac-ft"]}
          />
          <Input
            label="Notes"
            value={newHg.notes}
            onChange={(v) => setNewHg((s) => ({ ...s, notes: v }))}
            placeholder="Location, GPS, contact…"
          />
          <div className="flex items-end">
            <AdminButton type="submit" disabled={savingHg} isLoading={savingHg} fullWidth>
              Add
            </AdminButton>
          </div>
        </form>
      )}

      {headgates.length === 0 ? (
        <EmptyState
          icon={<WaterGauge size={36} level={null} status="open" />}
          title="No headgates yet"
          body="Add a headgate to start logging. Each one gets a unique QR code you can print and post at the gate."
        />
      ) : (
        <ul className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
          {headgates.map((h) => {
            const last = lastEntryByHeadgate.get(h.id);
            const level =
              last && h.high_threshold
                ? Math.min(1, last.measurement / Number(h.high_threshold))
                : null;
            return (
              <li
                key={h.id}
                className="group rounded-xl border border-[#d4d9d3] bg-white p-4 transition hover:border-[#1a4d2e]/40 hover:shadow-[0_4px_16px_rgba(26,77,46,0.08)]"
              >
                <div className="flex items-start gap-3">
                  <WaterGauge
                    size={36}
                    level={level}
                    status={h.status as "open" | "closed" | "maintenance"}
                    className="mt-0.5"
                  />
                  <div className="min-w-0 flex-1">
                    <div className="flex items-center gap-2">
                      <h3 className="truncate font-semibold text-[#1d1d1f]">
                        {h.name}
                      </h3>
                      <StatusPill
                        kind={
                          !h.active
                            ? "inactive"
                            : h.status === "closed"
                              ? "closed"
                              : h.status === "maintenance"
                                ? "warn"
                                : "active"
                        }
                      />
                    </div>
                    <p className="mt-0.5 font-mono text-[11px] uppercase tracking-wider text-[#86868b]">
                      Unit: {h.unit} · Token: {h.headgate_token.slice(0, 8)}…
                    </p>
                    {last ? (
                      <p className="mt-2 text-sm text-[#57694e]">
                        Last:{" "}
                        <span className="font-mono font-semibold text-[#1d1d1f]">
                          {last.measurement} {h.unit}
                        </span>{" "}
                        <span className="text-[#86868b]">
                          by {last.user_name} · {formatDateTime(last.logged_at)}
                        </span>
                      </p>
                    ) : (
                      <p className="mt-2 text-sm italic text-[#86868b]">
                        No readings yet
                      </p>
                    )}
                    {(h.high_threshold != null || h.low_threshold != null) && (
                      <p className="mt-1 font-mono text-[11px] text-[#57694e]">
                        {h.high_threshold != null && (
                          <>Hi&nbsp;≥&nbsp;{h.high_threshold}&nbsp;&nbsp;</>
                        )}
                        {h.low_threshold != null && (
                          <>Lo&nbsp;≤&nbsp;{h.low_threshold}</>
                        )}
                      </p>
                    )}
                  </div>
                </div>

                {canManage && (
                  <div className="mt-3 flex flex-wrap items-center justify-between gap-1 border-t border-[#e8ebe8] pt-3 text-[11px]">
                    <button type="button"
                      onClick={() => router.push(`/admin/water-log/headgates/${h.id}`)}
                      className="font-medium text-[#1a4d2e] hover:underline"
                    >
                      Edit →
                    </button>
                    <div className="flex items-center gap-2">
                      <button type="button"
                        onClick={() => handleRegenerateToken(h)}
                        className="text-[#57694e] hover:text-[#1a4d2e]"
                      >
                        Rotate token
                      </button>
                      <span className="text-[#d4d9d3]">·</span>
                      <button type="button"
                        onClick={() => handleDeleteHg(h)}
                        className="text-[#b91c1c] hover:text-[#7f1d1d]"
                      >
                        Delete
                      </button>
                    </div>
                  </div>
                )}
              </li>
            );
          })}
        </ul>
      )}

      {/* ── Water Users ──────────────────────────────────────────── */}
      <SectionHeader
        index="§ 02"
        title="Water Users"
        subtitle="The people who log readings in the field. Each gets a 4-digit PIN. Admin role can manage headgates, users, and entries; Irrigators can only submit."
        action={
          canManage ? (
            <AdminButton size="sm" onClick={() => setShowAddUser((v) => !v)}>
              {showAddUser ? "Cancel" : "+ Add User"}
            </AdminButton>
          ) : null
        }
      />

      {newPin && (
        <PinBanner
          title={`New PIN for ${newPin.name}`}
          pin={newPin.pin}
          onDismiss={() => setNewPin(null)}
        />
      )}
      {resetPin && (
        <PinBanner
          title={`Reset PIN for ${resetPin.name}`}
          pin={resetPin.pin}
          tone="warn"
          onDismiss={() => setResetPin(null)}
        />
      )}

      {showAddUser && canManage && (
        <form
          onSubmit={handleAddUser}
          className="mb-4 grid grid-cols-1 gap-3 rounded-xl border border-[#d4d9d3] bg-white p-4 sm:grid-cols-[1fr_140px_120px_1fr_auto]"
        >
          <Input
            label="Name"
            value={newUser.name}
            onChange={(v) => setNewUser((s) => ({ ...s, name: v }))}
            placeholder="Full name"
            required
            autoFocus
          />
          <Select
            label="Role"
            value={newUser.role}
            onChange={(v) =>
              setNewUser((s) => ({ ...s, role: v as "irrigator" | "water_admin" }))
            }
            options={[
              { value: "irrigator", label: "Irrigator" },
              { value: "water_admin", label: "Admin" },
            ]}
          />
          <Select
            label="Language"
            value={newUser.lang}
            onChange={(v) => setNewUser((s) => ({ ...s, lang: v }))}
            options={[
              { value: "en", label: "English" },
              { value: "es", label: "Español" },
            ]}
          />
          <Input
            label="Phone"
            value={newUser.phone}
            onChange={(v) => setNewUser((s) => ({ ...s, phone: v }))}
            placeholder="+1…"
            type="tel"
          />
          <div className="flex items-end">
            <AdminButton type="submit" disabled={savingUser} isLoading={savingUser} fullWidth>
              Add
            </AdminButton>
          </div>
        </form>
      )}

      <RoleLegend />

      {users.length === 0 ? (
        <EmptyState
          icon={<UserIcon />}
          title="No water users yet"
          body="Add an irrigator or admin to grant field access. Their PIN is generated automatically — write it down before dismissing."
        />
      ) : (
        <ul className="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
          {users.map((u) => (
            <li
              key={u.id}
              className={`flex items-center gap-3 rounded-xl border bg-white px-3 py-2 ${
                u.active ? "border-[#d4d9d3]" : "border-[#d4d9d3] bg-[#f5f3ef] opacity-70"
              }`}
            >
              <Avatar name={u.name} role={u.role} />
              <div className="min-w-0 flex-1">
                <p className="truncate font-semibold text-[#1d1d1f]">{u.name}</p>
                <p className="font-mono text-[11px] text-[#86868b]">
                  {u.role === "water_admin" ? "ADMIN" : "IRRIGATOR"} · {u.language_preference === "es" ? "ES" : "EN"}
                  {u.last_used_at ? ` · seen ${formatDate(u.last_used_at)}` : " · never signed in"}
                </p>
              </div>
              {canManage && (
                <div className="flex shrink-0 items-center gap-1 text-[11px]">
                  <button type="button"
                    onClick={() => handleResetPin(u)}
                    className="text-[#57694e] hover:text-[#1a4d2e]"
                  >
                    PIN
                  </button>
                  <span className="text-[#d4d9d3]">·</span>
                  <button type="button"
                    onClick={() => handleDeleteUser(u)}
                    className="text-[#b91c1c] hover:text-[#7f1d1d]"
                  >
                    Off
                  </button>
                </div>
              )}
            </li>
          ))}
        </ul>
      )}

      {/* ── Recent Entries ──────────────────────────────────────── */}
      <SectionHeader
        index="§ 03"
        title="Recent Entries"
        subtitle="The last {n} readings logged from the field or the admin panel. Use the filters to narrow, then export to CSV."
        action={
          <AdminButton
            size="sm"
            onClick={handleExportCSV}
            isLoading={csvLoading}
            icon={<DownloadIcon />}
          >
            Export CSV
          </AdminButton>
        }
      />

      <div className="mb-3 flex flex-wrap items-center gap-2 rounded-xl border border-[#d4d9d3] bg-white p-2.5">
        <FilterChip label="From">
          <input
            type="date"
            value={filterDateFrom}
            onChange={(e) => setFilterDateFrom(e.target.value)}
            className="border-0 bg-transparent text-sm text-[#1d1d1f] outline-none"
            aria-label="Filter: from date"
          />
        </FilterChip>
        <FilterChip label="To">
          <input
            type="date"
            value={filterDateTo}
            onChange={(e) => setFilterDateTo(e.target.value)}
            className="border-0 bg-transparent text-sm text-[#1d1d1f] outline-none"
            aria-label="Filter: to date"
          />
        </FilterChip>
        <FilterChip label="Headgate">
          <select
            value={filterHeadgate}
            onChange={(e) => setFilterHeadgate(e.target.value)}
            className="border-0 bg-transparent text-sm text-[#1d1d1f] outline-none"
            aria-label="Filter: headgate"
          >
            <option value="">All</option>
            {headgates.map((h) => (
              <option key={h.id} value={h.id}>
                {h.name}
              </option>
            ))}
          </select>
        </FilterChip>
        <FilterChip label="User">
          <select
            value={filterUser}
            onChange={(e) => setFilterUser(e.target.value)}
            className="border-0 bg-transparent text-sm text-[#1d1d1f] outline-none"
            aria-label="Filter: user"
          >
            <option value="">All</option>
            {users.map((u) => (
              <option key={u.id} value={u.id}>
                {u.name}
              </option>
            ))}
          </select>
        </FilterChip>
        <FilterChip label="Via">
          <select
            value={filterVia}
            onChange={(e) => setFilterVia(e.target.value)}
            className="border-0 bg-transparent text-sm text-[#1d1d1f] outline-none"
            aria-label="Filter: submission source"
          >
            <option value="">All</option>
            <option value="field">Field</option>
            <option value="admin">Admin</option>
            <option value="app">App</option>
          </select>
        </FilterChip>
        {(filterDateFrom ||
          filterDateTo ||
          filterHeadgate ||
          filterUser ||
          filterVia) && (
          <button type="button"
            onClick={() => {
              setFilterDateFrom("");
              setFilterDateTo("");
              setFilterHeadgate("");
              setFilterUser("");
              setFilterVia("");
            }}
            className="text-xs font-medium text-[#57694e] hover:text-[#1a4d2e] hover:underline"
          >
            Clear filters
          </button>
        )}
        <span className="ml-auto font-mono text-[11px] text-[#86868b]">
          {filteredEntries.length} of {entries.length} entries
        </span>
      </div>

      {filteredEntries.length === 0 ? (
        <EmptyState
          icon={<TableIcon />}
          title="No entries match"
          body={entries.length === 0 ? "No readings have been logged yet." : "Try clearing the filters above."}
        />
      ) : (
        <div className="overflow-hidden rounded-xl border border-[#d4d9d3] bg-white">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-[#d4d9d3] bg-[#f5f3ef] text-left font-mono text-[10px] uppercase tracking-[0.15em] text-[#57694e]">
                <th className="px-4 py-2.5">When</th>
                <th className="px-4 py-2.5">User</th>
                <th className="px-4 py-2.5">Headgate</th>
                <th className="px-4 py-2.5 text-right">Measurement</th>
                <th className="px-4 py-2.5 text-right">Gallons</th>
                <th className="px-4 py-2.5">Method</th>
                <th className="px-4 py-2.5">Via</th>
                <th className="px-4 py-2.5"></th>
              </tr>
            </thead>
            <tbody>
              {filteredEntries.map((e, i) => (
                <tr
                  key={e.id}
                  className={`group border-b border-[#e8ebe8] last:border-0 transition-colors hover:bg-[#fdfaf2] ${
                    i % 2 === 0 ? "" : "bg-[#fafaf7]"
                  }`}
                >
                  <td className="whitespace-nowrap px-4 py-2.5 font-mono text-xs text-[#57694e]">
                    {formatDateTime(e.logged_at)}
                  </td>
                  <td className="whitespace-nowrap px-4 py-2.5 text-[#1d1d1f]">
                    {e.user_name}
                  </td>
                  <td className="whitespace-nowrap px-4 py-2.5 text-[#1d1d1f]">
                    {e.headgate_name}
                  </td>
                  <td className="whitespace-nowrap px-4 py-2.5 text-right font-mono font-semibold text-[#1d1d1f]">
                    {e.measurement}{" "}
                    <span className="text-[10px] text-[#86868b]">{e.unit}</span>
                  </td>
                  <td className="whitespace-nowrap px-4 py-2.5 text-right font-mono text-[#57694e]">
                    {e.total_gallons != null ? e.total_gallons.toFixed(1) : "—"}
                  </td>
                  <td className="whitespace-nowrap px-4 py-2.5 font-mono text-[11px] uppercase text-[#57694e]">
                    {e.method}
                  </td>
                  <td className="whitespace-nowrap px-4 py-2.5">
                    <span
                      className={`inline-block rounded px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wider ${
                        e.submitted_via === "field"
                          ? "bg-[#dcfce7] text-[#15803d]"
                          : "bg-[#e8ebe8] text-[#57694e]"
                      }`}
                    >
                      {e.submitted_via}
                    </span>
                  </td>
                  <td className="px-4 py-2.5 text-right text-[11px]">
                    <button type="button"
                      onClick={() =>
                        router.push(`/admin/water-log/entries/${e.id}`)
                      }
                      className="font-medium text-[#1a4d2e] opacity-0 transition-opacity group-hover:opacity-100 hover:underline"
                    >
                      Edit →
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Toast */}
      {toast && (
        <div
          role="status"
          aria-live="polite"
          className={`fixed bottom-6 right-6 z-50 rounded-xl px-4 py-3 font-medium shadow-lg transition-all ${
            toast.kind === "ok"
              ? "border border-[#15803d] bg-[#dcfce7] text-[#15803d]"
              : "border border-[#b91c1c] bg-[#fee2e2] text-[#b91c1c]"
          }`}
        >
          {toast.msg}
        </div>
      )}
    </div>
  );
}

// ─── Sub-components ──────────────────────────────────────────────────────

function SectionHeader({
  index,
  title,
  subtitle,
  action,
}: {
  index: string;
  title: string;
  subtitle: string;
  action?: React.ReactNode;
}) {
  return (
    <header className="mb-3 mt-10 flex items-start justify-between gap-4 border-b border-[#d4d9d3] pb-3">
      <div>
        <div className="font-mono text-[10px] uppercase tracking-[0.3em] text-[#1a4d2e]">
          {index}
        </div>
        <h2
          className="mt-0.5 text-xl font-semibold text-[#1d1d1f]"
          style={{ fontFamily: "var(--font-display, Georgia, serif)" }}
        >
          {title}
        </h2>
        <p className="mt-0.5 max-w-xl text-xs text-[#57694e]">{subtitle}</p>
      </div>
      {action}
    </header>
  );
}

function StatTile({
  label,
  value,
  unit,
  accent,
  mono,
}: {
  label: string;
  value: string;
  unit: string;
  accent?: boolean;
  mono?: boolean;
}) {
  return (
    <div
      className={`rounded-lg border p-3 ${
        accent
          ? "border-[#1a4d2e]/30 bg-[#f0fdf4]"
          : "border-[#d4d9d3] bg-white"
      }`}
    >
      <div className="text-[10px] font-mono uppercase tracking-wider text-[#57694e]">
        {label}
      </div>
      <div className="mt-0.5 flex items-baseline gap-1">
        <span
          className={`text-lg font-semibold text-[#1a4d2e] ${
            mono ? "font-mono" : ""
          }`}
        >
          {value}
        </span>
        {unit && (
          <span className="font-mono text-[10px] uppercase text-[#57694e]">
            {unit}
          </span>
        )}
      </div>
    </div>
  );
}

function StatusPill({ kind }: { kind: "active" | "inactive" | "closed" | "warn" }) {
  const map = {
    active: { bg: "bg-[#dcfce7]", fg: "text-[#15803d]", label: "Active" },
    inactive: { bg: "bg-[#e8ebe8]", fg: "text-[#57694e]", label: "Inactive" },
    closed: { bg: "bg-[#e8ebe8]", fg: "text-[#57694e]", label: "Closed" },
    warn: { bg: "bg-[#fef9c3]", fg: "text-[#a16207]", label: "Maint." },
  } as const;
  const s = map[kind];
  return (
    <span
      className={`inline-flex shrink-0 items-center rounded-full px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wider ${s.bg} ${s.fg}`}
    >
      {s.label}
    </span>
  );
}

function PinBanner({
  title,
  pin,
  tone = "ok",
  onDismiss,
}: {
  title: string;
  pin: string;
  tone?: "ok" | "warn";
  onDismiss: () => void;
}) {
  return (
    <div
      className={`mb-4 flex items-center gap-4 rounded-xl border p-4 ${
        tone === "warn"
          ? "border-[#fde047] bg-[#fef9c3]"
          : "border-[#15803d]/40 bg-[#dcfce7]"
      }`}
    >
      <KeyIcon />
      <div className="flex-1">
        <p className="font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
          {title}
        </p>
        <p
          className="font-mono text-2xl font-bold tracking-[0.5em] text-[#1a4d2e]"
          aria-label={`PIN ${pin.split("").join(" ")}`}
        >
          {pin}
        </p>
      </div>
      <button type="button"
        onClick={onDismiss}
        className="rounded-lg border border-[#1a4d2e]/30 px-3 py-1.5 text-xs font-semibold text-[#1a4d2e] hover:bg-white"
      >
        Dismiss
      </button>
    </div>
  );
}

function RoleLegend() {
  return (
    <p className="mb-3 flex items-center gap-3 font-mono text-[11px] text-[#57694e]">
      <span>
        <span className="font-bold text-[#1e3a8a]">ADMIN</span>
        <span className="text-[#86868b]"> — manage headgates, users, entries</span>
      </span>
      <span className="text-[#d4d9d3]">·</span>
      <span>
        <span className="font-bold text-[#15803d]">IRRIGATOR</span>
        <span className="text-[#86868b]"> — submit entries only</span>
      </span>
    </p>
  );
}

function EmptyState({
  icon,
  title,
  body,
}: {
  icon: React.ReactNode;
  title: string;
  body: string;
}) {
  return (
    <div className="rounded-xl border border-dashed border-[#d4d9d3] bg-white px-6 py-10 text-center">
      <div className="mx-auto mb-3 flex w-12 items-center justify-center text-[#86868b]">
        {icon}
      </div>
      <p
        className="text-base font-semibold text-[#1d1d1f]"
        style={{ fontFamily: "var(--font-display, Georgia, serif)" }}
      >
        {title}
      </p>
      <p className="mx-auto mt-1 max-w-md text-sm text-[#57694e]">{body}</p>
    </div>
  );
}

function Input({
  label,
  value,
  onChange,
  placeholder,
  required,
  autoFocus,
  type = "text",
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
  required?: boolean;
  autoFocus?: boolean;
  type?: string;
}) {
  return (
    <label className="block">
      <span className="mb-1 block font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
        {label}
      </span>
      <input
        type={type}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        required={required}
        autoFocus={autoFocus}
        className="w-full rounded-lg border border-[#d4d9d3] bg-white px-3 py-2 text-sm text-[#1d1d1f] outline-none transition focus:border-[#1a4d2e] focus:ring-2 focus:ring-[#1a4d2e]/15"
      />
    </label>
  );
}

function Select({
  label,
  value,
  onChange,
  options,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  options: (string | { value: string; label: string })[];
}) {
  return (
    <label className="block">
      <span className="mb-1 block font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
        {label}
      </span>
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="w-full rounded-lg border border-[#d4d9d3] bg-white px-3 py-2 text-sm text-[#1d1d1f] outline-none transition focus:border-[#1a4d2e] focus:ring-2 focus:ring-[#1a4d2e]/15"
      >
        {options.map((o) => {
          if (typeof o === "string") {
            return (
              <option key={o} value={o}>
                {o}
              </option>
            );
          }
          return (
            <option key={o.value} value={o.value}>
              {o.label}
            </option>
          );
        })}
      </select>
    </label>
  );
}

function FilterChip({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="flex items-center gap-1.5 rounded-lg border border-[#d4d9d3] bg-[#fafaf7] px-2 py-1">
      <span className="font-mono text-[10px] uppercase tracking-wider text-[#86868b]">
        {label}
      </span>
      {children}
    </div>
  );
}

function Avatar({ name, role }: { name: string; role: string }) {
  const initials = name
    .split(/\s+/)
    .map((n) => n[0])
    .filter(Boolean)
    .slice(0, 2)
    .join("")
    .toUpperCase();
  const bg = role === "water_admin" ? "#1a4d2e" : "#57694e";
  return (
    <span
      className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full font-mono text-[11px] font-bold text-white"
      style={{ background: bg }}
      aria-hidden
    >
      {initials || "·"}
    </span>
  );
}

function ReportSettingsPanel({
  season,
  onSeasonChange,
  recipientName,
  onRecipientNameChange,
}: {
  season: IrrigationSeasonSettings;
  onSeasonChange: (s: IrrigationSeasonSettings) => void;
  recipientName: string;
  onRecipientNameChange: (v: string) => void;
}) {
  return (
    <div className="rounded-xl border border-[#d4d9d3] bg-white p-4">
      <div className="mb-3 flex items-center justify-between">
        <p className="font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
          Report / Messaging Settings
        </p>
      </div>
      <p className="mb-3 rounded-lg bg-[#fef9c3] px-3 py-2 text-xs text-[#a16207]">
        <strong>Preview only.</strong> Daily-report delivery is wired through
        the scheduled <code>api/cron/water-report</code> endpoint and respects
        these settings.
      </p>
      <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
        <div>
          <span className="mb-1 block font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
            Season start
          </span>
          <div className="flex gap-1">
            <MonthSelect
              value={season.seasonStartMonth}
              onChange={(m) => onSeasonChange({ ...season, seasonStartMonth: m })}
            />
            <DayInput
              value={season.seasonStartDay}
              onChange={(d) => onSeasonChange({ ...season, seasonStartDay: d })}
            />
          </div>
        </div>
        <div>
          <span className="mb-1 block font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
            Season end
          </span>
          <div className="flex gap-1">
            <MonthSelect
              value={season.seasonEndMonth}
              onChange={(m) => onSeasonChange({ ...season, seasonEndMonth: m })}
            />
            <DayInput
              value={season.seasonEndDay}
              onChange={(d) => onSeasonChange({ ...season, seasonEndDay: d })}
            />
          </div>
        </div>
        <div className="sm:col-span-2">
          <span className="mb-1 block font-mono text-[10px] uppercase tracking-wider text-[#57694e]">
            Recipient name (used in report salutation)
          </span>
          <input aria-label="David"
            type="text"
            value={recipientName}
            onChange={(e) => onRecipientNameChange(e.target.value)}
            placeholder="David"
            className="w-full rounded-lg border border-[#d4d9d3] px-3 py-2 text-sm outline-none focus:border-[#1a4d2e]"
          />
        </div>
      </div>
    </div>
  );
}

function MonthSelect({
  value,
  onChange,
}: {
  value: number;
  onChange: (m: number) => void;
}) {
  return (
    <select
      value={value}
      onChange={(e) => onChange(parseInt(e.target.value, 10))}
      className="flex-1 rounded-lg border border-[#d4d9d3] px-2 py-1.5 text-sm"
      aria-label="Month"
    >
      {Array.from({ length: 12 }, (_, i) => (
        <option key={i + 1} value={i + 1}>
          {new Date(0, i).toLocaleString("en", { month: "short" })}
        </option>
      ))}
    </select>
  );
}

function DayInput({
  value,
  onChange,
}: {
  value: number;
  onChange: (d: number) => void;
}) {
  return (
    <input
      type="number"
      min={1}
      max={31}
      value={value}
      onChange={(e) => onChange(parseInt(e.target.value, 10) || 1)}
      className="w-16 rounded-lg border border-[#d4d9d3] px-2 py-1.5 text-sm"
      aria-label="Day"
    />
  );
}

// ─── Icons (16–20px, currentColor) ──────────────────────────────────────

function QrIcon() {
  return (
    <svg width={14} height={14} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <rect x="2" y="2" width="5" height="5" />
      <rect x="9" y="2" width="5" height="5" />
      <rect x="2" y="9" width="5" height="5" />
      <path d="M9 9 H11 V11 H9 Z" />
      <path d="M12 9 H14 V12" />
      <path d="M9 12 V14 H14" />
    </svg>
  );
}

function GearIcon() {
  return (
    <svg width={14} height={14} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <circle cx="8" cy="8" r="2.2" />
      <path d="M8 1.5 V3.5 M8 12.5 V14.5 M1.5 8 H3.5 M12.5 8 H14.5 M3.3 3.3 L4.7 4.7 M11.3 11.3 L12.7 12.7 M3.3 12.7 L4.7 11.3 M11.3 4.7 L12.7 3.3" />
    </svg>
  );
}

function FieldIcon() {
  return (
    <svg width={14} height={14} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <path d="M2 11 L8 5 L11 8 L14 5" />
      <path d="M2 14 H14" />
    </svg>
  );
}

function ReportIcon() {
  return (
    <svg width={14} height={14} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <rect x="3" y="2" width="10" height="12" rx="1" />
      <path d="M5 5 H11 M5 8 H11 M5 11 H8" />
    </svg>
  );
}

function DownloadIcon() {
  return (
    <svg width={14} height={14} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <path d="M8 2 V10 M5 7 L8 10 L11 7" />
      <path d="M2 12 V14 H14 V12" />
    </svg>
  );
}

function KeyIcon() {
  return (
    <svg width={28} height={28} viewBox="0 0 24 24" fill="none" stroke="#1a4d2e" strokeWidth={1.6}>
      <circle cx="8" cy="12" r="4" />
      <path d="M12 12 H22 M18 12 V16 M22 12 V15" />
    </svg>
  );
}

function UserIcon() {
  return (
    <svg width={36} height={36} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <circle cx="12" cy="8" r="4" />
      <path d="M4 21 C4 16 8 14 12 14 C16 14 20 16 20 21" />
    </svg>
  );
}

function TableIcon() {
  return (
    <svg width={36} height={36} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.4}>
      <rect x="3" y="4" width="18" height="16" rx="1" />
      <path d="M3 10 H21 M9 4 V20" />
    </svg>
  );
}
