"use client";

import { useEffect, useRef, useReducer, useCallback } from "react";
import Image from "next/image";
import { useRouter } from "next/navigation";
import {
  getWaterHeadgatesAdmin,
  createWaterHeadgate,
  regenerateHeadgateToken,
  updateWaterHeadgate,
  deleteWaterHeadgate,
} from "@/actions/water-log/admin";
import { AdminButton } from "@/components/admin/design-system";

async function openPrintWindow(html: string) {
  const blob = new Blob([html], { type: "text/html;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const w = window.open(url, "_blank", "width=700,height=700");
  if (w) {
    // Revoke the blob URL once the new window has had time to load the document.
    w.addEventListener("load", () => URL.revokeObjectURL(url), { once: true });
    // Safety net: revoke after 60s even if the load event never fires.
    setTimeout(() => URL.revokeObjectURL(url), 60_000);
  } else {
    URL.revokeObjectURL(url);
  }
}

type Headgate = {
  id: string;
  name: string;
  active: boolean;
  unit: string;
  created_at: string;
  deleted_at?: string | null;
  headgate_token?: string | null;
  last_used_at?: string | null;
  high_threshold?: number | null;
  low_threshold?: number | null;
};

type Props = {
  initialHeadgates: Headgate[];
  brandId: string;
};

type Toast = { msg: string; ok: boolean };

type State = {
  headgates: Headgate[];
  showAdd: boolean;
  newName: string;
  newUnit: string;
  saving: boolean;
  qrModal: Headgate | null;
  selected: Set<string>;
  printLoading: boolean;
  toast: Toast | null;
  editHg: Headgate | null;
  editName: string;
  editUnit: string;
  editActive: boolean;
  editHigh: string;
  editLow: string;
  editSaving: boolean;
  deletingId: string | null;
};

type Action =
  | { type: "SET_HEADGATES"; value: Headgate[] }
  | { type: "SHOW_ADD" }
  | { type: "HIDE_ADD" }
  | { type: "SET_NEW_NAME"; value: string }
  | { type: "SET_NEW_UNIT"; value: string }
  | { type: "SET_SAVING"; value: boolean }
  | { type: "SET_QR_MODAL"; value: Headgate | null }
  | { type: "TOGGLE_SELECT"; id: string }
  | { type: "TOGGLE_ALL" }
  | { type: "CLEAR_SELECTED" }
  | { type: "SET_SELECTED"; value: Set<string> }
  | { type: "SET_PRINT_LOADING"; value: boolean }
  | { type: "SET_TOAST"; value: Toast | null }
  | { type: "OPEN_EDIT"; hg: Headgate }
  | { type: "CLOSE_EDIT" }
  | { type: "SET_EDIT_NAME"; value: string }
  | { type: "SET_EDIT_UNIT"; value: string }
  | { type: "SET_EDIT_ACTIVE"; value: boolean }
  | { type: "SET_EDIT_HIGH"; value: string }
  | { type: "SET_EDIT_LOW"; value: string }
  | { type: "SET_EDIT_SAVING"; value: boolean }
  | { type: "SET_DELETING_ID"; value: string | null };

const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";

function editStateFromHeadgate(hg: Headgate) {
  return {
    editHg: hg,
    editName: hg.name,
    editUnit: hg.unit,
    editActive: hg.active,
    editHigh: hg.high_threshold != null ? String(hg.high_threshold) : "",
    editLow: hg.low_threshold != null ? String(hg.low_threshold) : "",
  };
}

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "SET_HEADGATES":
      return { ...state, headgates: action.value };
    case "SHOW_ADD":
      return { ...state, showAdd: true };
    case "HIDE_ADD":
      return { ...state, showAdd: false, newName: "" };
    case "SET_NEW_NAME":
      return { ...state, newName: action.value };
    case "SET_NEW_UNIT":
      return { ...state, newUnit: action.value };
    case "SET_SAVING":
      return { ...state, saving: action.value };
    case "SET_QR_MODAL":
      return { ...state, qrModal: action.value };
    case "TOGGLE_SELECT": {
      const next = new Set(state.selected);
      if (next.has(action.id)) {
        next.delete(action.id);
      } else {
        next.add(action.id);
      }
      return { ...state, selected: next };
    }
    case "TOGGLE_ALL":
      return {
        ...state,
        selected:
          state.selected.size === state.headgates.length
            ? new Set()
            : new Set(state.headgates.map((h) => h.id)),
      };
    case "CLEAR_SELECTED":
      return { ...state, selected: new Set() };
    case "SET_SELECTED":
      return { ...state, selected: action.value };
    case "SET_PRINT_LOADING":
      return { ...state, printLoading: action.value };
    case "SET_TOAST":
      return { ...state, toast: action.value };
    case "OPEN_EDIT":
      return { ...state, ...editStateFromHeadgate(action.hg) };
    case "CLOSE_EDIT":
      return { ...state, editHg: null };
    case "SET_EDIT_NAME":
      return { ...state, editName: action.value };
    case "SET_EDIT_UNIT":
      return { ...state, editUnit: action.value };
    case "SET_EDIT_ACTIVE":
      return { ...state, editActive: action.value };
    case "SET_EDIT_HIGH":
      return { ...state, editHigh: action.value };
    case "SET_EDIT_LOW":
      return { ...state, editLow: action.value };
    case "SET_EDIT_SAVING":
      return { ...state, editSaving: action.value };
    case "SET_DELETING_ID":
      return { ...state, deletingId: action.value };
  }
}

function makeInitialState(initialHeadgates: Headgate[]): State {
  return {
    headgates: initialHeadgates,
    showAdd: false,
    newName: "",
    newUnit: "CFS",
    saving: false,
    qrModal: null,
    selected: new Set(),
    printLoading: false,
    toast: null,
    editHg: null,
    editName: "",
    editUnit: "CFS",
    editActive: true,
    editHigh: "",
    editLow: "",
    editSaving: false,
    deletingId: null,
  };
}

export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
  const router = useRouter();
  const [state, dispatch] = useReducer(reducer, initialHeadgates, makeInitialState);

  const showToast = useCallback((msg: string, ok = true) => {
    dispatch({ type: "SET_TOAST", value: { msg, ok } });
    setTimeout(() => dispatch({ type: "SET_TOAST", value: null }), 2500);
  }, []);

  const handleEditSave = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault();
      if (!state.editHg) return;
      dispatch({ type: "SET_EDIT_SAVING", value: true });
      const res = await updateWaterHeadgate(
        state.editHg.id,
        state.editName,
        state.editActive,
        state.editUnit,
        state.editHigh ? parseFloat(state.editHigh) : null,
        state.editLow ? parseFloat(state.editLow) : null
      );
      if (res.success) {
        const refreshed = await getWaterHeadgatesAdmin(brandId);
        dispatch({ type: "SET_HEADGATES", value: refreshed });
        dispatch({ type: "CLOSE_EDIT" });
        showToast("Headgate updated");
      } else {
        showToast(res.error ?? "Failed", false);
      }
      dispatch({ type: "SET_EDIT_SAVING", value: false });
    },
    [state.editHg, state.editName, state.editActive, state.editUnit, state.editHigh, state.editLow, brandId, showToast]
  );

  const handleAdd = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault();
      if (!state.newName.trim()) return;
      dispatch({ type: "SET_SAVING", value: true });
      const res = await createWaterHeadgate(brandId, state.newName.trim(), state.newUnit);
      if (res.success) {
        const refreshed = await getWaterHeadgatesAdmin(brandId);
        dispatch({ type: "SET_HEADGATES", value: refreshed });
        dispatch({ type: "SET_NEW_NAME", value: "" });
        dispatch({ type: "HIDE_ADD" });
        showToast("Headgate added");
      } else {
        showToast(res.error ?? "Failed", false);
      }
      dispatch({ type: "SET_SAVING", value: false });
    },
    [state.newName, state.newUnit, brandId, showToast]
  );

  const handleRegenerate = useCallback(
    async (hg: Headgate) => {
      if (!confirm(`Regenerate token for "${hg.name}"? Existing QR codes will stop working.`)) return;
      const res = await regenerateHeadgateToken(hg.id);
      if (res.success) {
        dispatch({
          type: "SET_HEADGATES",
          value: state.headgates.map((h) =>
            h.id === hg.id ? { ...h, headgate_token: res.token! } : h
          ),
        });
        showToast("Token regenerated");
      } else {
        showToast(res.error ?? "Failed", false);
      }
    },
    [state.headgates, showToast]
  );

  const handleDelete = useCallback(
    async (hg: Headgate) => {
      if (!window.confirm(`Delete headgate "${hg.name}"? Existing log entries will be preserved.`)) return;
      dispatch({ type: "SET_DELETING_ID", value: hg.id });
      const res = await deleteWaterHeadgate(hg.id);
      if (res.success) {
        // Optimistic update + refresh
        dispatch({
          type: "SET_HEADGATES",
          value: state.headgates.filter((h) => h.id !== hg.id),
        });
        const refreshed = await getWaterHeadgatesAdmin(brandId);
        dispatch({ type: "SET_HEADGATES", value: refreshed });
        showToast("Headgate deleted");
      } else {
        showToast(res.error ?? "Failed to delete headgate", false);
      }
      dispatch({ type: "SET_DELETING_ID", value: null });
    },
    [state.headgates, brandId, showToast]
  );

  const printSelected = useCallback(async () => {
    if (state.selected.size === 0) return;
    dispatch({ type: "SET_PRINT_LOADING", value: true });
    const hgs = state.headgates.filter((h) => state.selected.has(h.id));
    try {
      const res = await fetch("/api/water-qr-sheet", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ headgates: hgs, baseUrl: BASE_URL }),
      });
      const html = await res.text();
      openPrintWindow(html);
    } finally {
      dispatch({ type: "SET_PRINT_LOADING", value: false });
    }
  }, [state.selected, state.headgates]);

  return (
    <div className="min-h-screen bg-[var(--admin-bg)]">
      {/* Header */}
      <HeaderSection onBack={() => router.back()} onAdd={() => dispatch({ type: "SHOW_ADD" })} />

      <div className="mx-auto max-w-4xl px-6 py-6 space-y-6">
        {/* Bulk actions bar */}
        {state.headgates.length > 0 && (
          <BulkActionsBar
            allSelected={state.selected.size === state.headgates.length}
            selectedCount={state.selected.size}
            printLoading={state.printLoading}
            onToggleAll={() => dispatch({ type: "TOGGLE_ALL" })}
            onPrint={printSelected}
          />
        )}

        {/* Add form */}
        {state.showAdd && (
          <AddHeadgateForm
            name={state.newName}
            unit={state.newUnit}
            saving={state.saving}
            onNameChange={(v) => dispatch({ type: "SET_NEW_NAME", value: v })}
            onUnitChange={(v) => dispatch({ type: "SET_NEW_UNIT", value: v })}
            onSubmit={handleAdd}
            onCancel={() => dispatch({ type: "HIDE_ADD" })}
          />
        )}

        {/* Table */}
        {state.headgates.length === 0 ? (
          <EmptyState />
        ) : (
          <HeadgatesTable
            headgates={state.headgates}
            selected={state.selected}
            deletingId={state.deletingId}
            onToggleSelect={(id) => dispatch({ type: "TOGGLE_SELECT", id })}
            onToggleAll={() => dispatch({ type: "TOGGLE_ALL" })}
            onEdit={(hg) => dispatch({ type: "OPEN_EDIT", hg })}
            onShowQr={(hg) => dispatch({ type: "SET_QR_MODAL", value: hg })}
            onDelete={handleDelete}
          />
        )}
      </div>

      {/* Toast */}
      {state.toast && <ToastView toast={state.toast} />}

      {/* Edit Modal */}
      {state.editHg && (
        <EditHeadgateModal
          state={state}
          onClose={() => dispatch({ type: "CLOSE_EDIT" })}
          onNameChange={(v) => dispatch({ type: "SET_EDIT_NAME", value: v })}
          onUnitChange={(v) => dispatch({ type: "SET_EDIT_UNIT", value: v })}
          onActiveChange={(v) => dispatch({ type: "SET_EDIT_ACTIVE", value: v })}
          onHighChange={(v) => dispatch({ type: "SET_EDIT_HIGH", value: v })}
          onLowChange={(v) => dispatch({ type: "SET_EDIT_LOW", value: v })}
          onSubmit={handleEditSave}
        />
      )}

      {/* QR Modal */}
      {state.qrModal && (
        <QRModal
          hg={state.qrModal}
          onClose={() => dispatch({ type: "SET_QR_MODAL", value: null })}
          onRegenerate={async (hg) => {
            await handleRegenerate(hg);
            dispatch({ type: "SET_QR_MODAL", value: null });
          }}
        />
      )}
    </div>
  );
}

function HeaderSection({ onBack, onAdd }: { onBack: () => void; onAdd: () => void }) {
  return (
    <div className="bg-white border-b border-[var(--admin-border)] px-6 py-4">
      <div className="mx-auto max-w-4xl flex items-center justify-between">
        <div>
          <div className="flex items-center gap-2">
            <button type="button" onClick={onBack} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)] text-sm" aria-label="← Back">← Back</button>
            <h1 className="text-2xl font-bold text-[var(--admin-text-primary)]">Headgates & QR Codes</h1>
          </div>
          <p className="text-xs text-[var(--admin-text-muted)] mt-0.5">Manage headgates and generate QR codes for field access</p>
        </div>
        <AdminButton onClick={onAdd}>
          + Add Headgate
        </AdminButton>
      </div>
    </div>
  );
}

function BulkActionsBar({
  allSelected,
  selectedCount,
  printLoading,
  onToggleAll,
  onPrint,
}: {
  allSelected: boolean;
  selectedCount: number;
  printLoading: boolean;
  onToggleAll: () => void;
  onPrint: () => void;
}) {
  return (
    <div className="flex items-center gap-3 rounded-xl border border-[var(--admin-border)] bg-white px-4 py-3">
      <button type="button" onClick={onToggleAll} className="text-sm text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)]">
        {allSelected ? "Deselect all" : "Select all"}
      </button>
      <span className="text-xs text-[var(--admin-text-muted)]">|</span>
      <span className="text-xs text-[var(--admin-text-muted)]">{selectedCount} selected</span>
      <div className="flex-1" />
      <AdminButton
        onClick={onPrint}
        disabled={selectedCount === 0}
        isLoading={printLoading}
      >
        Print {selectedCount > 0 ? `(${selectedCount})` : ""} QR Codes
      </AdminButton>
    </div>
  );
}

function AddHeadgateForm({
  name,
  unit,
  saving,
  onNameChange,
  onUnitChange,
  onSubmit,
  onCancel,
}: {
  name: string;
  unit: string;
  saving: boolean;
  onNameChange: (v: string) => void;
  onUnitChange: (v: string) => void;
  onSubmit: (e: React.FormEvent) => void;
  onCancel: () => void;
}) {
  return (
    <div className="rounded-xl border border-[var(--admin-border)] bg-white p-5">
      <form onSubmit={onSubmit} className="flex gap-3 items-end">
        <div className="flex-1">
          <label htmlFor="headgate-add-name" className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Headgate Name</label>
          <input aria-label=". North Field Gate 1"
            id="headgate-add-name"
            type="text"
            value={name}
            onChange={(e) => onNameChange(e.target.value)}
            placeholder="e.g. North Field Gate 1"
            className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
            required
            aria-required="true"
          />
        </div>
        <div>
          <label htmlFor="headgate-add-unit" className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Unit</label>
          <select aria-label="Headgate Add Unit"
            id="headgate-add-unit"
            value={unit}
            onChange={(e) => onUnitChange(e.target.value)}
            className="rounded-xl border border-[var(--admin-border)] px-3 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
          >
            {["CFS", "GPM", "Inches", "AF/Day"].map((u) => (
              <option key={u} value={u}>{u}</option>
            ))}
          </select>
        </div>
        <AdminButton type="submit" disabled={saving} isLoading={saving}>
          Create
        </AdminButton>
        <AdminButton type="button" variant="secondary" onClick={onCancel}>
          Cancel
        </AdminButton>
      </form>
    </div>
  );
}

function EmptyState() {
  return (
    <div className="rounded-xl bg-white py-16 text-center text-[var(--admin-text-muted)] border border-[var(--admin-border)]">
      No headgates yet. Create one to get started.
    </div>
  );
}

function HeadgatesTable({
  headgates,
  selected,
  deletingId,
  onToggleSelect,
  onToggleAll,
  onEdit,
  onShowQr,
  onDelete,
}: {
  headgates: Headgate[];
  selected: Set<string>;
  deletingId: string | null;
  onToggleSelect: (id: string) => void;
  onToggleAll: () => void;
  onEdit: (hg: Headgate) => void;
  onShowQr: (hg: Headgate) => void;
  onDelete: (hg: Headgate) => void;
}) {
  const allSelected = selected.size === headgates.length;
  return (
    <div className="rounded-xl border border-[var(--admin-border)] bg-white overflow-hidden">
      <table className="w-full text-sm">
        <thead>
          <tr className="border-b border-[var(--admin-border)] bg-[var(--admin-bg-subtle)] text-left">
            <th className="px-4 py-3 w-8">
              <input aria-label="Checkbox" type="checkbox" className="rounded" onChange={onToggleAll} checked={allSelected} />
            </th>
            <th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Name</th>
            <th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Token</th>
            <th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Unit</th>
            <th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Last Used</th>
            <th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Status</th>
            <th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)] text-right">QR Code</th>
          </tr>
        </thead>
        <tbody>
          {headgates.map((hg) => (
            <tr key={hg.id} className={`border-b border-[var(--admin-border)] last:border-0 hover:bg-[var(--admin-bg-subtle)] ${selected.has(hg.id) ? "bg-blue-50" : ""}`}>
              <td className="px-4 py-3">
                <input aria-label="Checkbox" type="checkbox" className="rounded" checked={selected.has(hg.id)} onChange={() => onToggleSelect(hg.id)} />
              </td>
              <td className="px-4 py-3">
                <div className="flex items-center gap-2 flex-wrap">
                  <span className="font-semibold text-[var(--admin-text-primary)]">{hg.name}</span>
                  {hg.high_threshold != null && (
                    <span className="inline-flex items-center rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-xs font-semibold text-red-700">
                      High: {hg.high_threshold}
                    </span>
                  )}
                  {hg.low_threshold != null && (
                    <span className="inline-flex items-center rounded-full bg-blue-100 border border-blue-200 px-1.5 py-0.5 text-xs font-semibold text-blue-700">
                      Low: {hg.low_threshold}
                    </span>
                  )}
                </div>
              </td>
              <td className="px-4 py-3">
                <code className="text-xs text-[var(--admin-text-muted)]">{hg.headgate_token?.slice(0, 8)}…</code>
              </td>
              <td className="px-4 py-3">
                <span className="text-xs text-[var(--admin-text-muted)]">{hg.unit}</span>
              </td>
              <td className="px-4 py-3">
                <span className="text-xs text-[var(--admin-text-muted)]">
                  {hg.last_used_at
                    ? new Date(hg.last_used_at).toLocaleDateString("en-US", { month: "short", day: "numeric" })
                    : "Never"}
                </span>
              </td>
              <td className="px-4 py-3">
                <span className={`inline-flex rounded-full px-2 py-0.5 text-xs font-semibold ${hg.active ? "bg-green-100 text-green-700" : "bg-stone-100 text-stone-500"}`}>
                  {hg.active ? "Active" : "Inactive"}
                </span>
              </td>
              <td className="px-4 py-3 text-right">
                <div className="flex items-center justify-end gap-2">
                  <AdminButton variant="secondary" size="sm" onClick={() => onEdit(hg)}>
                    Edit
                  </AdminButton>
                  {/* QR preview thumbnail */}
                  <button type="button" onClick={() => onShowQr(hg)} className="hover:opacity-80" title="View / Print QR" aria-label="View / Print QR">
                    <Image
                      src={`/api/water-qr?token=${hg.headgate_token}&size=80`}
                      alt={`QR for ${hg.name}`}
                      width={40}
                      height={40}
                      unoptimized
                      className="w-10 h-10 rounded border border-[var(--admin-border)]"
                    />
                  </button>
                  <AdminButton variant="secondary" size="sm" onClick={() => onShowQr(hg)}>
                    Print
                  </AdminButton>
                  <AdminButton
                    variant="danger"
                    size="sm"
                    onClick={() => onDelete(hg)}
                    disabled={deletingId === hg.id}
                    isLoading={deletingId === hg.id}
                  >
                    Delete
                  </AdminButton>
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function ToastView({ toast }: { toast: Toast }) {
  return (
    <div className={`fixed bottom-6 right-6 rounded-xl px-4 py-3 text-sm font-semibold shadow-lg ${toast.ok ? "bg-green-100 text-green-800 border border-green-200" : "bg-red-100 text-red-800 border border-red-200"}`}>
      {toast.msg}
    </div>
  );
}

function EditHeadgateModal({
  state,
  onClose,
  onNameChange,
  onUnitChange,
  onActiveChange,
  onHighChange,
  onLowChange,
  onSubmit,
}: {
  state: State;
  onClose: () => void;
  onNameChange: (v: string) => void;
  onUnitChange: (v: string) => void;
  onActiveChange: (v: boolean) => void;
  onHighChange: (v: string) => void;
  onLowChange: (v: string) => void;
  onSubmit: (e: React.FormEvent) => void;
}) {
  const dialogRef = useRef<HTMLDialogElement>(null);

  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return;
    if (!dialog.open) dialog.showModal();
    const onCancel = (e: Event) => {
      e.preventDefault();
      onClose();
    };
    dialog.addEventListener("cancel", onCancel);
    return () => {
      dialog.removeEventListener("cancel", onCancel);
    };
  }, [onClose]);

  return (
    <dialog
      ref={dialogRef}
      aria-label="Edit Headgate"
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 m-0 p-0 max-w-none max-h-none w-full h-full backdrop:bg-black/50"
    >
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden border border-[var(--admin-border)]">
        <div className="flex items-center justify-between px-5 py-4 border-b border-[var(--admin-border)]">
          <p className="font-bold text-[var(--admin-text-primary)]">Edit Headgate</p>
          <button type="button" onClick={onClose} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)]" aria-label="Close">
            <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>
        <form onSubmit={onSubmit} className="p-5 space-y-4">
          <div>
            <label htmlFor="headgate-edit-name" className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Name</label>
            <input aria-label="Headgate Edit Name"
              id="headgate-edit-name"
              type="text"
              value={state.editName}
              onChange={(e) => onNameChange(e.target.value)}
              className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
              required
              aria-required="true"
            />
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <label htmlFor="headgate-edit-unit" className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Unit</label>
              <select aria-label="Headgate Edit Unit"
                id="headgate-edit-unit"
                value={state.editUnit}
                onChange={(e) => onUnitChange(e.target.value)}
                className="w-full rounded-xl border border-[var(--admin-border)] px-3 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
              >
                {["CFS", "GPM", "Inches", "AF/Day"].map((u) => (
                  <option key={u} value={u}>{u}</option>
                ))}
              </select>
            </div>
            <div className="flex items-center">
              <label className="flex items-center gap-2 text-sm text-[var(--admin-text-secondary)] cursor-pointer">
                <input id="headgate-edit-active" type="checkbox" checked={state.editActive} onChange={(e) => onActiveChange(e.target.checked)} className="rounded" />
                Active
              </label>
            </div>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <label htmlFor="headgate-edit-high" className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">High Alert Threshold</label>
              <input aria-label=". 15.0"
                id="headgate-edit-high"
                type="number"
                step="any"
                value={state.editHigh}
                onChange={(e) => onHighChange(e.target.value)}
                placeholder="e.g. 15.0"
                className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
              />
            </div>
            <div>
              <label htmlFor="headgate-edit-low" className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Low Alert Threshold</label>
              <input aria-label=". 5.0"
                id="headgate-edit-low"
                type="number"
                step="any"
                value={state.editLow}
                onChange={(e) => onLowChange(e.target.value)}
                placeholder="e.g. 5.0"
                className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
              />
            </div>
          </div>
          <p className="text-xs text-[var(--admin-text-muted)]">Leave thresholds blank to disable alerts for this headgate.</p>
          <div className="flex gap-2">
            <AdminButton type="submit" disabled={state.editSaving} isLoading={state.editSaving} fullWidth>
              Save Changes
            </AdminButton>
            <AdminButton type="button" variant="secondary" onClick={onClose}>
              Cancel
            </AdminButton>
          </div>
        </form>
      </div>
    </dialog>
  );
}

function QRModal({ hg, onClose, onRegenerate }: { hg: Headgate; onClose: () => void; onRegenerate: (hg: Headgate) => void }) {
  const [tab, setTab] = useReducer(
    (state: "preview" | "print" | "download", action: "preview" | "print" | "download") => action,
    "preview"
  );
  const [loading, setLoading] = useReducer((s: boolean, a: boolean) => a, false);
  const dialogRef = useRef<HTMLDialogElement>(null);

  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return;
    if (!dialog.open) dialog.showModal();
    const onCancel = (e: Event) => {
      e.preventDefault();
      onClose();
    };
    dialog.addEventListener("cancel", onCancel);
    return () => {
      dialog.removeEventListener("cancel", onCancel);
    };
  }, [onClose]);

  const code = hg.name.replace(/\s+/g, "-").toUpperCase().slice(0, 6) + "-1";
  const waterUrl = `${process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000"}/water?h=${hg.headgate_token}`;

  async function handlePrintLabel() {
    setLoading(true);
    try {
      const res = await fetch("/api/water-qr-label", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ token: hg.headgate_token, name: hg.name }),
      });
      const html = await res.text();
      const blob = new Blob([html], { type: "text/html;charset=utf-8" });
      const url = URL.createObjectURL(blob);
      const w = window.open(url, "_blank", "width=500,height=600");
      if (w) {
        w.addEventListener("load", () => URL.revokeObjectURL(url), { once: true });
        setTimeout(() => URL.revokeObjectURL(url), 60_000);
      } else {
        URL.revokeObjectURL(url);
      }
    } finally {
      setLoading(false);
    }
  }

  async function handleDownload() {
    setLoading(true);
    try {
      const res = await fetch(`/api/water-qr?token=${hg.headgate_token}&size=400`);
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `${hg.name.replace(/\s+/g, "-").toLowerCase()}-qr.png`;
      a.click();
      URL.revokeObjectURL(url);
    } finally {
      setLoading(false);
    }
  }

  return (
    <dialog
      ref={dialogRef}
      aria-label="Headgate details"
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 m-0 p-0 max-w-none max-h-none w-full h-full backdrop:bg-black/50"
    >
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden border border-[var(--admin-border)]">
        {/* Header */}
        <div className="flex items-center justify-between px-5 py-4 border-b border-[var(--admin-border)]">
          <div>
            <p className="font-bold text-[var(--admin-text-primary)]">{hg.name}</p>
            <p className="text-xs text-[var(--admin-text-muted)] mt-0.5">QR Label Preview</p>
          </div>
          <button type="button" onClick={onClose} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)]" aria-label="Close">
            <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* ── Simplified label preview ── */}
        <div className="flex justify-center bg-[var(--admin-bg-subtle)] py-6 px-4">
          <div className="w-40 border-2 border-black rounded-lg p-3 text-center bg-white shadow-sm">
            <div className="text-xl font-black text-black leading-tight tracking-tight">{hg.name}</div>
            <div className="text-[9px] font-bold text-gray-500 uppercase tracking-widest mt-0.5 mb-3">{code}</div>
            <div className="flex justify-center mb-2">
              <Image
                src={`/api/water-qr?token=${hg.headgate_token}&size=160`}
                alt="QR"
                width={112}
                height={112}
                unoptimized
                className="w-28 h-28 rounded"
              />
            </div>
            <div className="text-[5.5px] text-gray-500 leading-tight break-all">{waterUrl}</div>
          </div>
        </div>

        {/* Tab toggle */}
        <div className="flex border-b border-[var(--admin-border)]">
          {(["preview", "print", "download"] as const).map((t) => (
            <button type="button"
              key={t}
              onClick={() => setTab(t)}
              className={`flex-1 py-3 text-sm font-semibold transition-colors ${tab === t ? "text-[var(--admin-text-primary)] border-b-2 border-[var(--admin-accent)]" : "text-[var(--admin-text-muted)]"}`}
            >
              {t === "preview" ? "Preview" : t === "print" ? "🖨️ Print" : "💾 Download"}
            </button>
          ))}
        </div>

        <div className="p-5 space-y-3">
          {tab === "preview" ? (
            <div className="space-y-2 text-sm text-[var(--admin-text-secondary)]">
              <p>This label is optimized for physical signs and thermal printing:</p>
              <ul className="list-disc list-inside space-y-1 text-xs text-[var(--admin-text-muted)]">
                <li><strong>Large name</strong> (24pt bold) — scannable from distance</li>
                <li><strong>Short code</strong> (e.g. <code className="font-mono bg-[var(--admin-bg-subtle)] px-1 rounded">{code}</code>) — field reference</li>
                <li><strong>High-contrast QR</strong> — error correction H for outdoor use</li>
                <li><strong>Tiny URL</strong> at bottom — reference only</li>
              </ul>
              <AdminButton onClick={() => setTab("print")} fullWidth>
                🖨️ Print This Label
              </AdminButton>
            </div>
          ) : tab === "print" ? (
            <AdminButton onClick={handlePrintLabel} disabled={loading} isLoading={loading} fullWidth>
              🖨️ Print Label
            </AdminButton>
          ) : (
            <AdminButton onClick={handleDownload} disabled={loading} isLoading={loading} fullWidth>
              💾 Download PNG
            </AdminButton>
          )}

          <AdminButton
            onClick={() => onRegenerate(hg)}
            variant="secondary"
            fullWidth
          >
            🔄 Regenerate Token
          </AdminButton>

          <div className="rounded-lg border border-[var(--admin-border)] p-3">
            <p className="text-xs text-[var(--admin-text-muted)] mb-1">Token</p>
            <code className="text-xs text-[var(--admin-text-secondary)] font-mono break-all">{hg.headgate_token}</code>
          </div>
        </div>
      </div>
    </dialog>
  );
}
