"use client";

import { useRef, useState } from "react";
import { MapPin } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { FormField, SelectField } from "@/components/shared/form-field";
import { SearchableFilterField } from "@/components/shared/searchable-filter-field";
import type { Location } from "@/features/locations/types";
import { buildChargepointUpdatePayload } from "./update-contract";
import { updateChargepoint } from "./edit-client-api";
import type { Chargepoint } from "./types";

const booleanOptions = [
  { value: "true", label: "Yes" },
  { value: "false", label: "No" },
];

export function EditChargepointDialog({
  open,
  onOpenChange,
  chargepoint,
  locations,
  onSaved,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  chargepoint: Chargepoint;
  locations: Location[];
  onSaved: () => void;
}) {
  const [locationId, setLocationId] = useState(chargepoint.locationId);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  const errorRef = useRef<HTMLParagraphElement>(null);
  const locationOptions = locations.map((location) => ({
    value: location.id,
    label: location.name,
    description: location.address,
  }));
  if (!locationOptions.some((location) => location.value === chargepoint.locationId)) {
    locationOptions.unshift({
      value: chargepoint.locationId,
      label: chargepoint.locationName,
      description: chargepoint.locationId,
    });
  }
  const deviceFields: { name: string; label: string; value?: string }[] = [
    { name: "vendor", label: "Vendor", value: chargepoint.vendor },
    { name: "model", label: "Model", value: chargepoint.model },
    { name: "firmware_version", label: "Firmware version", value: chargepoint.firmware },
    { name: "box_serial_number", label: "Box serial number", value: chargepoint.boxSerialNumber },
    { name: "cp_serial_number", label: "Chargepoint serial number", value: chargepoint.serialNumber },
    { name: "iccid", label: "ICCID", value: chargepoint.iccid },
    { name: "imsi", label: "IMSI", value: chargepoint.imsi },
    { name: "meter_serial_number", label: "Meter serial number", value: chargepoint.meterSerialNumber },
    { name: "meter_type", label: "Meter type", value: chargepoint.meterType },
  ];

  function changeOpen(nextOpen: boolean) {
    if (saving) return;
    if (!nextOpen) {
      setLocationId(chargepoint.locationId);
      setError("");
    }
    onOpenChange(nextOpen);
  }

  return (
    <Dialog
      open={open}
      onOpenChange={changeOpen}
    >
      <DialogContent className="flex max-h-[92dvh] flex-col gap-0 overflow-clip p-0 sm:max-w-[760px]">
        <DialogHeader className="shrink-0 border-b px-6 py-5 pr-14">
          <DialogTitle>Edit chargepoint</DialogTitle>
          <DialogDescription>
            Update the station settings and save them to the CSMS.
          </DialogDescription>
        </DialogHeader>
        <form
          className="flex min-h-0 flex-1 flex-col"
          onSubmit={async (event) => {
            event.preventDefault();
            if (saving) return;
            setError("");
            if (!locationOptions.some((location) => location.value === locationId)) {
              setError("Select a location from the list.");
              requestAnimationFrame(() => errorRef.current?.focus());
              return;
            }
            const payload = buildChargepointUpdatePayload(
              new FormData(event.currentTarget),
              chargepoint,
            );
            if (!payload) {
              setError("Make a change and check that every field is valid.");
              requestAnimationFrame(() => errorRef.current?.focus());
              return;
            }

            setSaving(true);
            try {
              await updateChargepoint(chargepoint.id, payload);
              changeOpen(false);
              onSaved();
            } catch (cause) {
              setError(
                cause instanceof Error
                  ? cause.message
                  : "Unable to update this chargepoint. Please try again.",
              );
              requestAnimationFrame(() => errorRef.current?.focus());
            } finally {
              setSaving(false);
            }
          }}
        >
          <div className="min-h-0 flex-1 space-y-5 overflow-y-auto px-6 py-5">
            {error && (
              <p
                ref={errorRef}
                tabIndex={-1}
                role="alert"
                className="rounded-lg border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive"
              >
                {error}
              </p>
            )}
            <fieldset disabled={saving} className="space-y-5 disabled:opacity-70">
              <section
                className="rounded-xl border p-4 sm:p-5"
                aria-labelledby="edit-chargepoint-information"
              >
                <h3 id="edit-chargepoint-information" className="mb-4 font-semibold">
                  Station information
                </h3>
                <div className="grid gap-4 sm:grid-cols-2">
                  <FormField
                    name="name"
                    label="Chargepoint name"
                    required
                    maxLength={256}
                    defaultValue={chargepoint.name}
                  />
                  <FormField
                    name="ocpp_identity"
                    label="OCPP identity"
                    maxLength={256}
                    placeholder="Not returned by API"
                    defaultValue={chargepoint.ocppIdentity ?? ""}
                  />
                  <FormField
                    name="static_endpoint"
                    label="Static endpoint"
                    maxLength={256}
                    placeholder="Not returned by API"
                    defaultValue={chargepoint.staticEndpoint ?? ""}
                  />
                  <SelectField
                    name="protocol"
                    label="Protocol"
                    options={[
                      { value: "ocpp1.6", label: "OCPP 1.6" },
                      { value: "ocpp2.0.1", label: "OCPP 2.0.1" },
                    ]}
                    defaultValue={chargepoint.protocol.toLowerCase()}
                  />
                  <SelectField
                    name="active"
                    label="Active status"
                    options={[
                      ...(chargepoint.status === "Unknown"
                        ? [{ value: "", label: "Not returned by API" }]
                        : []),
                      ...booleanOptions.map((option) => ({
                        value: option.value,
                        label: option.value === "true" ? "Active" : "Inactive",
                      })),
                    ]}
                    defaultValue={
                      chargepoint.status === "Unknown"
                        ? ""
                        : String(chargepoint.status === "Active")
                    }
                  />
                  <SelectField
                    name="is_simulator"
                    label="Station type"
                    options={[
                      ...(chargepoint.isSimulator === undefined
                        ? [{ value: "", label: "Not returned by API" }]
                        : []),
                      { value: "false", label: "Physical station" },
                      { value: "true", label: "Simulator" },
                    ]}
                    defaultValue={
                      chargepoint.isSimulator === undefined
                        ? ""
                        : String(chargepoint.isSimulator)
                    }
                  />
                  <SelectField
                    name="status"
                    label="Availability status"
                    options={[
                      ...(chargepoint.availabilityStatus === undefined
                        ? [{ value: "", label: "Not returned by API" }]
                        : []),
                      { value: "available", label: "Available" },
                      { value: "unavailable", label: "Unavailable" },
                    ]}
                    defaultValue={chargepoint.availabilityStatus ?? ""}
                  />
                  <SelectField
                    name="enable_authorization"
                    label="Charging authorization required"
                    options={[
                      ...(chargepoint.enableAuthorization === undefined
                        ? [{ value: "", label: "Not returned by API" }]
                        : []),
                      ...booleanOptions,
                    ]}
                    defaultValue={
                      chargepoint.enableAuthorization === undefined
                        ? ""
                        : String(chargepoint.enableAuthorization)
                    }
                  />
                  <SelectField
                    name="public"
                    label="Public access"
                    options={booleanOptions}
                    defaultValue={String(chargepoint.visibility === "Public")}
                  />
                  <FormField
                    className="sm:col-span-2"
                    name="description"
                    label="Description"
                    maxLength={2000}
                    defaultValue={chargepoint.description ?? ""}
                  />
                  <FormField
                    className="sm:col-span-2"
                    name="connection_url"
                    label="Connection URL"
                    maxLength={512}
                    defaultValue={chargepoint.connectionUrl ?? ""}
                  />
                </div>
              </section>

              <section
                className="rounded-xl border p-4 sm:p-5"
                aria-labelledby="edit-chargepoint-location"
              >
                <h3
                  id="edit-chargepoint-location"
                  className="mb-4 flex items-center gap-2 font-semibold"
                >
                  <MapPin aria-hidden="true" className="size-4" /> Location
                </h3>
                <SearchableFilterField
                  name="location_id"
                  label="Location"
                  required
                  value={locationId}
                  options={locationOptions}
                  allowCustomValue={false}
                  onValueChange={setLocationId}
                />
                <p className="mt-2 text-xs text-muted-foreground">
                  Keep the existing coordinates or update the station’s exact position.
                </p>
                <div className="mt-4 grid gap-4 sm:grid-cols-2">
                  <FormField
                    name="latitude"
                    label="Latitude"
                    type="number"
                    required
                    min={-90}
                    max={90}
                    step="any"
                    defaultValue={chargepoint.latitude}
                    onWheel={(event) => event.currentTarget.blur()}
                  />
                  <FormField
                    name="longitude"
                    label="Longitude"
                    type="number"
                    required
                    min={-180}
                    max={180}
                    step="any"
                    defaultValue={chargepoint.longitude}
                    onWheel={(event) => event.currentTarget.blur()}
                  />
                </div>
              </section>

              <details className="rounded-xl border p-4 sm:p-5">
                <summary className="cursor-pointer font-semibold">
                  Device details
                </summary>
                <div className="mt-4 grid gap-4 sm:grid-cols-2">
                  {deviceFields.map(({ name, label, value }) => (
                    <FormField
                      key={name}
                      name={name}
                      label={label}
                      maxLength={512}
                      defaultValue={value === "—" ? "" : value}
                    />
                  ))}
                </div>
              </details>
            </fieldset>
          </div>
          <DialogFooter className="mx-0 mb-0 shrink-0 rounded-b-xl border-t px-6 py-4">
            <Button
              type="button"
              variant="outline"
              disabled={saving}
              onClick={() => onOpenChange(false)}
            >
              Cancel
            </Button>
            <Button type="submit" disabled={saving}>
              {saving ? "Saving…" : "Save changes"}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
