"use client";

import { useRef, useState } from "react";
import { Calculator, Info, Loader2, Send } 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 { Panel } from "@/components/shared/panel";
import { runDlmActionRequest } from "./client-api";
import { DlmOperationResult } from "./operation-result";
import type { DlmAction, DlmOperation, DlmSite } from "./types";

export function DlmSiteActions({ site, locationName, activeConnectors, connectorsComplete }: { site: DlmSite; locationName: string; activeConnectors: number; connectorsComplete: boolean }) {
  const [action, setAction] = useState<DlmAction>();
  const [confirming, setConfirming] = useState(false);
  const [error, setError] = useState("");
  const [result, setResult] = useState<DlmOperation>();
  const [completedAt, setCompletedAt] = useState("");
  const pending = useRef(false), cancelButton = useRef<HTMLButtonElement>(null);
  async function run(nextAction: DlmAction) {
    if (pending.current) return;
    pending.current = true; setAction(nextAction); setError(""); setResult(undefined);
    try {
      const operation = await runDlmActionRequest(site.id, nextAction);
      setResult(operation); setCompletedAt(new Date().toISOString()); setConfirming(false);
      if (nextAction === "evaluate") toast.success("Evaluation saved. Review the results below.");
      else if (operation.allocations.some(row => !row.applied)) toast.error("Apply completed with limits not applied. Review the results.");
      else toast.success("Apply request completed. Review the backend results.");
    } catch (cause) { setError(cause instanceof Error ? cause.message : "The DLM request was not confirmed. Refresh before retrying."); }
    finally { pending.current = false; setAction(undefined); }
  }
  function changeOpen(open: boolean) { if (!pending.current) setConfirming(open); }
  return <Panel title="Power allocation" description="Evaluate and Apply are independent actions. Run either whenever needed.">
    <div className="grid gap-4 md:grid-cols-2">
      <div className="flex flex-col items-start rounded-xl border bg-muted/20 p-4 md:p-5">
        <div className="mb-3 flex items-center gap-2"><Calculator aria-hidden="true" className="size-4 text-muted-foreground" /><h3 className="font-semibold">Evaluate &amp; save</h3></div>
        <p className="mb-5 flex-1 text-sm leading-relaxed text-muted-foreground">Save a new evaluation in the backend. This does not send charging limits to the chargers.</p>
        <Button type="button" variant="outline" className="w-full sm:w-auto" disabled={Boolean(action)} aria-busy={action === "evaluate"} onClick={() => run("evaluate")}>
          {action === "evaluate" ? <Loader2 aria-hidden="true" className="animate-spin motion-reduce:animate-none" /> : <Calculator aria-hidden="true" />}{action === "evaluate" ? "Evaluating…" : "Evaluate"}
        </Button>
      </div>
      <div className="flex flex-col items-start rounded-xl border bg-muted/20 p-4 md:p-5">
        <div className="mb-3 flex items-center gap-2"><Send aria-hidden="true" className="size-4 text-muted-foreground" /><h3 className="font-semibold">Apply configuration</h3></div>
        <p className="mb-5 flex-1 text-sm leading-relaxed text-muted-foreground">Send the latest site and connector configuration to the chargers.</p>
        <Button type="button" className="w-full sm:w-auto" disabled={Boolean(action)} onClick={() => { setError(""); setConfirming(true); }}><Send aria-hidden="true" />Apply</Button>
      </div>
    </div>
    <p className="mt-4 flex items-start gap-2 rounded-lg border bg-muted/30 p-3 text-sm text-muted-foreground"><Info aria-hidden="true" className="mt-0.5 size-4 shrink-0" /><span>After changing site settings or assigned connectors, use Apply to send the changes. Saving an evaluation does not apply them.</span></p>
    {error && !confirming && <p role="alert" className="mt-4 rounded-lg border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive">{error}</p>}
    {result && <DlmOperationResult result={result} completedAt={completedAt} />}
    {confirming && <Dialog open onOpenChange={changeOpen}><DialogContent className="max-h-[calc(100dvh-2rem)] overflow-y-auto [&_.text-muted-foreground]:text-foreground/70 sm:max-w-md" showCloseButton={!action} onOpenAutoFocus={event => { event.preventDefault(); cancelButton.current?.focus(); }}><DialogHeader><DialogTitle>Apply charging limits?</DialogTitle><DialogDescription>Send the latest saved DLM configuration to the chargers. This can change charging power.</DialogDescription></DialogHeader><div className="rounded-lg border bg-muted/40 p-4"><p className="break-words font-semibold">{site.name}</p><p className="mt-1 text-sm text-muted-foreground">{site.code} · {locationName}</p><dl className="mt-3 grid grid-cols-2 gap-2 text-sm"><dt className="text-muted-foreground">Site maximum</dt><dd className="text-right tabular-nums">{site.maxPowerKw} kW</dd><dt className="text-muted-foreground">Active assignments</dt><dd className="text-right tabular-nums">{connectorsComplete ? activeConnectors : "Unavailable"}</dd></dl></div><p className="text-xs leading-relaxed text-muted-foreground">Apply uses the current backend configuration. The backend determines which connectors receive limits.</p>{error && <p role="alert" className="text-sm text-destructive">{error}</p>}<DialogFooter><Button ref={cancelButton} type="button" variant="outline" disabled={Boolean(action)} onClick={() => changeOpen(false)}>Cancel</Button><Button type="button" disabled={Boolean(action)} aria-busy={action === "apply"} onClick={() => run("apply")}>{action === "apply" && <Loader2 aria-hidden="true" className="animate-spin motion-reduce:animate-none" />}{action === "apply" ? "Applying…" : "Confirm Apply"}</Button></DialogFooter></DialogContent></Dialog>}
  </Panel>;
}
