"use client";

import { useState, type FormEvent } from "react";
import { Field, SelectField } from "@/components/shared/field";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import type {
  CreateLocationPayload,
  LocationDirectoryRecord,
  UpdateLocationPayload,
} from "./api-contract";

type LocationPayload = CreateLocationPayload | UpdateLocationPayload;
type LocationDraft = {
  code: string;
  name: string;
  phone: string;
  email: string;
  avatarUrl: string;
  street: string;
  city: string;
  state: string;
  country: string;
  postalCode: string;
  latitude: string;
  longitude: string;
  currency: string;
  isPublic: string;
  active: string;
};

function draftFromRecord(record: LocationDirectoryRecord | null): LocationDraft {
  return record
    ? {
        code: record.code,
        name: record.name,
        phone: record.phone,
        email: record.email,
        avatarUrl: record.avatar_url,
        street: record.address.street_and_number,
        city: record.city,
        state: record.address.state,
        country: record.address.country,
        postalCode: record.address.postal_code,
        latitude: record.latitude === null ? "" : String(record.latitude),
        longitude: record.longitude === null ? "" : String(record.longitude),
        currency: record.currency,
        isPublic: record.public === null ? "" : String(record.public),
        active: String(record.active),
      }
    : {
        code: "",
        name: "",
        phone: "",
        email: "",
        avatarUrl: "",
        street: "",
        city: "",
        state: "",
        country: "",
        postalCode: "",
        latitude: "",
        longitude: "",
        currency: "",
        isPublic: "",
        active: "",
      };
}

function asBoolean(value: string) {
  return value === "true";
}

export function LocationForm({
  record,
  onSave,
  onClose,
}: {
  record: LocationDirectoryRecord | null;
  onSave: (payload: LocationPayload) => Promise<string | null>;
  onClose: () => void;
}) {
  const [draft, setDraft] = useState(() => draftFromRecord(record));
  const [error, setError] = useState("");
  const [saving, setSaving] = useState(false);
  const change = (key: keyof LocationDraft, value: string) =>
    setDraft((previous) => ({ ...previous, [key]: value }));

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError("");
    const latitude = Number(draft.latitude);
    const longitude = Number(draft.longitude);
    if (!draft.code.trim() || !draft.name.trim() || !draft.street.trim() || !draft.city.trim()) {
      setError("Enter a location code, name, street address, and city.");
      return;
    }
    if (
      !draft.latitude.trim() ||
      !draft.longitude.trim() ||
      !Number.isFinite(latitude) ||
      latitude < -90 ||
      latitude > 90 ||
      !Number.isFinite(longitude) ||
      longitude < -180 ||
      longitude > 180
    ) {
      setError("Enter valid coordinates: latitude -90 to 90 and longitude -180 to 180.");
      return;
    }
    if (!/^[A-Za-z]{3}$/.test(draft.currency.trim())) {
      setError("Enter a 3-letter currency code, such as IDR.");
      return;
    }
    if (draft.active === "" || draft.isPublic === "") {
      setError("Choose a status and public visibility.");
      return;
    }
    if (draft.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(draft.email)) {
      setError("Enter a valid email address.");
      return;
    }

    const base = {
      code: draft.code.trim(),
      name: draft.name.trim(),
      phone: draft.phone.trim(),
      email: draft.email.trim(),
      avatar_url: draft.avatarUrl.trim(),
      city: draft.city.trim(),
      latitude,
      longitude,
      currency: draft.currency.trim().toUpperCase(),
      public: asBoolean(draft.isPublic),
      active: asBoolean(draft.active),
    };
    const payload: LocationPayload = record
      ? {
          ...base,
          address: [
            draft.street,
            draft.city,
            draft.state,
            draft.country,
            draft.postalCode,
          ]
            .map((value) => value.trim())
            .filter(Boolean)
            .join(", "),
        }
      : {
          ...base,
          address: {
            street_and_number: draft.street.trim(),
            city: draft.city.trim(),
            state: draft.state.trim(),
            country: draft.country.trim(),
            postal_code: draft.postalCode.trim(),
          },
        };

    setSaving(true);
    try {
      const saveError = await onSave(payload);
      if (saveError) setError(saveError);
    } finally {
      setSaving(false);
    }
  }

  return (
    <Dialog
      open
      onOpenChange={(open) => {
        if (!open && !saving) onClose();
      }}
    >
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-3xl">
        <DialogHeader>
          <DialogTitle>{record ? "Edit location" : "Add location"}</DialogTitle>
          <DialogDescription>
            {record
              ? "Update the location details stored in TIAR."
              : "Add a location to the TIAR location directory."}
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={submit}>
          <div className="grid gap-4 sm:grid-cols-2">
            <Field
              label="Location code"
              required
              value={draft.code}
              onChange={(event) => change("code", event.target.value)}
              maxLength={255}
            />
            <Field
              label="Location name"
              required
              value={draft.name}
              onChange={(event) => change("name", event.target.value)}
              maxLength={255}
            />
            <Field
              label="Email address"
              type="email"
              value={draft.email}
              onChange={(event) => change("email", event.target.value)}
              maxLength={254}
            />
            <Field
              label="Phone"
              value={draft.phone}
              onChange={(event) => change("phone", event.target.value)}
              maxLength={64}
            />
            <Field
              label="Street and number"
              required
              value={draft.street}
              onChange={(event) => change("street", event.target.value)}
            />
            <Field
              label="City"
              required
              value={draft.city}
              onChange={(event) => change("city", event.target.value)}
            />
            <Field
              label="State or province"
              value={draft.state}
              onChange={(event) => change("state", event.target.value)}
            />
            <Field
              label="Postal code"
              value={draft.postalCode}
              onChange={(event) => change("postalCode", event.target.value)}
            />
            <Field
              label="Country"
              value={draft.country}
              onChange={(event) => change("country", event.target.value)}
            />
            <Field
              label="Currency"
              required
              value={draft.currency}
              onChange={(event) => change("currency", event.target.value)}
              placeholder="IDR"
              maxLength={3}
            />
            <Field
              label="Latitude"
              type="number"
              step="any"
              required
              min={-90}
              max={90}
              value={draft.latitude}
              onChange={(event) => change("latitude", event.target.value)}
            />
            <Field
              label="Longitude"
              type="number"
              step="any"
              required
              min={-180}
              max={180}
              value={draft.longitude}
              onChange={(event) => change("longitude", event.target.value)}
            />
            <SelectField
              label="Status"
              value={draft.active}
              options={[
                { value: "", label: "Select status" },
                { value: "true", label: "Active" },
                { value: "false", label: "Inactive" },
              ]}
              onChange={(event) => change("active", event.target.value)}
            />
            <SelectField
              label="Public visibility"
              value={draft.isPublic}
              options={[
                { value: "", label: "Select visibility" },
                { value: "true", label: "Public" },
                { value: "false", label: "Private" },
              ]}
              onChange={(event) => change("isPublic", event.target.value)}
            />
            <Field
              label="Avatar URL"
              value={draft.avatarUrl}
              onChange={(event) => change("avatarUrl", event.target.value)}
              maxLength={2048}
              className="sm:col-span-2"
            />
          </div>
          {error && (
            <p role="alert" className="mt-4 text-sm text-destructive">
              {error}
            </p>
          )}
          <DialogFooter className="mt-6">
            <Button type="button" variant="outline" onClick={onClose} disabled={saving}>
              Cancel
            </Button>
            <Button type="submit" disabled={saving}>
              {saving ? "Saving…" : record ? "Save changes" : "Create location"}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
