"use client";

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import Link from "next/link";
import { api, Monitor, MonitorInput, MonitorType } from "@/lib/api";
import { Button } from "@/components/ui";
import { formatDuration } from "@/components/monitors/MonitorVisuals";

/*
 * The form is grouped the way the detail page reads it back: what is checked,
 * how often, and who hears about it. The section names are the same words on
 * both screens — someone editing "Fails after" should recognise the number
 * they saw under "Fails after".
 */

const inputClass =
    "w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:border-accent/50 focus:outline-none focus:ring-1 focus:ring-accent/30";

const typeCopy: Record<MonitorType, { title: string; blurb: string; target: string }> = {
    http: { title: "HTTP", blurb: "Requests a URL and checks the response", target: "URL" },
    tcp: { title: "TCP", blurb: "Opens a socket on a host and port", target: "Host and port" },
    icmp: { title: "Ping", blurb: "Pings a host and measures round trip", target: "Host" },
    tls: { title: "TLS", blurb: "Reads a certificate and counts days left", target: "Host and port" },
};

function Section({ title, hint, children }: { title: string; hint?: string; children: React.ReactNode }) {
    return (
        <section className="rounded-lg border border-border bg-surface">
            <div className="flex items-baseline justify-between gap-3 border-b border-border-soft px-5 py-3.5">
                <h2 className="text-[15px] font-semibold text-text-primary">{title}</h2>
                {hint && <span className="font-mono text-[10px] uppercase tracking-[0.16em] text-text-tertiary">{hint}</span>}
            </div>
            <div className="flex flex-col gap-4 p-5">{children}</div>
        </section>
    );
}

function Field({ label, help, children }: { label: string; help?: string; children: React.ReactNode }) {
    return (
        <label className="block">
            <span className="mb-1.5 block text-sm font-medium text-text-secondary">{label}</span>
            {children}
            {help && <span className="mt-1.5 block text-xs text-text-tertiary">{help}</span>}
        </label>
    );
}

function Check({
    checked,
    onChange,
    title,
    detail,
}: {
    checked: boolean;
    onChange: (v: boolean) => void;
    title: React.ReactNode;
    detail?: React.ReactNode;
}) {
    return (
        <label
            className={`flex cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 transition-colors ${
                checked ? "border-accent/50 bg-accent/5" : "border-border bg-surface-2 hover:border-accent/30"
            }`}
        >
            <input
                type="checkbox"
                checked={checked}
                onChange={(e) => onChange(e.target.checked)}
                className="mt-0.5 h-4 w-4 accent-accent"
            />
            <span className="min-w-0">
                <span className="block text-sm text-text-primary">{title}</span>
                {detail && <span className="mt-0.5 block text-xs text-text-tertiary">{detail}</span>}
            </span>
        </label>
    );
}

export function MonitorForm({
    initial,
    submitLabel,
    onSubmit,
    isPending,
    error,
}: {
    initial?: Monitor;
    submitLabel: string;
    onSubmit: (input: MonitorInput) => void;
    isPending: boolean;
    error?: Error | null;
}) {
    const [name, setName] = useState(initial?.name ?? "");
    const [type, setType] = useState<MonitorType>(initial?.type ?? "http");
    const [url, setUrl] = useState(initial?.target.url ?? "");
    const [host, setHost] = useState(initial?.target.host ?? "");
    const [port, setPort] = useState<number>(initial?.target.port ?? 443);
    const [method, setMethod] = useState(initial?.target.method ?? "GET");
    const [expectedStatus, setExpectedStatus] = useState<number>(initial?.target.expected_status ?? 200);
    const [keyword, setKeyword] = useState(initial?.target.keyword ?? "");
    const [tlsWarnDays, setTlsWarnDays] = useState<number>(initial?.target.tls_warn_days ?? 14);
    const [insecure, setInsecure] = useState<boolean>(initial?.target.insecure ?? false);
    const [intervalSec, setIntervalSec] = useState<number>(initial?.interval_sec ?? 60);
    const [retries, setRetries] = useState<number>(initial?.retries ?? 1);
    const [runner, setRunner] = useState(initial?.runner ?? "server");
    const [enabled, setEnabled] = useState(initial?.enabled ?? true);
    const [channelIds, setChannelIds] = useState<string[]>(initial?.channel_ids ?? []);

    const { data: servers } = useQuery({ queryKey: ["servers"], queryFn: () => api.listServers() });
    const { data: channels } = useQuery({ queryKey: ["channels"], queryFn: () => api.listChannels() });

    function handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        const target: MonitorInput["target"] = {};
        if (type === "http") {
            target.url = url;
            target.method = method;
            target.expected_status = expectedStatus;
            if (keyword) target.keyword = keyword;
            target.insecure = insecure;
        } else if (type === "tls") {
            target.host = host;
            target.port = port || 443;
            target.tls_warn_days = tlsWarnDays;
        } else if (type === "icmp") {
            target.host = host;
        } else {
            target.host = host;
            target.port = port;
        }
        onSubmit({ name, type, target, interval_sec: intervalSec, retries, runner, enabled, channel_ids: channelIds });
    }

    const runnerName = runner === "server" ? "the control plane" : servers?.find((s) => s.server_id === runner)?.hostname || "an agent";
    /* Retries are consecutive failures, so the delay before "down" is one
       interval per remaining try after the first. Say it in minutes, because
       that is the number people are actually choosing between. */
    const downAfter = formatDuration(new Date(Date.now() - intervalSec * Math.max(retries, 1) * 1000).toISOString());

    return (
        <form onSubmit={handleSubmit} className="flex max-w-3xl flex-col gap-5">
            <Section title="Check" hint={typeCopy[type].target}>
                <Field label="Name" help="Shown in the fleet list and in every alert this check sends.">
                    <input className={inputClass} value={name} onChange={(e) => setName(e.target.value)} placeholder="Billing API" required />
                </Field>

                <div>
                    <span className="mb-1.5 block text-sm font-medium text-text-secondary">Kind</span>
                    <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
                        {(Object.keys(typeCopy) as MonitorType[]).map((t) => (
                            <button
                                key={t}
                                type="button"
                                onClick={() => setType(t)}
                                aria-pressed={type === t}
                                className={`rounded-lg border px-3 py-2.5 text-left transition-colors ${
                                    type === t
                                        ? "border-accent bg-accent/10"
                                        : "border-border bg-surface-2 hover:border-accent/40"
                                }`}
                            >
                                <span
                                    className={`block font-mono text-[11px] uppercase tracking-[0.1em] ${type === t ? "text-accent" : "text-text-secondary"}`}
                                >
                                    {typeCopy[t].title}
                                </span>
                                <span className="mt-1 block text-[11px] leading-snug text-text-tertiary">{typeCopy[t].blurb}</span>
                            </button>
                        ))}
                    </div>
                </div>

                {type === "http" && (
                    <>
                        <Field label="URL">
                            <input
                                className={`${inputClass} font-mono`}
                                value={url}
                                onChange={(e) => setUrl(e.target.value)}
                                placeholder="https://example.com/healthz"
                                required
                            />
                        </Field>
                        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                            <Field label="Method">
                                <select className={inputClass} value={method} onChange={(e) => setMethod(e.target.value)}>
                                    <option>GET</option>
                                    <option>HEAD</option>
                                </select>
                            </Field>
                            <Field label="Expected status">
                                <input
                                    type="number"
                                    className={`${inputClass} font-mono tabular-nums`}
                                    value={expectedStatus}
                                    onChange={(e) => setExpectedStatus(Number(e.target.value))}
                                />
                            </Field>
                        </div>
                        <Field label="Body must contain" help="Optional. The check fails if the response body is missing this text.">
                            <input className={inputClass} value={keyword} onChange={(e) => setKeyword(e.target.value)} placeholder="ok" />
                        </Field>
                        <Check
                            checked={insecure}
                            onChange={setInsecure}
                            title="Accept any certificate"
                            detail="Use for self-signed or expired certificates. The check stops reporting TLS problems."
                        />
                    </>
                )}

                {(type === "tcp" || type === "tls" || type === "icmp") && (
                    <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                        <Field label="Host">
                            <input
                                className={`${inputClass} font-mono`}
                                value={host}
                                onChange={(e) => setHost(e.target.value)}
                                placeholder="example.com"
                                required
                            />
                        </Field>
                        {type !== "icmp" && (
                            <Field label="Port">
                                <input
                                    type="number"
                                    className={`${inputClass} font-mono tabular-nums`}
                                    value={port}
                                    onChange={(e) => setPort(Number(e.target.value))}
                                />
                            </Field>
                        )}
                    </div>
                )}

                {type === "tls" && (
                    <Field label="Warn this many days before expiry">
                        <input
                            type="number"
                            className={`${inputClass} font-mono tabular-nums`}
                            value={tlsWarnDays}
                            onChange={(e) => setTlsWarnDays(Number(e.target.value))}
                            min={1}
                        />
                    </Field>
                )}
            </Section>

            <Section title="Schedule">
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                    <Field label="Run every" help="Seconds between checks. Minimum 10.">
                        <input
                            type="number"
                            className={`${inputClass} font-mono tabular-nums`}
                            value={intervalSec}
                            onChange={(e) => setIntervalSec(Number(e.target.value))}
                            min={10}
                        />
                    </Field>
                    <Field label="Fails after" help="Consecutive failures before an incident opens.">
                        <input
                            type="number"
                            className={`${inputClass} font-mono tabular-nums`}
                            value={retries}
                            onChange={(e) => setRetries(Number(e.target.value))}
                            min={1}
                        />
                    </Field>
                </div>

                <Field
                    label="Runs from"
                    help="Pick an agent for anything only reachable from inside that network. Everything else runs centrally."
                >
                    <select className={inputClass} value={runner} onChange={(e) => setRunner(e.target.value)}>
                        <option value="server">Control plane</option>
                        {servers?.map((s) => (
                            <option key={s.server_id} value={s.server_id}>
                                Agent · {s.hostname}
                            </option>
                        ))}
                    </select>
                </Field>

                <p className="rounded-lg bg-well px-4 py-3 font-mono text-[11.5px] leading-relaxed text-text-secondary">
                    Checked every {intervalSec} s from {runnerName}. Reported down after {retries}{" "}
                    {retries === 1 ? "failure" : "consecutive failures"} — roughly {downAfter}.
                </p>
            </Section>

            <Section title="Alerts" hint={channelIds.length > 0 ? `${channelIds.length} selected` : undefined}>
                {!channels || channels.length === 0 ? (
                    <p className="text-sm text-text-secondary">
                        No channels exist yet, so nobody will be told when this check fails.{" "}
                        <Link href="/settings/notifications" className="text-accent hover:underline">
                            Add a channel
                        </Link>
                        .
                    </p>
                ) : (
                    <div className="flex flex-col gap-2">
                        {channels.map((ch) => (
                            <Check
                                key={ch.channel_id}
                                checked={channelIds.includes(ch.channel_id)}
                                onChange={(v) =>
                                    setChannelIds((prev) => (v ? [...prev, ch.channel_id] : prev.filter((id) => id !== ch.channel_id)))
                                }
                                title={ch.name}
                                detail={
                                    <span className="font-mono uppercase tracking-[0.1em]">
                                        {ch.type}
                                        {!ch.enabled && " · disabled, sends nothing"}
                                    </span>
                                }
                            />
                        ))}
                    </div>
                )}

                <Check
                    checked={enabled}
                    onChange={setEnabled}
                    title="Start checking straight away"
                    detail="Turn this off to save the monitor without running it. You can resume it any time."
                />
            </Section>

            {error && (
                <p className="rounded-lg border border-danger/30 bg-danger/10 px-4 py-3 text-sm text-danger">{error.message}</p>
            )}

            <div className="flex gap-3">
                <Button type="submit" variant="primary" loading={isPending}>
                    {submitLabel}
                </Button>
                <Link href="/monitors">
                    <Button type="button" variant="ghost">
                        Cancel
                    </Button>
                </Link>
            </div>
        </form>
    );
}
