"use client";

import { useRef, useState } from "react";
import { Check, LoaderCircle, ShieldCheck } from "lucide-react";
import { Button } from "@/components/ui/button";
import { SelectField } from "@/components/shared/form-field";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { cn } from "@/lib/utils";
import type { Chargepoint } from "../types";
import { sendChargepointCommand } from "./client-api";
import { validateCommandPayload, type CommandResult as Result } from "./contract.ts";
import { certificateSigningTypeOptions } from "./certificate-contract.ts";
import { CommandResult } from "./command-result";
import { securityWorkflowSteps } from "./security-workflow.ts";

export function SecurityWorkflowDialog({ chargepoint, source, onClose }: { chargepoint: Chargepoint; source: "api" | "preview"; onClose: () => void }) {
  const steps = securityWorkflowSteps();
  const [index, setIndex] = useState(0);
  const [submitting, setSubmitting] = useState(false);
  const [confirmed, setConfirmed] = useState(false);
  const [error, setError] = useState("");
  const [response, setResponse] = useState<Result>();
  const [certificateType, setCertificateType] = useState("SignChargePointCertificate");
  const [signingMode, setSigningMode] = useState<"auto" | "manual">("auto");
  const [certificateChain, setCertificateChain] = useState("");
  const pending = useRef(false);
  const complete = index >= steps.length;
  const step = steps[index];
  const preview = source === "preview";
  const action = step?.command === "certificate-signed" && signingMode === "manual" ? "Send Certificate" : step?.action;

  async function sendStep() {
    if (!step || pending.current || (step.confirm && !confirmed)) return;
    const input = step.command === "update-certificate" ? { certificateType }
      : step.command === "certificate-signed" ? signingMode === "auto" ? { auto: true } : { certificateChain }
        : step.payload;
    const validation = validateCommandPayload(step.command, input);
    if ("error" in validation) {
      setError(validation.error);
      return;
    }
    pending.current = true;
    setSubmitting(true);
    setError("");
    setResponse(undefined);
    try {
      const result: Result = preview ? { accepted: null, data: { preview: true, message: "No command was sent to the device." } } : await sendChargepointCommand(chargepoint.ocppIdentity, step.command, validation.payload);
      setResponse(result);
      if (!preview && result.accepted !== true) {
        setError("This step was not accepted. Review the response and charger Logs before retrying. Later steps have not been sent.");
        return;
      }
      setConfirmed(false);
      if (step.command === "certificate-signed") setCertificateChain("");
      setIndex(current => current + 1);
    } catch (cause) {
      setError(cause instanceof Error ? cause.message : "This step could not be confirmed. Check Logs before retrying.");
    } finally {
      pending.current = false;
      setSubmitting(false);
    }
  }

  return <Dialog open onOpenChange={open => { if (!open && !pending.current) onClose(); }}>
    <DialogContent className="max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-2xl" showCloseButton={!submitting} onEscapeKeyDown={event => { if (pending.current) event.preventDefault(); }} onInteractOutside={event => { if (pending.current) event.preventDefault(); }}>
      <DialogHeader><DialogTitle>Update CP Certificate</DialogTitle><DialogDescription>Complete each step in order and review the response before continuing.</DialogDescription></DialogHeader>
      <div className="flex items-center gap-3 rounded-lg border bg-muted/30 p-3"><ShieldCheck aria-hidden="true" className="size-5 shrink-0 text-primary" /><div className="min-w-0"><p className="truncate font-medium">{chargepoint.name}</p><p className="text-xs text-muted-foreground">{chargepoint.ocppIdentity ?? chargepoint.endpoint}{preview ? " · Local preview" : ""}</p></div></div>
      <ol aria-label="Security workflow progress" className="space-y-2">{steps.map((item, position) => <li key={item.command} aria-current={!complete && index === position ? "step" : undefined} className={cn("flex items-center gap-3 rounded-lg px-3 py-2 text-sm", position === index ? "bg-primary/10" : "text-muted-foreground")}><span className={cn("flex size-6 shrink-0 items-center justify-center rounded-full border text-xs", position < index ? "border-success/30 bg-success/10 text-success" : "border-border")}>{position < index ? <Check aria-hidden="true" className="size-3.5" /> : position + 1}</span><span className="flex-1">{item.title}</span>{position < index && <span className="text-xs">{preview ? "Validated" : "Accepted"}</span>}</li>)}</ol>
      {response && <CommandResult result={response} preview={preview} />}
      {error && <p id="security-workflow-error" role="alert" className="rounded-lg bg-destructive/10 p-3 text-sm text-destructive">{error}</p>}
      {complete ? <p role="status" className="rounded-lg border border-success/25 bg-success/5 p-3 text-sm">{preview ? "Preview complete. No device commands were sent." : "The charger accepted the certificate request. Check Logs for subsequent certificate and connection events."}</p> : <section className="space-y-3 rounded-xl border p-4" aria-busy={submitting}>
        <h3 className="font-semibold">{step.title}</h3><p className="text-sm leading-relaxed text-muted-foreground">{step.description}</p>
        {step.command === "update-certificate" && <SelectField name="certificateType" label="Certificate type" required disabled={submitting} value={certificateType} options={certificateSigningTypeOptions} onChange={event => { setCertificateType(event.target.value); setError(""); }} />}
        {step.command === "certificate-signed" && <div className="space-y-3">
          <SelectField name="signingMode" label="Certificate generation" value={signingMode} disabled={submitting} options={[{ value: "auto", label: "Auto — generate by system" }, { value: "manual", label: "Manual — paste certificate chain" }]} onChange={event => { setSigningMode(event.target.value === "manual" ? "manual" : "auto"); setConfirmed(false); setError(""); }} />
          {signingMode === "manual" ? <div className="space-y-2">
            <label className="field-label" htmlFor="workflow-certificate-chain">PEM certificate chain <span className="text-destructive">*</span></label>
            <textarea id="workflow-certificate-chain" name="certificateChain" required rows={8} maxLength={20_000} value={certificateChain} disabled={submitting} autoComplete="off" spellCheck={false} aria-describedby={`workflow-certificate-help${error ? " security-workflow-error" : ""}`} onChange={event => { setCertificateChain(event.target.value); setConfirmed(false); setError(""); }} className="w-full rounded-lg border border-input bg-card px-3 py-2.5 font-mono text-xs leading-relaxed outline-none focus-visible:ring-2 focus-visible:ring-ring" placeholder={"-----BEGIN CERTIFICATE-----\nPaste the signed certificate chain here\n-----END CERTIFICATE-----"} />
            <p id="workflow-certificate-help" className="text-xs text-muted-foreground">Paste one or more PEM certificates, up to 10,000 characters after normalizing line breaks.</p>
          </div> : <p className="text-xs text-muted-foreground">The backend signs the stored CSR. Check Logs for the charger’s SignCertificate request before sending.</p>}
        </div>}
        {step.confirm && <label className="flex items-start gap-3 rounded-lg border border-warning/25 bg-warning/5 p-3 text-sm"><input type="checkbox" checked={confirmed} disabled={submitting} onChange={event => setConfirmed(event.target.checked)} className="mt-0.5 size-4 shrink-0 accent-primary" /><span>I have reviewed this chargepoint and am ready to send this security change.</span></label>}
        {submitting && <p role="status" className="text-sm text-muted-foreground">Waiting for this step’s response…</p>}
      </section>}
      <p className="text-xs text-muted-foreground">Closing this flow preserves changes already sent to the charger. Requests are never retried automatically.</p>
      <DialogFooter><Button type="button" variant="outline" disabled={submitting} onClick={onClose}>{complete ? "Close" : "Cancel"}</Button>{!complete && <Button type="button" disabled={submitting || (step.confirm && !confirmed)} onClick={sendStep}>{submitting && <LoaderCircle aria-hidden="true" className="size-4 animate-spin motion-reduce:animate-none" />}{submitting ? "Sending…" : preview ? `Validate: ${action}` : action}</Button>}</DialogFooter>
    </DialogContent>
  </Dialog>;
}
