"use client";

import { useEffect, useRef, useState, type FormEvent } from "react";
import { useSearchParams } from "next/navigation";
import { ChevronLeft, ChevronRight, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";
import { toast } from "react-hot-toast";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { FormField, SelectField } from "@/components/shared/form-field";
import { Panel } from "@/components/shared/panel";
import { useQueryUpdate } from "@/components/shared/query-controls";
import { readOperatorListQuery } from "./query";
import {
  fetchOperator,
  fetchOperators,
  removeOperator,
  saveOperator,
} from "./client-api";
import type { OperatorRecord, OperatorWriteValues } from "./types";
import type { Pagination } from "@/lib/list-query";

const emptyPagination: Pagination = {
  page: 1,
  pages: 1,
  limit: 10,
  total: 0,
  start: 0,
  end: 0,
};

const emptyDraft: OperatorWriteValues = {
  firstName: "",
  lastName: "",
  email: "",
  phone: "",
  active: true,
};

function fullName(operator: OperatorRecord) {
  return `${operator.firstName} ${operator.lastName}`.trim();
}

function messageFrom(error: unknown, fallback: string) {
  return error instanceof Error && error.message.trim() ? error.message : fallback;
}

export function OperatorsView() {
  const searchParams = useSearchParams();
  const queryString = searchParams.toString();
  const listQuery = readOperatorListQuery(new URLSearchParams(queryString));
  const page = listQuery.page;
  const pageSize = listQuery.limit;
  const updateQuery = useQueryUpdate();
  const [operators, setOperators] = useState<OperatorRecord[]>([]);
  const [pagination, setPagination] = useState<Pagination>(emptyPagination);
  const [organizationCode, setOrganizationCode] = useState("");
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState("");
  const [refreshVersion, setRefreshVersion] = useState(0);
  const [editorOpen, setEditorOpen] = useState(false);
  const [editingOperator, setEditingOperator] = useState<OperatorRecord | null>(null);
  const [draft, setDraft] = useState<OperatorWriteValues>(emptyDraft);
  const [detailLoading, setDetailLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [operatorToDelete, setOperatorToDelete] = useState<OperatorRecord | null>(null);
  const [deleting, setDeleting] = useState(false);
  const detailRequest = useRef(0);

  const firstPageNumber = Math.max(1, Math.min(pagination.page - 2, pagination.pages - 4));
  const pageNumbers = Array.from(
    { length: Math.min(pagination.pages, 5) },
    (_, index) => firstPageNumber + index,
  );

  useEffect(() => {
    let cancelled = false;
    async function load() {
      setLoading(true);
      setLoadError("");
      try {
        const result = await fetchOperators({ page, limit: pageSize });
        if (cancelled) return;
        setOperators(result.records);
        setPagination(result.pagination);
        setOrganizationCode(result.organizationCode);
      } catch (error) {
        if (cancelled) return;
        setOperators([]);
        setPagination(emptyPagination);
        setLoadError(messageFrom(error, "Unable to load operators. Please try again."));
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    void load();
    return () => {
      cancelled = true;
    };
  }, [page, pageSize, refreshVersion]);

  function notify(kind: "success" | "error", message: string) {
    if (kind === "success") {
      toast.success(message);
    } else {
      toast.error(message);
    }
  }

  function refreshList() {
    setRefreshVersion((version) => version + 1);
  }

  function closeEditor(open: boolean) {
    setEditorOpen(open);
    if (!open) {
      detailRequest.current += 1;
      setEditingOperator(null);
      setDetailLoading(false);
    }
  }

  function openCreateDialog() {
    detailRequest.current += 1;
    setEditingOperator(null);
    setDraft(emptyDraft);
    setEditorOpen(true);
  }

  async function openEditDialog(operator: OperatorRecord) {
    const requestId = ++detailRequest.current;
    setEditingOperator(operator);
    setDraft({
      firstName: operator.firstName,
      lastName: operator.lastName,
      email: operator.email,
      phone: operator.phone,
      active: operator.active,
      ...(operator.address ? { address: operator.address } : {}),
      ...(operator.profile ? { profile: operator.profile } : {}),
    });
    setEditorOpen(true);
    setDetailLoading(true);
    try {
      const result = await fetchOperator(operator.id);
      if (detailRequest.current !== requestId) return;
      const detail = result.operator;
      setEditingOperator(detail);
      setDraft({
        firstName: detail.firstName,
        lastName: detail.lastName,
        email: detail.email,
        phone: detail.phone,
        active: detail.active,
        ...(detail.address ? { address: detail.address } : {}),
        ...(detail.profile ? { profile: detail.profile } : {}),
      });
    } catch (error) {
      if (detailRequest.current !== requestId) return;
      setEditorOpen(false);
      setEditingOperator(null);
      notify("error", messageFrom(error, "Unable to load operator details."));
    } finally {
      if (detailRequest.current === requestId) setDetailLoading(false);
    }
  }

  async function handleSave(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (detailLoading) return;
    setSaving(true);
    try {
      const values: OperatorWriteValues = {
        ...draft,
        firstName: draft.firstName.trim(),
        lastName: draft.lastName.trim(),
        email: draft.email.trim(),
        phone: draft.phone.trim(),
      };
      const result = await saveOperator(editingOperator?.id, values);
      notify("success", result.message || (editingOperator ? "Operator updated successfully." : "Operator created successfully."));
      closeEditor(false);
      if (!editingOperator && page !== 1) {
        updateQuery({ paginate_page: "1" });
      } else {
        refreshList();
      }
    } catch (error) {
      notify("error", messageFrom(error, "Unable to save the operator."));
    } finally {
      setSaving(false);
    }
  }

  async function handleDelete() {
    if (!operatorToDelete) return;
    setDeleting(true);
    try {
      const message = await removeOperator(operatorToDelete.id);
      notify("success", message || "Operator deleted successfully.");
      setOperatorToDelete(null);
      if (operators.length === 1 && pagination.page > 1) {
        updateQuery({ paginate_page: String(pagination.page - 1) });
      } else {
        refreshList();
      }
    } catch (error) {
      notify("error", messageFrom(error, "Unable to delete the operator."));
    } finally {
      setDeleting(false);
    }
  }

  return (
    <>
      <Panel className="overflow-hidden p-0">
        <div className="border-b border-border px-5 py-4 md:px-6">
          <h2 className="text-lg font-semibold">Operators ({pagination.total})</h2>
          <p className="mt-1 text-sm text-muted-foreground">
            Manage field operators for this organization.
          </p>
        </div>
        <div className="mb-4 flex flex-col gap-3 px-5 pt-4 lg:flex-row lg:items-center lg:justify-between">
          <label className="flex items-center gap-3 text-sm text-muted-foreground">
            <span>Show</span>
            <select
              aria-label="Operators per page"
              className="h-11 rounded-lg border border-input bg-card px-3 text-foreground focus-visible:outline-2 focus-visible:outline-ring"
              value={pageSize}
              onChange={(event) => updateQuery({ paginate_limit: event.target.value, paginate_page: "1" })}
            >
              {[10, 25, 50].map((size) => (
                <option key={size} value={size}>{size}</option>
              ))}
            </select>
            <span>entries</span>
          </label>
          <Button onClick={openCreateDialog} disabled={loading}>
            <Plus aria-hidden="true" />
            Add Operator
          </Button>
        </div>

        {loadError && (
          <div role="alert" className="mx-5 mb-4 flex flex-wrap items-center justify-between gap-3 rounded-lg border border-destructive/40 bg-destructive/5 px-4 py-3 text-destructive">
            <span>{loadError}</span>
            <Button variant="outline" size="sm" onClick={refreshList}>
              <RefreshCw aria-hidden="true" />
              Retry
            </Button>
          </div>
        )}

        <div className="max-w-full overflow-x-auto px-5">
          <table className="w-full min-w-[850px] border-collapse text-sm">
            <thead>
              <tr>
                {["Name", "Email", "Phone", "Status", "Role", "Action"].map((heading) => (
                  <th key={heading} scope="col" className="border border-border px-4 py-3 text-left text-xs font-medium text-muted-foreground">
                    {heading}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {loading ? (
                <tr><td colSpan={6} className="border border-border px-4 py-8 text-center text-muted-foreground">Loading operators…</td></tr>
              ) : loadError ? (
                <tr><td colSpan={6} className="border border-border px-4 py-8 text-center text-muted-foreground">Operator list is unavailable.</td></tr>
              ) : operators.length === 0 ? (
                <tr><td colSpan={6} className="border border-border px-4 py-8 text-center text-muted-foreground">No operators found.</td></tr>
              ) : operators.map((operator) => (
                <tr key={operator.id} className="hover:bg-muted/30">
                  <td className="border border-border px-4 py-4 font-medium">{fullName(operator) || "—"}</td>
                  <td className="border border-border px-4 py-4">{operator.email}</td>
                  <td className="border border-border px-4 py-4">{operator.phone || "—"}</td>
                  <td className="border border-border px-4 py-4">{operator.active ? "Active" : "Inactive"}</td>
                  <td className="border border-border px-4 py-4">FIELD OPERATOR</td>
                  <td className="border border-border px-4 py-3">
                    <div className="flex items-center gap-2">
                      <Button
                        variant="ghost"
                        size="icon-sm"
                        aria-label={`Edit ${fullName(operator)}`}
                        title="Edit Operator"
                        onClick={() => void openEditDialog(operator)}
                      >
                        <Pencil aria-hidden="true" />
                      </Button>
                      <Button
                        variant="ghost"
                        size="icon-sm"
                        aria-label={`Delete ${fullName(operator)}`}
                        title="Delete Operator"
                        className="text-muted-foreground hover:text-destructive"
                        onClick={() => setOperatorToDelete(operator)}
                      >
                        <Trash2 aria-hidden="true" />
                      </Button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        <div className="mt-4 flex flex-col gap-3 rounded-b-xl border border-t-0 border-border px-4 py-4 sm:flex-row sm:items-center sm:justify-between">
          <div className="flex items-center justify-center gap-2 sm:justify-end">
            <Button
              variant="outline"
              size="sm"
              disabled={loading || pagination.page <= 1}
              onClick={() => updateQuery({ paginate_page: String(pagination.page - 1) })}
            >
              <ChevronLeft aria-hidden="true" />
              Previous
            </Button>
            <nav aria-label="Pagination" className="flex items-center gap-1">
              {pageNumbers.map((number) => (
                <button
                  key={number}
                  type="button"
                  aria-label={`Go to page ${number}`}
                  aria-current={pagination.page === number ? "page" : undefined}
                  disabled={loading}
                  className={`size-9 rounded-lg text-sm focus-visible:outline-2 focus-visible:outline-ring disabled:opacity-50 ${pagination.page === number ? "bg-accent text-primary" : "hover:bg-muted"}`}
                  onClick={() => updateQuery({ paginate_page: String(number) })}
                >
                  {number}
                </button>
              ))}
            </nav>
            <Button
              variant="outline"
              size="sm"
              disabled={loading || pagination.page >= pagination.pages}
              onClick={() => updateQuery({ paginate_page: String(pagination.page + 1) })}
            >
              Next
              <ChevronRight aria-hidden="true" />
            </Button>
          </div>
          <p className="pt-1 text-center text-sm font-medium text-muted-foreground sm:pt-0 sm:text-left">
            Showing {pagination.start} to {pagination.end} of {pagination.total} entries
          </p>
        </div>
      </Panel>

      <Dialog open={editorOpen} onOpenChange={closeEditor}>
        <DialogContent className="max-h-[90dvh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{editingOperator ? "Edit Operator" : "Add Operator"}</DialogTitle>
            <DialogDescription>
              {editingOperator ? "Update field operator information." : "Fill in the details to add a new field operator."}
            </DialogDescription>
          </DialogHeader>
          {detailLoading ? (
            <p role="status" className="py-8 text-center text-muted-foreground">Loading operator details…</p>
          ) : (
            <form className="space-y-5" onSubmit={(event) => void handleSave(event)}>
              <FormField
                name="operator-organization"
                label="Organization Code"
                value={editingOperator?.organizationCode || organizationCode}
                disabled
              />
              <div className="grid gap-4 sm:grid-cols-2">
                <FormField
                  name="operator-first-name"
                  label="First Name"
                  value={draft.firstName}
                  onChange={(event) => setDraft((current) => ({ ...current, firstName: event.target.value }))}
                  placeholder="Enter first name"
                  required
                />
                <FormField
                  name="operator-last-name"
                  label="Last Name"
                  value={draft.lastName}
                  onChange={(event) => setDraft((current) => ({ ...current, lastName: event.target.value }))}
                  placeholder="Enter last name"
                  required
                />
                <FormField
                  name="operator-email"
                  label="Email"
                  type="email"
                  value={draft.email}
                  onChange={(event) => setDraft((current) => ({ ...current, email: event.target.value }))}
                  placeholder="name@example.com"
                  required
                  disabled={Boolean(editingOperator)}
                />
                <FormField
                  name="operator-phone"
                  label="Phone"
                  value={draft.phone}
                  onChange={(event) => setDraft((current) => ({ ...current, phone: event.target.value }))}
                  placeholder="+62 812-3456-7890"
                  required
                  disabled={Boolean(editingOperator)}
                />
                <SelectField
                  className="sm:col-span-2"
                  name="operator-active"
                  label="Status"
                  value={String(draft.active)}
                  onChange={(event) => setDraft((current) => ({ ...current, active: event.target.value === "true" }))}
                  options={[
                    { value: "true", label: "Active" },
                    { value: "false", label: "Inactive" },
                  ]}
                />
              </div>
              <DialogFooter>
                <Button type="button" variant="outline" disabled={saving} onClick={() => closeEditor(false)}>
                  Cancel
                </Button>
                <Button type="submit" disabled={saving}>
                  {saving ? "Saving…" : editingOperator ? "Save Changes" : "Create Operator"}
                </Button>
              </DialogFooter>
            </form>
          )}
        </DialogContent>
      </Dialog>

      <Dialog open={Boolean(operatorToDelete)} onOpenChange={(open) => !open && setOperatorToDelete(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Delete operator?</DialogTitle>
            <DialogDescription>
              {operatorToDelete ? `${fullName(operatorToDelete)} will be permanently removed.` : "This operator will be permanently removed."}
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button type="button" variant="outline" disabled={deleting} onClick={() => setOperatorToDelete(null)}>
              Cancel
            </Button>
            <Button type="button" variant="destructive" disabled={deleting} onClick={() => void handleDelete()}>
              {deleting ? "Deleting…" : "Delete Operator"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

    </>
  );
}
