import { FormEvent, useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Save, Wand2 } from "lucide-react";

import { api, Network, Policy, SecurityGroup, ServiceCatalogItem, Workload } from "../api/client";
import { buttonClass, Field, inputClass, secondaryButtonClass, selectClass } from "../components/FormControls";
import { PageHeader } from "../components/PageHeader";

type TargetOption = {
  label: string;
  value: string;
};

export function PolicyDesigner() {
  const queryClient = useQueryClient();
  const workloads = useQuery({ queryKey: ["workloads"], queryFn: () => api<Workload[]>("/vms") });
  const securityGroups = useQuery({ queryKey: ["security-groups"], queryFn: () => api<SecurityGroup[]>("/security-groups") });
  const networks = useQuery({ queryKey: ["networks"], queryFn: () => api<Network[]>("/networks") });
  const services = useQuery({ queryKey: ["service-catalog"], queryFn: () => api<ServiceCatalogItem[]>("/service-catalog") });
  const [preview, setPreview] = useState<Record<string, unknown> | null>(null);
  const [form, setForm] = useState({
    name: "",
    source: "any",
    destination: "any",
    service_id: "",
    protocol: "tcp",
    ports: "443",
    action: "allow",
    direction: "ingress",
    enforcement_mode: "enforced",
    logging: true,
    description: "Policy intent",
  });

  const targets = useMemo<TargetOption[]>(() => {
    return [
      { label: "Any", value: "any" },
      ...(workloads.data ?? []).map((workload) => ({ label: `VM/LXC: ${workload.name}`, value: `workload:${workload.id}` })),
      ...(securityGroups.data ?? []).map((group) => ({ label: `Security Group: ${group.name}`, value: `sg:${group.name}` })),
      ...(networks.data ?? []).map((network) => ({ label: `Network: ${network.name}`, value: `network:${network.name}` })),
    ];
  }, [networks.data, securityGroups.data, workloads.data]);

  function payload() {
    const service = services.data?.find((item) => item.id === form.service_id);
    return {
      project_id: null,
      name: form.name.trim(),
      enabled: true,
      definition: {
        source: form.source,
        destination: form.destination,
        service: { protocol: service?.protocol ?? form.protocol, ports: service?.ports ?? form.ports },
        action: form.action,
        direction: form.direction,
        enforcement_mode: form.enforcement_mode,
        logging: form.logging,
        description: form.description,
      },
    };
  }

  const save = useMutation({
    mutationFn: () => api<Policy>("/policies", { method: "POST", body: JSON.stringify(payload()) }),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ["policies"] }),
  });

  async function submit(event: FormEvent) {
    event.preventDefault();
    await save.mutateAsync();
  }

  function dryRun() {
    const current = payload();
    const warnings = [];
    if (current.definition.source === "any" && current.definition.destination === "any") {
      warnings.push("Policy targets all sources and destinations.");
    }
    if (current.definition.enforcement_mode === "audit") {
      warnings.push("Audit mode logs decisions without enforcing them.");
    }
    setPreview({
      affected_workloads: (workloads.data ?? []).filter((workload) =>
        [current.definition.source, current.definition.destination].includes(`workload:${workload.id}`),
      ),
      generated_rule: current.definition,
      conflicts: [],
      warnings,
    });
  }

  return (
    <>
      <PageHeader title="Policy Designer" subtitle="Build tenant-aware microsegmentation policies and inspect their intended impact." />
      <div className="grid gap-4 lg:grid-cols-[1fr_420px]">
        <form onSubmit={submit} className="rounded-md border border-border bg-panel p-4">
          <div className="grid gap-4 md:grid-cols-2">
            <Field label="Policy Name">
              <input
                className={inputClass}
                value={form.name}
                onChange={(event) => setForm({ ...form, name: event.target.value })}
                placeholder="DNS from VMs to resolver"
                required
              />
            </Field>
            <div />
            <Field label="Source">
              <select className={selectClass} value={form.source} onChange={(event) => setForm({ ...form, source: event.target.value })}>
                {targets.map((target) => <option key={target.value} value={target.value}>{target.label}</option>)}
              </select>
            </Field>
            <Field label="Destination">
              <select className={selectClass} value={form.destination} onChange={(event) => setForm({ ...form, destination: event.target.value })}>
                {targets.map((target) => <option key={target.value} value={target.value}>{target.label}</option>)}
              </select>
            </Field>
            <Field label="Service">
              <select className={selectClass} value={form.service_id} onChange={(event) => setForm({ ...form, service_id: event.target.value })}>
                <option value="">Custom</option>
                {(services.data ?? []).map((service) => <option key={service.id} value={service.id}>{service.name} {service.ports}</option>)}
              </select>
            </Field>
            <Field label="Action">
              <select className={selectClass} value={form.action} onChange={(event) => setForm({ ...form, action: event.target.value })}>
                <option>allow</option>
                <option>deny</option>
                <option>reject</option>
              </select>
            </Field>
            <Field label="Protocol"><input className={inputClass} value={form.protocol} onChange={(event) => setForm({ ...form, protocol: event.target.value })} /></Field>
            <Field label="Ports"><input className={inputClass} value={form.ports} onChange={(event) => setForm({ ...form, ports: event.target.value })} /></Field>
            <Field label="Direction">
              <select className={selectClass} value={form.direction} onChange={(event) => setForm({ ...form, direction: event.target.value })}>
                <option>ingress</option>
                <option>egress</option>
              </select>
            </Field>
            <Field label="Mode">
              <select className={selectClass} value={form.enforcement_mode} onChange={(event) => setForm({ ...form, enforcement_mode: event.target.value })}>
                <option value="enforced">enforced</option>
                <option value="audit">audit</option>
              </select>
            </Field>
          </div>
          <Field label="Description">
            <input className={inputClass} value={form.description} onChange={(event) => setForm({ ...form, description: event.target.value })} />
          </Field>
          <label className="mt-4 flex items-center gap-2 text-sm">
            <input type="checkbox" checked={form.logging} onChange={(event) => setForm({ ...form, logging: event.target.checked })} />
            Logging enabled
          </label>
          <div className="mt-5 flex gap-3">
            <button className={secondaryButtonClass} type="button" onClick={dryRun}>
              <Wand2 size={18} />
              Dry Run
            </button>
            <button className={buttonClass} disabled={!form.name.trim() || save.isPending}>
              <Save size={18} />
              Save
            </button>
          </div>
        </form>
        <aside className="rounded-md border border-border bg-panel p-4">
          <div className="mb-3 font-medium">Impact Preview</div>
          <pre className="max-h-[520px] overflow-auto rounded-md border border-border bg-canvas p-3 text-xs">
            {preview ? JSON.stringify(preview, null, 2) : "Run a dry run to calculate affected workloads, warnings, and generated rules."}
          </pre>
        </aside>
      </div>
    </>
  );
}
