import { FormEvent, useState } from "react";
import { Activity, Pencil, PlugZap, Plus, RefreshCw, Trash2, X } from "lucide-react";

import { api } from "../api/client";
import { Button } from "../components/Button";
import type { Monitor } from "../types/api";

interface NetworkChecksPageProps {
  token: string;
  monitors: Monitor[];
  onChanged: () => Promise<void>;
}

type NetworkCheckType = "ping" | "tcp";

export function NetworkChecksPage({ token, monitors, onChanged }: NetworkChecksPageProps) {
  const networkChecks = monitors.filter((monitor) => monitor.monitor_type === "ping" || monitor.monitor_type === "tcp");
  const [checkType, setCheckType] = useState<NetworkCheckType>("ping");
  const [name, setName] = useState("");
  const [host, setHost] = useState("");
  const [port, setPort] = useState(443);
  const [timeoutSeconds, setTimeoutSeconds] = useState(5);
  const [intervalSeconds, setIntervalSeconds] = useState(60);
  const [failureThreshold, setFailureThreshold] = useState(3);
  const [alertEnabled, setAlertEnabled] = useState(true);
  const [editingMonitorId, setEditingMonitorId] = useState<number | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [deletingId, setDeletingId] = useState<number | null>(null);
  const [error, setError] = useState<string | null>(null);

  async function handleSubmit(event: FormEvent) {
    event.preventDefault();
    setSubmitting(true);
    setError(null);
    try {
      if (editingMonitorId) {
        await api.updateMonitor(token, editingMonitorId, {
          name,
          target: checkType === "tcp" ? `${host}:${port}` : host,
          interval_seconds: intervalSeconds,
          config: checkType === "tcp" ? { host, port, timeout_seconds: timeoutSeconds } : { timeout_seconds: timeoutSeconds },
        });
      } else if (checkType === "tcp") {
        await api.createTcpMonitor(token, {
          name,
          host,
          port,
          timeout_seconds: timeoutSeconds,
          interval_seconds: intervalSeconds,
          create_asset: true,
          alert_enabled: alertEnabled,
          alert_severity: "warning",
          failure_threshold: failureThreshold,
        });
      } else {
        await api.createPingMonitor(token, {
          name,
          host,
          timeout_seconds: timeoutSeconds,
          interval_seconds: intervalSeconds,
          create_asset: true,
          alert_enabled: alertEnabled,
          alert_severity: "warning",
          failure_threshold: failureThreshold,
        });
      }
      resetForm();
      await onChanged();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Could not save network check");
    } finally {
      setSubmitting(false);
    }
  }

  function startEdit(monitor: Monitor) {
    const nextType = monitor.monitor_type === "tcp" ? "tcp" : "ping";
    setEditingMonitorId(monitor.id);
    setCheckType(nextType);
    setName(monitor.name);
    setHost(nextType === "tcp" ? String(monitor.config?.host ?? monitor.target.split(":")[0] ?? "") : monitor.target);
    setPort(Number(monitor.config?.port ?? 443));
    setTimeoutSeconds(Number(monitor.config?.timeout_seconds ?? 5));
    setIntervalSeconds(monitor.interval_seconds);
    setAlertEnabled(true);
    setFailureThreshold(3);
    setError(null);
  }

  function resetForm() {
    setEditingMonitorId(null);
    setCheckType("ping");
    setName("");
    setHost("");
    setPort(443);
    setTimeoutSeconds(5);
    setIntervalSeconds(60);
    setFailureThreshold(3);
    setAlertEnabled(true);
  }

  async function deleteMonitor(monitorId: number) {
    setDeletingId(monitorId);
    setError(null);
    try {
      await api.deleteMonitor(token, monitorId);
      await onChanged();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Could not delete network check");
    } finally {
      setDeletingId(null);
    }
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col justify-between gap-4 md:flex-row md:items-end">
        <div>
          <h1 className="text-3xl font-semibold">Network Checks</h1>
          <p className="mt-2 text-sm text-slate-400">ICMP ping checks and TCP port availability checks.</p>
        </div>
        <Button variant="ghost" onClick={onChanged}>
          <RefreshCw size={16} />
          Refresh
        </Button>
      </div>

      <section className="grid gap-5 xl:grid-cols-[420px_minmax(0,1fr)]">
        <form className="space-y-4 rounded-md border border-line bg-[#0d131c] p-5" onSubmit={handleSubmit}>
          <div className="flex items-center gap-2">
            {checkType === "tcp" ? <PlugZap size={18} className="text-pulse" /> : <Activity size={18} className="text-pulse" />}
            <h2 className="text-base font-semibold">{editingMonitorId ? "Edit Network Check" : "Add Network Check"}</h2>
          </div>

          <div className="grid grid-cols-2 rounded-md border border-line bg-slate-950 p-1">
            <button className={modeClass(checkType === "ping")} disabled={Boolean(editingMonitorId)} onClick={() => setCheckType("ping")} type="button">
              Ping
            </button>
            <button className={modeClass(checkType === "tcp")} disabled={Boolean(editingMonitorId)} onClick={() => setCheckType("tcp")} type="button">
              TCP
            </button>
          </div>

          <label className="block space-y-2">
            <span className="text-sm text-slate-300">Name</span>
            <input className="h-10 w-full rounded-md border border-line bg-slate-950 px-3 text-sm outline-none ring-pulse/40 focus:ring-2" value={name} onChange={(event) => setName(event.target.value)} required />
          </label>

          <label className="block space-y-2">
            <span className="text-sm text-slate-300">Host</span>
            <input className="h-10 w-full rounded-md border border-line bg-slate-950 px-3 text-sm outline-none ring-pulse/40 focus:ring-2" value={host} onChange={(event) => setHost(event.target.value)} placeholder="router.local or 192.168.1.1" required />
          </label>

          <div className="grid gap-3 sm:grid-cols-3">
            {checkType === "tcp" ? (
              <label className="block space-y-2">
                <span className="text-sm text-slate-300">Port</span>
                <input className="h-10 w-full rounded-md border border-line bg-slate-950 px-3 text-sm outline-none ring-pulse/40 focus:ring-2" value={port} onChange={(event) => setPort(Number(event.target.value))} min={1} max={65535} type="number" />
              </label>
            ) : null}
            <label className="block space-y-2">
              <span className="text-sm text-slate-300">Timeout</span>
              <input className="h-10 w-full rounded-md border border-line bg-slate-950 px-3 text-sm outline-none ring-pulse/40 focus:ring-2" value={timeoutSeconds} onChange={(event) => setTimeoutSeconds(Number(event.target.value))} min={1} max={60} type="number" />
            </label>
            <label className="block space-y-2">
              <span className="text-sm text-slate-300">Interval</span>
              <input className="h-10 w-full rounded-md border border-line bg-slate-950 px-3 text-sm outline-none ring-pulse/40 focus:ring-2" value={intervalSeconds} onChange={(event) => setIntervalSeconds(Number(event.target.value))} min={10} type="number" />
            </label>
          </div>

          {!editingMonitorId ? (
            <div className="flex items-center justify-between rounded-md border border-line bg-slate-950 px-3 py-2">
              <span className="text-sm text-slate-300">Alert on repeated failures</span>
              <input className="h-5 w-5 accent-teal-400" checked={alertEnabled} onChange={(event) => setAlertEnabled(event.target.checked)} type="checkbox" />
            </div>
          ) : null}

          {!editingMonitorId ? (
            <label className="block space-y-2">
              <span className="text-sm text-slate-300">Failure Threshold</span>
              <input className="h-10 w-full rounded-md border border-line bg-slate-950 px-3 text-sm outline-none ring-pulse/40 focus:ring-2" value={failureThreshold} onChange={(event) => setFailureThreshold(Number(event.target.value))} min={1} max={20} type="number" />
            </label>
          ) : null}

          {error ? <div className="rounded-md border border-red-500/40 bg-red-950/40 p-3 text-sm text-red-200">{error}</div> : null}

          <div className="flex gap-2">
            {editingMonitorId ? (
              <Button className="flex-1" onClick={resetForm} type="button" variant="ghost">
                <X size={16} />
                Cancel
              </Button>
            ) : null}
            <Button className="flex-1" disabled={submitting} type="submit">
              <Plus size={16} />
              {submitting ? "Saving..." : editingMonitorId ? "Save Check" : "Create Check"}
            </Button>
          </div>
        </form>

        <div className="rounded-md border border-line bg-[#0d131c]">
          <div className="border-b border-line p-4">
            <h2 className="text-base font-semibold">Configured Network Checks</h2>
          </div>
          <div className="divide-y divide-line">
            {networkChecks.length ? (
              networkChecks.map((monitor) => (
                <div key={monitor.id} className="grid gap-2 p-4 md:grid-cols-[1fr_90px_110px_250px] md:items-center">
                  <div>
                    <div className="font-medium">{monitor.name}</div>
                    <div className="truncate text-sm text-slate-400">{monitor.target}</div>
                  </div>
                  <span className="text-sm uppercase text-slate-400">{monitor.monitor_type}</span>
                  <Status status={monitor.status} />
                  <div className="flex flex-wrap items-center justify-start gap-2 md:justify-end">
                    <div className="text-sm text-slate-400">{monitor.last_checked_at ? new Date(monitor.last_checked_at).toLocaleTimeString() : "Not checked"}</div>
                    <Button aria-label={`Edit ${monitor.name}`} className="h-8 px-3" onClick={() => startEdit(monitor)} title="Edit check" type="button" variant="ghost">
                      <Pencil className="text-slate-100" size={15} />
                      Edit
                    </Button>
                    <Button aria-label={`Delete ${monitor.name}`} className="h-8 px-3 text-red-100" disabled={deletingId === monitor.id} onClick={() => deleteMonitor(monitor.id)} title="Delete check" type="button" variant="ghost">
                      <Trash2 className="text-red-200" size={15} />
                      Delete
                    </Button>
                  </div>
                </div>
              ))
            ) : (
              <div className="p-6 text-sm text-slate-400">No network checks yet.</div>
            )}
          </div>
        </div>
      </section>
    </div>
  );
}

function modeClass(active: boolean) {
  return `h-8 rounded-md text-sm transition disabled:opacity-70 ${active ? "bg-slate-800 text-white" : "text-slate-400 hover:bg-slate-900 hover:text-white"}`;
}

function Status({ status }: { status: string }) {
  const classes =
    status === "up"
      ? "border-teal-500/40 bg-teal-950/40 text-teal-200"
      : status === "down"
        ? "border-red-500/40 bg-red-950/40 text-red-200"
        : status === "warning"
          ? "border-amber-500/40 bg-amber-950/40 text-amber-200"
          : "border-slate-600 bg-slate-900 text-slate-300";
  return <span className={`inline-flex h-7 w-24 items-center justify-center rounded-md border text-xs font-medium ${classes}`}>{status}</span>;
}
