"use client";

import { useRef, useState } from "react";
import { ListChecks, LoaderCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { SelectField } from "@/components/shared/form-field";
import { certificateTypeOptions, isCertificateType, type CertificateHashData, type CertificateType } from "./certificate-contract.ts";
import { sendChargepointCommand } from "./client-api";
import type { CommandResult } from "./contract.ts";

export function InstalledCertificates({ chargepointId, source, initialType = "CentralSystemRootCertificate", selectable = false, invalidField, onSelectionChange }: {
  chargepointId: string;
  source: "api" | "preview";
  initialType?: CertificateType;
  selectable?: boolean;
  invalidField?: string;
  onSelectionChange?: (value: string) => void;
}) {
  const [certificateType, setCertificateType] = useState<CertificateType>(initialType);
  const [certificates, setCertificates] = useState<CertificateHashData[]>();
  const [selected, setSelected] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [response, setResponse] = useState<CommandResult>();
  const pending = useRef(false);
  const selectedCertificate = certificates?.find(certificate => JSON.stringify(certificate) === selected);

  async function readCertificates() {
    if (pending.current || source === "preview") return;
    pending.current = true;
    setLoading(true);
    setSelected("");
    onSelectionChange?.("");
    setCertificates(undefined);
    setResponse(undefined);
    setError("");
    try {
      const result = await sendChargepointCommand(chargepointId, "get-installed-certificate-ids", { certificateType });
      setResponse(result);
      if (result.accepted !== true && result.status?.toLowerCase() !== "notfound") throw new Error(`The chargepoint returned ${result.status ?? "an unconfirmed request"}. Review the lookup response.`);
      if (!result.certificates) throw new Error("The response did not contain a usable certificate list. Review the lookup response and check Logs.");
      setCertificates(result.certificates);
    } catch (cause) {
      setError(cause instanceof Error ? cause.message : "The certificate read was not confirmed. Check Logs before retrying.");
    } finally {
      pending.current = false;
      setLoading(false);
    }
  }

  return <div className="flex flex-col gap-4 rounded-lg border bg-muted/20 p-4" aria-busy={loading}>
    <div>
      <h3 className="text-sm font-semibold">Installed certificates</h3>
      <p className="mt-1 text-sm text-muted-foreground">{selectable ? "Read the charger’s certificate list, then choose the certificate to remove." : "Read the charger’s certificate list to check the installation."}</p>
    </div>
    <SelectField name="certificateType" id="installed-certificate-type" label="Certificate type" options={certificateTypeOptions} value={certificateType} disabled={loading} onChange={event => {
      if (!isCertificateType(event.target.value)) return;
      setCertificateType(event.target.value);
      setCertificates(undefined);
      setSelected("");
      onSelectionChange?.("");
      setResponse(undefined);
      setError("");
    }} />
    <Button type="button" variant="outline" disabled={loading || source === "preview"} onClick={readCertificates}>
      {loading ? <LoaderCircle aria-hidden="true" className="animate-spin motion-reduce:animate-none" /> : <ListChecks aria-hidden="true" />}
      {loading ? "Reading…" : selectable ? "Read installed certificates" : "Check installed certificates"}
    </Button>
    {source === "preview" && <p className="text-sm text-muted-foreground">Connect to the API to read installed certificates and select one for deletion.</p>}
    {loading && <p role="status" className="text-sm text-muted-foreground">Waiting for the charger’s certificate list…</p>}
    {error && <p role="alert" className="text-sm text-destructive">{error}</p>}
    {certificates && !certificates.length && <p role="status" className="text-sm text-muted-foreground">No installed certificates were returned for this type.</p>}
    {certificates && certificates.length > 0 && <>
      <p role="status" className="text-sm text-muted-foreground">{certificates.length} installed {certificates.length === 1 ? "certificate" : "certificates"} returned.</p>
      {selectable ? <SelectField
        name="certificateHashData" id="operation-certificateHashData" label="Certificate to delete" required value={selected}
        aria-invalid={invalidField === "certificateHashData"} aria-describedby={invalidField === "certificateHashData" ? "operation-error" : undefined}
        options={[{ value: "", label: "Choose a certificate" }, ...certificates.map(certificate => ({ value: JSON.stringify(certificate), label: `${certificate.serialNumber} · ${certificate.hashAlgorithm}` }))]}
        onChange={event => {
          const value = certificates.some(certificate => JSON.stringify(certificate) === event.target.value) ? event.target.value : "";
          setSelected(value);
          onSelectionChange?.(value);
        }}
      /> : <div className="overflow-x-auto rounded-lg border bg-card"><table className="data-table w-full"><caption className="sr-only">Installed certificate identifiers returned by the charger</caption><thead><tr><th>Serial number</th><th>Hash algorithm</th></tr></thead><tbody>{certificates.map((certificate, index) => <tr key={`${certificate.serialNumber}-${index}`}><td className="break-all font-mono text-xs">{certificate.serialNumber}</td><td>{certificate.hashAlgorithm}</td></tr>)}</tbody></table></div>}
    </>}
    {selectedCertificate && <div className="rounded-lg border border-warning/25 bg-warning/5 p-3 text-sm">
      <p className="font-medium">Selected certificate</p>
      <p className="mt-1 break-all font-mono text-xs">{selectedCertificate.serialNumber}</p>
      <p className="mt-2 text-muted-foreground">Deleting a trusted root can prevent secure connections that depend on it.</p>
      <details className="mt-3"><summary className="cursor-pointer font-medium focus-visible:outline-2 focus-visible:outline-ring">Certificate hashes</summary><dl className="mt-2 space-y-2 text-xs"><div><dt>Issuer name hash</dt><dd className="mt-1 break-all font-mono">{selectedCertificate.issuerNameHash}</dd></div><div><dt>Issuer key hash</dt><dd className="mt-1 break-all font-mono">{selectedCertificate.issuerKeyHash}</dd></div></dl></details>
    </div>}
    {response && <details className="rounded-lg border bg-card px-3 py-2"><summary className="cursor-pointer text-sm font-medium focus-visible:outline-2 focus-visible:outline-ring">Lookup response</summary><pre className="mt-2 max-h-48 overflow-auto whitespace-pre-wrap break-all font-mono text-xs">{JSON.stringify(response.data, null, 2)}</pre></details>}
  </div>;
}
