import { FormEvent, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Database, Download, Pencil, Plus, RefreshCcw } from "lucide-react";

import { api, authorizedFetch, IpAddress, Network, RuntimeSettings, Subnet } from "../api/client";
import { DataTable } from "../components/DataTable";
import { buttonClass, Field, iconButtonClass, inputClass, secondaryButtonClass, selectClass } from "../components/FormControls";
import { LoadingOverlay } from "../components/LoadingOverlay";
import { Modal } from "../components/Modal";
import { PageHeader } from "../components/PageHeader";

const emptySubnetForm = { network_id: "", cidr: "10.50.0.0/24", gateway: "10.50.0.1", dns: ["10.50.0.10"], dhcp_enabled: false };

export function Ipam() {
  const queryClient = useQueryClient();
  const networks = useQuery({ queryKey: ["networks"], queryFn: () => api<Network[]>("/networks") });
  const subnets = useQuery({ queryKey: ["subnets"], queryFn: () => api<Subnet[]>("/ipam/subnets") });
  const addresses = useQuery({ queryKey: ["addresses"], queryFn: () => api<IpAddress[]>("/ipam/addresses") });
  const settings = useQuery({ queryKey: ["settings"], queryFn: () => api<RuntimeSettings>("/settings") });
  const [message, setMessage] = useState("");
  const [subnetForm, setSubnetForm] = useState(emptySubnetForm);
  const [ipForm, setIpForm] = useState({ subnet_id: "", address: "10.50.0.20", status: "reserved", note: "" });
  const [subnetOpen, setSubnetOpen] = useState(false);
  const [ipOpen, setIpOpen] = useState(false);
  const [busyMessage, setBusyMessage] = useState("");
  const [editingSubnet, setEditingSubnet] = useState<Subnet | null>(null);

  const saveSubnet = useMutation({
    mutationFn: () => api<Subnet>(editingSubnet ? `/ipam/subnets/${editingSubnet.id}` : "/ipam/subnets", {
      method: editingSubnet ? "PATCH" : "POST",
      body: JSON.stringify({ ...subnetForm, network_id: subnetForm.network_id || networks.data?.[0]?.id }),
    }),
    onSuccess: () => {
      setMessage(editingSubnet ? "Subnet updated." : "Subnet created.");
      setSubnetOpen(false);
      setEditingSubnet(null);
      queryClient.invalidateQueries({ queryKey: ["subnets"] });
    },
    onError: (error) => setMessage(error instanceof Error ? error.message : "Subnet save failed."),
  });
  const createIp = useMutation({
    mutationFn: () => api<IpAddress>("/ipam/addresses", { method: "POST", body: JSON.stringify({ ...ipForm, subnet_id: ipForm.subnet_id || subnets.data?.[0]?.id }) }),
    onSuccess: () => {
      setMessage("IP address saved.");
      setIpOpen(false);
      queryClient.invalidateQueries({ queryKey: ["addresses"] });
    },
    onError: (error) => setMessage(error instanceof Error ? error.message : "IP reservation failed."),
  });
  const toggleAutoDiscover = useMutation({
    mutationFn: () => api<RuntimeSettings>("/settings", {
      method: "PATCH",
      body: JSON.stringify({ auto_ipam_sync_enabled: !settings.data?.auto_ipam_sync_enabled }),
    }),
    onSuccess: () => settings.refetch(),
  });

  async function submitSubnet(event: FormEvent) {
    event.preventDefault();
    await saveSubnet.mutateAsync();
  }

  async function submitIp(event: FormEvent) {
    event.preventDefault();
    await createIp.mutateAsync();
  }

  async function exportCsv() {
    setBusyMessage("Preparing IPAM export...");
    try {
      const response = await authorizedFetch("/ipam/export.csv");
      const blob = await response.blob();
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "nexafabric-ipam.csv";
      link.click();
      URL.revokeObjectURL(url);
    } finally {
      setBusyMessage("");
    }
  }

  async function discoverIpam() {
    setBusyMessage("Discovering IP addresses from Proxmox...");
    try {
      const result = await api<{ imported: number; removed: number; errors: Array<Record<string, unknown>> }>("/ipam/discover", { method: "POST" });
      setMessage(`Discovery imported ${result.imported} IP addresses and removed ${result.removed} container bridge entries${result.errors.length ? " with errors" : ""}.`);
      await queryClient.invalidateQueries({ queryKey: ["subnets"] });
      await queryClient.invalidateQueries({ queryKey: ["addresses"] });
    } catch (error) {
      setMessage(error instanceof Error ? error.message : "IPAM discovery failed.");
    } finally {
      setBusyMessage("");
    }
  }

  function addSubnet() {
    setEditingSubnet(null);
    setSubnetForm(emptySubnetForm);
    setSubnetOpen(true);
  }

  function editSubnet(subnet: Subnet) {
    setEditingSubnet(subnet);
    setSubnetForm({
      network_id: subnet.network_id,
      cidr: subnet.cidr,
      gateway: subnet.gateway ?? "",
      dns: subnet.dns ?? [],
      dhcp_enabled: subnet.dhcp_enabled,
    });
    setSubnetOpen(true);
  }

  return (
    <>
      <PageHeader title="IPAM" subtitle="Manage subnets, reservations, assignments, conflicts, and export state." />
      <LoadingOverlay open={Boolean(busyMessage)} message={busyMessage} />
      <div className="space-y-4">
        <div className="flex flex-wrap items-center justify-between gap-3 rounded-md border border-border bg-panel p-3">
          <div>
            <div className="text-sm font-medium">Automatic IPAM discovery</div>
            <div className="text-xs text-slate-500">
              {settings.data?.auto_ipam_sync_enabled ? `Enabled every ${settings.data.auto_ipam_sync_interval_minutes} minutes` : "Disabled"}
            </div>
          </div>
          <button className={secondaryButtonClass} disabled={toggleAutoDiscover.isPending || !settings.data} onClick={() => toggleAutoDiscover.mutate()}>
            <RefreshCcw size={16} />
            {settings.data?.auto_ipam_sync_enabled ? "Disable Auto Discover" : "Enable Auto Discover"}
          </button>
        </div>
        <div className="flex flex-wrap gap-2">
          <button className={buttonClass} onClick={addSubnet}><Plus size={16} /> Add Subnet</button>
          <button className={buttonClass} onClick={() => setIpOpen(true)}><Plus size={16} /> Reserve IP</button>
          <button className={secondaryButtonClass} onClick={discoverIpam}>Discover from Proxmox</button>
          <button className={secondaryButtonClass} onClick={exportCsv}><Download size={16} /> Export CSV</button>
        </div>
        {message ? <div className="rounded-md border border-border bg-panel p-3 text-sm">{message}</div> : null}
        <Modal title={editingSubnet ? "Edit Subnet" : "Add Subnet"} open={subnetOpen} onClose={() => setSubnetOpen(false)}>
          <form onSubmit={submitSubnet}>
          <div className="mb-4 flex items-center gap-2 font-medium"><Database size={18} /> {editingSubnet ? "Edit Subnet" : "Add Subnet"}</div>
          <div className="grid gap-3">
            <Field label="Network">
              <select className={selectClass} value={subnetForm.network_id} onChange={(event) => setSubnetForm({ ...subnetForm, network_id: event.target.value })}>
                <option value="">Auto select</option>
                {(networks.data ?? []).map((network) => <option key={network.id} value={network.id}>{network.name}</option>)}
              </select>
            </Field>
            <Field label="CIDR"><input className={inputClass} value={subnetForm.cidr} onChange={(event) => setSubnetForm({ ...subnetForm, cidr: event.target.value })} /></Field>
            <Field label="Gateway"><input className={inputClass} value={subnetForm.gateway} onChange={(event) => setSubnetForm({ ...subnetForm, gateway: event.target.value })} /></Field>
            <Field label="DNS Servers"><input className={inputClass} value={subnetForm.dns.join(", ")} onChange={(event) => setSubnetForm({ ...subnetForm, dns: event.target.value.split(",").map((item) => item.trim()).filter(Boolean) })} /></Field>
            <label className="flex items-center gap-2 text-sm">
              <input type="checkbox" checked={subnetForm.dhcp_enabled} onChange={(event) => setSubnetForm({ ...subnetForm, dhcp_enabled: event.target.checked })} />
              DHCP enabled
            </label>
            <button className={buttonClass} disabled={saveSubnet.isPending}><Plus size={16} /> {editingSubnet ? "Update Subnet" : "Add Subnet"}</button>
          </div>
          </form>
        </Modal>
        <Modal title="Reserve IP" open={ipOpen} onClose={() => setIpOpen(false)}>
          <form onSubmit={submitIp}>
          <div className="mb-4 flex items-center gap-2 font-medium"><Plus size={18} /> Reserve IP</div>
          <div className="grid gap-3">
            <Field label="Subnet">
              <select className={selectClass} value={ipForm.subnet_id} onChange={(event) => setIpForm({ ...ipForm, subnet_id: event.target.value })}>
                <option value="">Auto select</option>
                {(subnets.data ?? []).map((subnet) => <option key={subnet.id} value={subnet.id}>{subnet.cidr}</option>)}
              </select>
            </Field>
            <Field label="Address"><input className={inputClass} value={ipForm.address} onChange={(event) => setIpForm({ ...ipForm, address: event.target.value })} /></Field>
            <Field label="Status">
              <select className={selectClass} value={ipForm.status} onChange={(event) => setIpForm({ ...ipForm, status: event.target.value })}>
                {["free", "reserved", "assigned", "deprecated", "conflict"].map((status) => <option key={status}>{status}</option>)}
              </select>
            </Field>
            <Field label="Note"><input className={inputClass} value={ipForm.note} onChange={(event) => setIpForm({ ...ipForm, note: event.target.value })} /></Field>
            <button className={buttonClass}><Plus size={16} /> Save IP</button>
          </div>
          </form>
        </Modal>
        <section className="space-y-4">
          <DataTable
            rows={(subnets.data ?? []) as unknown as Record<string, unknown>[]}
            columns={[
              { key: "cidr", label: "Subnet" },
              { key: "gateway", label: "Gateway" },
              { key: "dhcp_enabled", label: "DHCP" },
              {
                key: "actions",
                label: "Actions",
                render: (row) => {
                  const subnet = row as unknown as Subnet;
                  return (
                    <div className="flex justify-end">
                      <button className={iconButtonClass} title="Edit subnet" aria-label={`Edit subnet ${subnet.cidr}`} onClick={() => editSubnet(subnet)}><Pencil size={16} /></button>
                    </div>
                  );
                },
              },
            ]}
          />
          <DataTable
            rows={(addresses.data ?? []) as unknown as Record<string, unknown>[]}
            columns={[
              { key: "address", label: "Address" },
              { key: "subnet_cidr", label: "Subnet" },
              { key: "status", label: "Status" },
              { key: "workload_name", label: "VM/LXC" },
              { key: "workload_external_id", label: "VMID" },
              { key: "note", label: "Note" },
            ]}
          />
        </section>
      </div>
    </>
  );
}
