"use client";
import { useState } from "react";
import { Zap, ChevronDown } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { FormField, SelectField } from "@/components/shared/form-field";
import { StatusBadge } from "@/components/shared/status-badge";
import { EmptyState } from "@/components/shared/panel";
import {
  parseNozzleCreatePayload,
  parseNozzleUpdatePayload,
  type NozzleWritePayload,
} from "./api-contract";
import {
  createNozzle,
  getNozzleForEdit,
  removeNozzle,
  updateNozzle,
} from "./nozzle-client-api";
import type { Connector } from "./types";
import { ConnectorQrCode } from "./connector-qr-code";

const statusOptions = [
  "Available",
  "Charging",
  "Preparing",
  "Faulted",
  "Unavailable",
  "Reserved",
  "Finishing",
  "SuspendedEV",
  "SuspendedEVSE",
];
const apiNozzleTypes = ["CCS2", "CHADEMO", "TYPE2", "TYPE1"] as const;

function apiNozzleType(type?: string) {
  const normalized = type?.trim().toUpperCase().replace(/[\s_-]/g, "") ?? "";
  if (normalized === "TYPE2CABLE") return "TYPE2";
  return normalized || "CCS2";
}

function apiPayload(data: FormData, selected?: Connector): NozzleWritePayload {
  const payload = {
    active: String(data.get("active")) === "true",
    connector_number: Number(data.get("connector_number")),
    currency: String(data.get("currency") ?? "").trim(),
    description: String(data.get("description") ?? "").trim(),
    format: String(data.get("format") ?? ""),
    name: String(data.get("name") ?? "").trim(),
    nozzle_number: Number(data.get("nozzle_number")),
    power_kw: Number(data.get("power_kw")),
    power_type: String(data.get("power_type") ?? ""),
    status: selected?.status ?? "Available",
    type: String(data.get("type") ?? ""),
  };
  const parsed = selected
    ? parseNozzleUpdatePayload(payload)
    : parseNozzleCreatePayload(payload);
  if (!parsed) throw new Error("Check the connector details and try again.");
  return parsed as NozzleWritePayload;
}

export function ConnectorList({
  data,
  chargepointId,
  chargepointName,
  organizationCode,
  source = "preview",
  readOnly = false,
}: {
  data: Connector[];
  chargepointId?: string;
  chargepointName?: string;
  organizationCode?: string;
  source?: "api" | "preview";
  readOnly?: boolean;
}) {
  const [connectorState, setConnectorState] = useState({ source: data, rows: data });
  const connectors = connectorState.source === data ? connectorState.rows : data;
  const [edit, setEdit] = useState(false);
  const [selected, setSelected] = useState<Connector>();
  const [remove, setRemove] = useState<Connector>();
  const [notice, setNotice] = useState("");
  const [error, setError] = useState("");
  const [loadingId, setLoadingId] = useState("");
  const [expandedConnectorId, setExpandedConnectorId] = useState<string | null>(null);
  const apiMode = source === "api";
  const selectedApiType = apiNozzleType(selected?.type);
  const apiNozzleTypeOptions = apiNozzleTypes.includes(
    selectedApiType as (typeof apiNozzleTypes)[number],
  )
    ? apiNozzleTypes
    : [selectedApiType, ...apiNozzleTypes];
  const usedNumbers = new Set(connectors.map((connector) => connector.number));
  let nextNumber = 1;
  while (usedNumbers.has(nextNumber)) nextNumber++;

  function updateConnectors(update: Connector[] | ((current: Connector[]) => Connector[])) {
    setConnectorState((current) => {
      const rows = current.source === data ? current.rows : data;
      return {
        source: data,
        rows: typeof update === "function" ? update(rows) : update,
      };
    });
  }

  function openCreate() {
    setSelected(undefined);
    setError("");
    setEdit(true);
  }

  async function openEdit(connector: Connector) {
    setError("");
    if (apiMode && chargepointId) {
      setLoadingId(connector.id);
      try {
        setSelected(await getNozzleForEdit(chargepointId, connector.id));
        setEdit(true);
      } catch (loadError) {
        setError(loadError instanceof Error ? loadError.message : "Unable to load this connector.");
      } finally {
        setLoadingId("");
      }
      return;
    }
    setSelected(connector);
    setEdit(true);
  }

  async function saveConnector(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError("");
    const formData = new FormData(event.currentTarget);
    if (apiMode) {
      if (!chargepointId) {
        setError("The chargepoint id is missing.");
        return;
      }
      try {
        const payload = apiPayload(formData, selected);
        const saved = selected
          ? await updateNozzle(chargepointId, selected.id, payload)
          : await createNozzle(chargepointId, payload);
        updateConnectors((rows) =>
          selected
            ? rows.map((row) => row.id === saved.id ? saved : row)
            : [...rows, saved],
        );
        setEdit(false);
        setNotice(selected ? "Connector updated." : "Connector created.");
        window.location.reload();
      } catch (saveError) {
        setError(saveError instanceof Error ? saveError.message : "Unable to save this connector.");
      }
      return;
    }

    const number = Number(formData.get("number"));
    if (!Number.isSafeInteger(number) || number < 1) {
      setError("Enter a positive whole connector number.");
      return;
    }
    if (connectors.some((row) => row.number === number && row.id !== selected?.id)) {
      setError("This connector number is already used.");
      return;
    }
    const saved: Connector = {
      id: selected?.id ?? crypto.randomUUID(),
      number,
      type: String(formData.get("type")),
      power: Number(formData.get("power")),
      status: String(formData.get("status")) as Connector["status"],
    };
    updateConnectors((rows) =>
      selected ? rows.map((row) => row.id === saved.id ? saved : row) : [...rows, saved],
    );
    setEdit(false);
    setNotice("Connector saved in this preview.");
  }

  async function confirmDelete() {
    if (!remove) return;
    setError("");
    if (apiMode && chargepointId) {
      try {
        await removeNozzle(chargepointId, remove.id);
        updateConnectors((rows) => rows.filter((row) => row.id !== remove.id));
        setNotice("Connector deleted.");
        window.location.reload();
      } catch (deleteError) {
        setError(deleteError instanceof Error ? deleteError.message : "Unable to delete this connector.");
      }
    } else {
      updateConnectors((rows) => rows.filter((row) => row.id !== remove.id));
    }
    setRemove(undefined);
  }

  return (
    <>
      {!readOnly && (
        <div className="mb-6 flex items-center justify-between">
          <h2 className="font-semibold">Connectors</h2>
          <Button size="sm" onClick={openCreate}>Create Connector</Button>
        </div>
      )}
      <div className="space-y-6">
        {connectors.map((connector) => {
          const expanded = expandedConnectorId === connector.id;
          const connectorName = connector.name || `Connector ${connector.number}`;
          const rateName = connector.rateName || (
            connector.rateAssignment === "unassigned"
              ? "Not assigned"
              : connector.rateAssignment === "assigned"
                ? "Name not provided"
                : "Not available"
          );
          return (
            <article key={connector.id} className="detail-panel overflow-hidden">
              <div className="flex flex-wrap items-center justify-between gap-4 p-4">
                <div className="flex items-center gap-3">
                  <span className="flex size-10 items-center justify-center rounded-lg bg-accent text-primary">
                    <Zap aria-hidden="true" />
                  </span>
                  <div>
                    <h3 className="font-semibold">
                      {connectorName} - {connector.type}
                    </h3>
                    <p className="text-muted-foreground">
                      {(connector.format ?? (connector.type === "CCS2" ? "CABLE" : "SOCKET"))} · {connector.power} kW · {connector.powerType ?? (connector.type === "CCS2" ? "DC" : "AC_3_PHASE")}
                      {connector.active === false ? " · Inactive" : ""}
                    </p>
                  </div>
                </div>
                <div className="flex items-center gap-3">
                  <StatusBadge>{connector.status}</StatusBadge>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    aria-expanded={expanded}
                    aria-controls={`connector-details-${connector.id}`}
                    aria-label={`${expanded ? "Hide" : "Show"} details for connector ${connector.number}`}
                    onClick={() => setExpandedConnectorId(expanded ? null : connector.id)}
                  >
                    <ChevronDown aria-hidden="true" className={`transition-transform duration-200 motion-reduce:transition-none ${expanded ? "rotate-180" : ""}`} />
                  </Button>
                </div>
              </div>
              <div id={`connector-details-${connector.id}`} hidden={!expanded}>
                {expanded && (
                  <div className="border-t p-4 md:p-5">
                    <div className={`grid gap-4 ${apiMode && chargepointId ? "lg:grid-cols-[240px_minmax(0,1fr)]" : ""}`}>
                      {apiMode && chargepointId && (
                        <ConnectorQrCode
                          chargepointId={chargepointId}
                          chargepointName={chargepointName ?? "Chargepoint"}
                          connector={connector}
                          organizationCode={organizationCode}
                        />
                      )}
                      <div className="grid content-start gap-4 sm:grid-cols-2">
                        <section className="rounded-xl border bg-card p-4" aria-label={`Charging rate for connector ${connector.number}`}>
                          <h4 className="text-sm font-semibold">Charging Rate</h4>
                          <dl className="mt-3 space-y-1 text-sm">
                            <dt className="text-muted-foreground">Rate Name</dt>
                            <dd className="break-words font-medium">{rateName}</dd>
                          </dl>
                          {!connector.rateName && connector.rateAssignment !== "unassigned" && (
                            <p className="mt-2 text-xs text-muted-foreground">
                              The connector response does not include the rate name.
                            </p>
                          )}
                        </section>
                        <section className="rounded-xl border bg-card p-4" aria-label={`Details for connector ${connector.number}`}>
                          <h4 className="text-sm font-semibold">Connector Details</h4>
                          <dl className="mt-3 space-y-3 text-sm">
                            <div>
                              <dt className="text-muted-foreground">Connector ID</dt>
                              <dd className="mt-1 break-all font-medium">{connector.id}</dd>
                            </div>
                            {connector.description && (
                              <div>
                                <dt className="text-muted-foreground">Description</dt>
                                <dd className="mt-1 break-words font-medium">{connector.description}</dd>
                              </div>
                            )}
                            {connector.nozzleNumber !== undefined && (
                              <div>
                                <dt className="text-muted-foreground">Nozzle number</dt>
                                <dd className="mt-1 font-medium">{connector.nozzleNumber}</dd>
                              </div>
                            )}
                          </dl>
                        </section>
                      </div>
                    </div>
                  </div>
                )}
              </div>
              {!readOnly && (
                <div className="flex flex-wrap justify-end gap-2 border-t px-4 py-3">
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={loadingId === connector.id}
                    onClick={() => void openEdit(connector)}
                  >
                    {loadingId === connector.id ? "Loading…" : "Edit"}
                  </Button>
                  {!apiMode && (
                    <Button
                      variant="outline"
                      size="sm"
                      disabled={connector.status !== "Charging"}
                      onClick={() => {
                        updateConnectors((rows) => rows.map((row) => row.id === connector.id ? { ...row, status: "Available" } : row));
                        setNotice("Charging stopped in this preview.");
                      }}
                    >
                      Stop Charging
                    </Button>
                  )}
                  <Button
                    variant="outline"
                    size="sm"
                    className="text-destructive"
                    onClick={() => setRemove(connector)}
                  >
                    Delete
                  </Button>
                </div>
              )}
            </article>
          );
        })}
        {!connectors.length && <EmptyState title="No connectors found" />}
        {error && !edit && <p role="alert" className="text-destructive">{error}</p>}
        {notice && <p role="status" className="text-muted-foreground">{notice}</p>}
      </div>
      {!readOnly && (
        <Dialog open={edit} onOpenChange={setEdit}>
          <DialogContent className="max-h-[90dvh] overflow-y-auto sm:max-w-lg">
            <DialogHeader>
              <DialogTitle>{selected ? "Edit Connector" : "Create Connector"}</DialogTitle>
              <DialogDescription className="sr-only">Connector configuration</DialogDescription>
            </DialogHeader>
            <form onSubmit={(event) => void saveConnector(event)}>
              {apiMode ? (
                <div className="mb-6 grid gap-4 sm:grid-cols-2">
                  <FormField name="name" label="Name" required defaultValue={selected?.name} />
                  <FormField name="description" label="Description" defaultValue={selected?.description} />
                  <FormField name="connector_number" label="Connector Number" type="number" min={1} required defaultValue={selected?.connectorNumber ?? selected?.number ?? nextNumber} />
                  <FormField name="nozzle_number" label="Nozzle Number" type="number" min={1} required defaultValue={selected?.nozzleNumber ?? nextNumber} />
                  <SelectField name="format" label="Format" options={["CABLE", "SOCKET", "INDUCTIVE"]} defaultValue={selected?.format ?? "CABLE"} />
                  <SelectField name="type" label="Type" options={apiNozzleTypeOptions} defaultValue={selectedApiType} />
                  <SelectField name="power_type" label="Power Type" options={["AC_3_PHASE", "AC_1_PHASE", "DC"]} defaultValue={selected?.powerType ?? "DC"} />
                  <FormField name="power_kw" label="Power (kW)" type="number" min={1} step="any" required defaultValue={selected?.power ?? 50} />
                  <FormField name="currency" label="Currency" required defaultValue={selected?.currency ?? "IDR"} />
                  <SelectField name="active" label="Active" options={[{ value: "true", label: "Active" }, { value: "false", label: "Inactive" }]} defaultValue={String(selected?.active ?? true)} />
                  <input type="hidden" name="status" value={selected?.status ?? "Available"} />
                </div>
              ) : (
                <div className="mb-6 grid gap-4 sm:grid-cols-2">
                  <FormField name="number" label="Connector Number" type="number" min={1} required defaultValue={selected?.number ?? nextNumber} />
                  <SelectField name="type" label="Connector Type" options={["Type 2 Cable", "CCS2"]} defaultValue={selected?.type} />
                  <FormField name="power" label="Maximum Power (kW)" type="number" min={1} step="any" required defaultValue={selected?.power ?? 22} />
                  <SelectField name="status" label="Status" options={statusOptions} defaultValue={selected?.status} />
                </div>
              )}
              {error && <p role="alert" className="mb-4 text-destructive">{error}</p>}
              <DialogFooter>
                <Button type="button" variant="outline" onClick={() => setEdit(false)}>Cancel</Button>
                <Button>Save Connector</Button>
              </DialogFooter>
            </form>
          </DialogContent>
        </Dialog>
      )}
      {!readOnly && (
        <Dialog open={!!remove} onOpenChange={(open) => { if (!open) setRemove(undefined); }}>
          <DialogContent className="sm:max-w-md">
            <DialogHeader>
              <DialogTitle>Delete Connector</DialogTitle>
              <DialogDescription>
                Remove Connector {remove?.number}{apiMode ? " from this chargepoint?" : " from this local preview?"}
              </DialogDescription>
            </DialogHeader>
            {error && <p role="alert" className="text-destructive">{error}</p>}
            <DialogFooter>
              <Button variant="outline" onClick={() => setRemove(undefined)}>Cancel</Button>
              <Button variant="destructive" onClick={() => void confirmDelete()}>Delete</Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      )}
    </>
  );
}
