"use client";

import { useRef, useState, type FormEvent } from "react";
import { LoaderCircle, Radio, Send } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import type { Chargepoint } from "../types";
import { commandPolicies, isSensitiveConfigurationKey, validateCommandPayload, type CommandResult as Result, type ReadyCommand } from "./contract.ts";
import { sendChargepointCommand } from "./client-api";
import { CommandFields } from "./command-fields";
import { CommandResult } from "./command-result";
import { isCertificateType, type CertificateType } from "./certificate-contract.ts";
import { InstalledCertificates } from "./installed-certificates";

type CommandDialogProps = {
  command: ReadyCommand;
  chargepoint: Chargepoint;
  source: "api" | "preview";
  onClose: () => void;
};

export function CommandDialog({ command, chargepoint, source, onClose }: CommandDialogProps) {
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<{ message: string; field?: string }>();
  const [result, setResult] = useState<Result>();
  const [installedType, setInstalledType] = useState<CertificateType>();
  const [certificateSelection, setCertificateSelection] = useState("");
  const [confirmationScope, setConfirmationScope] = useState("");
  const pending = useRef(false);
  const policy = commandPolicies[command];

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (pending.current) return;
    const form = event.currentTarget;
    const input = Object.fromEntries(new FormData(form));
    for (const name of ["startTime", "stopTime", "oldestTimestamp", "latestTimestamp", "startSchedule", "validFrom", "validTo", "retrieveDateTime", "installDateTime"]) {
      if (typeof input[name] === "string" && input[name]) {
        const date = new Date(input[name]);
        if (!Number.isFinite(date.getTime())) {
          setError({ message: "Enter a valid date and time.", field: name });
          return;
        }
        input[name] = date.toISOString();
      }
    }
    const validation = validateCommandPayload(command, input);
    if ("error" in validation) {
      setError({ message: validation.error, field: validation.field });
      const target = form.querySelector?.<HTMLElement>(`[name="${validation.field}"]:not([type="hidden"])`) ?? form.querySelector?.<HTMLElement>(`[data-operation-field="${validation.field}"]`);
      const details = target?.closest("details");
      if (details) details.open = true;
      target?.focus();
      return;
    }
    if (policy.confirm && input.confirmed !== "yes") {
      setError({ message: "Confirm this operation before sending it.", field: "confirmed" });
      return;
    }
    setError(undefined);
    pending.current = true;
    setSubmitting(true);
    try {
      const response = source === "preview"
        ? { accepted: null, data: { preview: true, message: "Inputs validated. No device request was sent." } }
        : await sendChargepointCommand(chargepoint.id, command, validation.payload);
      setResult(response);
      if (command === "install-certificate" && isCertificateType(validation.payload.certificateType)) setInstalledType(validation.payload.certificateType);
    } catch (cause) {
      setError({ message: cause instanceof Error ? cause.message : "The request was not confirmed. Check Logs before retrying." });
    } finally {
      if (command === "update-password" || (typeof validation.payload.key === "string" && isSensitiveConfigurationKey(validation.payload.key))) {
        const input = form.querySelector?.<HTMLInputElement>('[name="value"]');
        if (input) input.value = "";
      }
      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 ${["set-charging-profile", "signed-update-firmware"].includes(command) ? "sm:max-w-2xl" : "sm:max-w-xl"}`}
        showCloseButton={!submitting}
        onEscapeKeyDown={event => { if (pending.current) event.preventDefault(); }}
        onInteractOutside={event => { if (pending.current) event.preventDefault(); }}
      >
        <DialogHeader>
          <DialogTitle>{policy.title}</DialogTitle>
          <DialogDescription>Review the inputs for this chargepoint before sending your request.</DialogDescription>
        </DialogHeader>
        <div className="flex items-center gap-3 rounded-lg border bg-muted/30 px-4 py-3">
          <Radio 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 {chargepoint.endpoint}{source === "preview" ? " · Local preview" : ""}
            </p>
          </div>
        </div>
        {result ? (
          <>
            <CommandResult result={result} preview={source === "preview"} />
            {command === "install-certificate" && result.accepted === true && installedType && <InstalledCertificates chargepointId={chargepoint.id} source={source} initialType={installedType} />}
            <DialogFooter>
              <Button type="button" variant="outline" onClick={onClose}>Close</Button>
            </DialogFooter>
          </>
        ) : (
          <form onSubmit={submit} onInvalidCapture={event => {
            if (event.target instanceof HTMLElement) {
              const details = event.target.closest("details");
              if (details) details.open = true;
            }
          }} className="flex flex-col gap-5" aria-busy={submitting}>
            <fieldset disabled={submitting} className="flex min-w-0 flex-col gap-5">
              <CommandFields command={command} connectors={chargepoint.connectors} chargepointId={chargepoint.id} source={source} invalidField={error?.field} onCertificateSelection={setCertificateSelection} onConfirmationScopeChange={setConfirmationScope} />
              {policy.confirm && (
                <label className="flex cursor-pointer items-start gap-3 rounded-lg border border-warning/25 bg-warning/5 p-3 text-sm">
                  <input
                    key={command === "delete-certificate" ? certificateSelection : command === "clear-charging-profile" ? confirmationScope : command}
                    name="confirmed" value="yes" type="checkbox" required
                    aria-invalid={error?.field === "confirmed"}
                    aria-describedby={error?.field === "confirmed" ? "operation-error" : undefined}
                    className="mt-0.5 size-4 shrink-0 accent-primary focus-visible:outline-2 focus-visible:outline-ring"
                  />
                  <span>I’ve reviewed the target charger and understand this operation can affect its operation or active charging.</span>
                </label>
              )}
            </fieldset>
            {error && (
              <p id="operation-error" role="alert" className="rounded-lg bg-destructive/10 px-3 py-2.5 text-sm text-destructive">
                {error.message}
              </p>
            )}
            {submitting && (
              <p role="status" className="text-sm text-muted-foreground">
                Waiting for the response. This request will be sent once.
              </p>
            )}
            <DialogFooter>
              <Button type="button" variant="outline" disabled={submitting} onClick={onClose}>Cancel</Button>
              <Button type="submit" disabled={submitting || (command === "delete-certificate" && !certificateSelection)} variant={["reset", "clear-cache", "remote-stop", "delete-certificate", "clear-charging-profile"].includes(command) ? "destructive" : "default"}>
                {submitting ? <LoaderCircle aria-hidden="true" className="animate-spin motion-reduce:animate-none" /> : <Send aria-hidden="true" />}
                {submitting ? "Sending…" : source === "preview" ? "Validate Preview" : "Send Request"}
              </Button>
            </DialogFooter>
          </form>
        )}
      </DialogContent>
    </Dialog>
  );
}
