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

import { api } from "../../api/client";
import { Modal } from "../../components/Modal";
import { Page } from "../../components/Page";
import { Table } from "../../components/Table";

const columns = [
  { key: "name", label: "Policy" },
  { key: "targets", label: "Targets" },
  { key: "destinations", label: "Destinations" },
  { key: "mode", label: "Mode" },
  { key: "actions", label: "Actions" }
];

export function PoliciesPage() {
  const queryClient = useQueryClient();
  const query = useQuery({
    queryKey: ["policies"],
    queryFn: api.policies
  });
  const usersQuery = useQuery({
    queryKey: ["users"],
    queryFn: api.users
  });
  const groupsQuery = useQuery({
    queryKey: ["groups"],
    queryFn: api.groups
  });
  const [form, setForm] = useState({
    name: "",
    description: "",
    destinations: "",
    targetType: "user",
    targetIds: [] as string[],
    fullTunnel: false
  });
  const [createOpen, setCreateOpen] = useState(false);
  const [editingPolicyId, setEditingPolicyId] = useState<string | null>(null);
  const [editForm, setEditForm] = useState({
    name: "",
    description: "",
    destinations: "",
    fullTunnel: false,
    isActive: true,
    targetType: "user",
    targetIds: [] as string[]
  });

  const createMutation = useMutation({
    mutationFn: api.createPolicy,
    onSuccess: () => {
      setCreateOpen(false);
      setForm({ name: "", description: "", destinations: "", targetType: "user", targetIds: [], fullTunnel: false });
      void queryClient.invalidateQueries({ queryKey: ["policies"] });
    }
  });

  const updateMutation = useMutation({
    mutationFn: ({ policyId, payload }: { policyId: string; payload: { name: string; description: string; destinations: string[]; full_tunnel: boolean; is_active: boolean; targets: Array<{ type: string; id: string }> } }) =>
      api.updatePolicy(policyId, payload),
    onSuccess: () => {
      setEditingPolicyId(null);
      setEditForm({ name: "", description: "", destinations: "", fullTunnel: false, isActive: true, targetType: "user", targetIds: [] });
      void queryClient.invalidateQueries({ queryKey: ["policies"] });
    }
  });

  const deleteMutation = useMutation({
    mutationFn: api.deletePolicy,
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["policies"] });
    }
  });

  const rows = query.data?.map((policy) => ({
    id: policy.id,
    name: policy.name,
    targets: policy.targets?.length ? policy.targets.map((target) => `${target.type}: ${target.name ?? target.id}`).join(", ") : "No targets",
    destinations: policy.destinations?.join(", ") ?? (policy.full_tunnel ? "0.0.0.0/0" : "-"),
    mode: policy.full_tunnel ? "Full tunnel" : "Split tunnel"
  })) ?? [];

  const selectableUsers = useMemo(() => usersQuery.data ?? [], [usersQuery.data]);
  const selectableGroups = useMemo(() => groupsQuery.data ?? [], [groupsQuery.data]);
  const selectableTargets = form.targetType === "group" ? selectableGroups : selectableUsers;
  const editableTargets = editForm.targetType === "group" ? selectableGroups : selectableUsers;

  function onSubmit(event: FormEvent) {
    event.preventDefault();
    if (!form.targetIds.length) {
      return;
    }
    createMutation.mutate({
      name: form.name,
      description: form.description,
      priority: 100,
      effect: "allow",
      full_tunnel: form.fullTunnel,
      destinations: form.fullTunnel ? ["0.0.0.0/0"] : form.destinations.split(",").map((value) => value.trim()).filter(Boolean),
      targets: form.targetIds.map((id) => ({ type: form.targetType, id }))
    });
  }

  function startEdit(policyId: string) {
    const policy = query.data?.find((item) => item.id === policyId);
    if (!policy) {
      return;
    }
    setEditingPolicyId(policyId);
    const targetType = policy.targets?.[0]?.type ?? "user";
    setEditForm({
      name: policy.name,
      description: policy.description,
      destinations: policy.destinations?.join(", ") ?? "",
      fullTunnel: policy.full_tunnel,
      isActive: policy.is_active,
      targetType,
      targetIds: policy.targets?.filter((target) => target.type === targetType).map((target) => target.id) ?? []
    });
  }

  function onEditSubmit(event: FormEvent) {
    event.preventDefault();
    if (!editingPolicyId) {
      return;
    }
    updateMutation.mutate({
      policyId: editingPolicyId,
      payload: {
        name: editForm.name,
        description: editForm.description,
        destinations: editForm.fullTunnel ? ["0.0.0.0/0"] : editForm.destinations.split(",").map((value) => value.trim()).filter(Boolean),
        full_tunnel: editForm.fullTunnel,
        is_active: editForm.isActive,
        targets: editForm.targetIds.map((id) => ({ type: editForm.targetType, id }))
      }
    });
  }

  function toggleTarget(id: string, editing = false) {
    if (editing) {
      setEditForm((value) => ({
        ...value,
        targetIds: value.targetIds.includes(id)
          ? value.targetIds.filter((item) => item !== id)
          : [...value.targetIds, id]
      }));
      return;
    }

    setForm((value) => ({
      ...value,
      targetIds: value.targetIds.includes(id)
        ? value.targetIds.filter((item) => item !== id)
        : [...value.targetIds, id]
    }));
  }

  return (
    <Page
      title="Policies"
      subtitle="Manage per-user and per-device access controls enforced at the gateway."
      actions={(
        <div className="action-row">
          <span className="pill">Gateway enforced</span>
          <button className="button" type="button" onClick={() => setCreateOpen(true)}>New policy</button>
        </div>
      )}
    >
      {query.isError ? <p className="notice">Unable to load policies from the API.</p> : null}
      {createMutation.isError ? <p className="notice">Unable to create policy.</p> : null}
      {updateMutation.isError ? <p className="notice">Unable to update policy.</p> : null}
      {deleteMutation.isError ? <p className="notice">Unable to delete policy.</p> : null}
      <Table
        columns={columns}
        rows={rows}
        renderCell={(row, column) => {
          if (column.key === "actions") {
            return (
              <div className="action-row">
                <button className="ghost-button" type="button" onClick={() => startEdit(row.id)}>Edit</button>
                <button className="ghost-button" type="button" onClick={() => deleteMutation.mutate(row.id)}>Delete</button>
              </div>
            );
          }
          return <span>{row[column.key as keyof (typeof rows)[number]]}</span>;
        }}
      />
      {createOpen ? (
        <Modal title="Create policy" subtitle="Choose destinations and assign them to users or groups." onClose={() => setCreateOpen(false)}>
          <form className="stacked-form" onSubmit={onSubmit}>
            <input placeholder="policy name" value={form.name} onChange={(event) => setForm((value) => ({ ...value, name: event.target.value }))} />
            <input placeholder="description" value={form.description} onChange={(event) => setForm((value) => ({ ...value, description: event.target.value }))} />
            <select value={form.targetType} onChange={(event) => setForm((value) => ({ ...value, targetType: event.target.value, targetIds: [] }))}>
              <option value="user">Users</option>
              <option value="group">Groups</option>
            </select>
            <div className="selection-panel">
              <p className="eyebrow">{form.targetType === "group" ? "Target groups" : "Target users"}</p>
              <div className="selection-list">
                {selectableTargets.map((target) => (
                  <label className="selection-item" key={target.id}>
                    <input type="checkbox" checked={form.targetIds.includes(target.id)} onChange={() => toggleTarget(target.id)} />
                    <span>{"username" in target ? target.username : target.name}</span>
                  </label>
                ))}
              </div>
            </div>
            <input
              placeholder="destinations: 172.16.10.0/24,10.0.0.5/32"
              value={form.destinations}
              onChange={(event) => setForm((value) => ({ ...value, destinations: event.target.value }))}
              disabled={form.fullTunnel}
            />
            <label className="checkbox">
              <input type="checkbox" checked={form.fullTunnel} onChange={(event) => setForm((value) => ({ ...value, fullTunnel: event.target.checked }))} />
              Full tunnel
            </label>
            <div className="action-row">
              <button className="button" type="submit" disabled={createMutation.isPending}>Create policy</button>
              <button className="ghost-button" type="button" onClick={() => setCreateOpen(false)}>Cancel</button>
            </div>
          </form>
        </Modal>
      ) : null}
      {editingPolicyId ? (
        <Modal title="Edit policy" subtitle="Change targets, mode, and destinations in one place." onClose={() => setEditingPolicyId(null)}>
          <form className="stacked-form" onSubmit={onEditSubmit}>
            <input placeholder="policy name" value={editForm.name} onChange={(event) => setEditForm((value) => ({ ...value, name: event.target.value }))} />
            <input placeholder="description" value={editForm.description} onChange={(event) => setEditForm((value) => ({ ...value, description: event.target.value }))} />
            <select value={editForm.targetType} onChange={(event) => setEditForm((value) => ({ ...value, targetType: event.target.value, targetIds: [] }))}>
              <option value="user">Users</option>
              <option value="group">Groups</option>
            </select>
            <div className="selection-panel">
              <p className="eyebrow">{editForm.targetType === "group" ? "Target groups" : "Target users"}</p>
              <div className="selection-list">
                {editableTargets.map((target) => (
                  <label className="selection-item" key={target.id}>
                    <input type="checkbox" checked={editForm.targetIds.includes(target.id)} onChange={() => toggleTarget(target.id, true)} />
                    <span>{"username" in target ? target.username : target.name}</span>
                  </label>
                ))}
              </div>
            </div>
            <input
              placeholder="destinations"
              value={editForm.destinations}
              onChange={(event) => setEditForm((value) => ({ ...value, destinations: event.target.value }))}
              disabled={editForm.fullTunnel}
            />
            <label className="checkbox">
              <input type="checkbox" checked={editForm.fullTunnel} onChange={(event) => setEditForm((value) => ({ ...value, fullTunnel: event.target.checked }))} />
              Full tunnel
            </label>
            <label className="checkbox">
              <input type="checkbox" checked={editForm.isActive} onChange={(event) => setEditForm((value) => ({ ...value, isActive: event.target.checked }))} />
              Active
            </label>
            <div className="action-row">
              <button className="button" type="submit" disabled={updateMutation.isPending}>Save policy</button>
              <button className="ghost-button" type="button" onClick={() => setEditingPolicyId(null)}>Cancel</button>
            </div>
          </form>
        </Modal>
      ) : null}
    </Page>
  );
}
