/**
 * ActivateJailDialog — confirmation dialog for activating an inactive jail.
 *
 * Displays the jail name and provides optional override fields for bantime,
 * findtime, maxretry, port and logpath.  Calls the activate endpoint on
 * confirmation and propagates the result via callbacks.
 */

import { useState } from "react";
import {
  Button,
  Dialog,
  DialogActions,
  DialogBody,
  DialogContent,
  DialogSurface,
  DialogTitle,
  Field,
  Input,
  MessageBar,
  MessageBarBody,
  Spinner,
  Text,
  tokens,
} from "@fluentui/react-components";
import { activateJail } from "../../api/config";
import type { ActivateJailRequest, InactiveJail } from "../../types/config";
import { ApiError } from "../../api/client";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface ActivateJailDialogProps {
  /** The inactive jail to activate, or null when the dialog is closed. */
  jail: InactiveJail | null;
  /** Whether the dialog is currently open. */
  open: boolean;
  /** Called when the dialog should be closed without taking action. */
  onClose: () => void;
  /** Called after the jail has been successfully activated. */
  onActivated: () => void;
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

/**
 * Confirmation dialog for activating an inactive jail.
 *
 * All override fields are optional — leaving them blank uses the values
 * already in the config files.
 *
 * @param props - Component props.
 * @returns JSX element.
 */
export function ActivateJailDialog({
  jail,
  open,
  onClose,
  onActivated,
}: ActivateJailDialogProps): React.JSX.Element {
  const [bantime, setBantime] = useState("");
  const [findtime, setFindtime] = useState("");
  const [maxretry, setMaxretry] = useState("");
  const [port, setPort] = useState("");
  const [logpath, setLogpath] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const resetForm = (): void => {
    setBantime("");
    setFindtime("");
    setMaxretry("");
    setPort("");
    setLogpath("");
    setError(null);
  };

  const handleClose = (): void => {
    if (submitting) return;
    resetForm();
    onClose();
  };

  const handleConfirm = (): void => {
    if (!jail || submitting) return;

    const overrides: ActivateJailRequest = {};
    if (bantime.trim()) overrides.bantime = bantime.trim();
    if (findtime.trim()) overrides.findtime = findtime.trim();
    if (maxretry.trim()) {
      const n = parseInt(maxretry.trim(), 10);
      if (!isNaN(n)) overrides.maxretry = n;
    }
    if (port.trim()) overrides.port = port.trim();
    if (logpath.trim()) {
      overrides.logpath = logpath
        .split("\n")
        .map((l) => l.trim())
        .filter(Boolean);
    }

    setSubmitting(true);
    setError(null);

    activateJail(jail.name, overrides)
      .then(() => {
        resetForm();
        onActivated();
      })
      .catch((err: unknown) => {
        const msg =
          err instanceof ApiError
            ? err.message
            : err instanceof Error
              ? err.message
              : String(err);
        setError(msg);
      })
      .finally(() => {
        setSubmitting(false);
      });
  };

  if (!jail) return <></>;

  return (
    <Dialog open={open} onOpenChange={(_ev, data) => { if (!data.open) handleClose(); }}>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Activate jail &ldquo;{jail.name}&rdquo;</DialogTitle>
          <DialogContent>
            <Text block style={{ marginBottom: tokens.spacingVerticalM }}>
              This will write <code>enabled = true</code> to{" "}
              <code>jail.d/{jail.name}.local</code> and reload fail2ban. The
              jail will start monitoring immediately.
            </Text>
            <Text block weight="semibold" style={{ marginBottom: tokens.spacingVerticalS }}>
              Override values (leave blank to use config defaults)
            </Text>
            <div
              style={{
                display: "grid",
                gridTemplateColumns: "1fr 1fr",
                gap: tokens.spacingVerticalS,
              }}
            >
              <Field
                label="Ban time"
                hint={jail.bantime ? `Current: ${jail.bantime}` : undefined}
              >
                <Input
                  placeholder={jail.bantime ?? "e.g. 10m"}
                  value={bantime}
                  disabled={submitting}
                  onChange={(_e, d) => { setBantime(d.value); }}
                />
              </Field>
              <Field
                label="Find time"
                hint={jail.findtime ? `Current: ${jail.findtime}` : undefined}
              >
                <Input
                  placeholder={jail.findtime ?? "e.g. 10m"}
                  value={findtime}
                  disabled={submitting}
                  onChange={(_e, d) => { setFindtime(d.value); }}
                />
              </Field>
              <Field
                label="Max retry"
                hint={jail.maxretry != null ? `Current: ${String(jail.maxretry)}` : undefined}
              >
                <Input
                  type="number"
                  placeholder={jail.maxretry != null ? String(jail.maxretry) : "e.g. 5"}
                  value={maxretry}
                  disabled={submitting}
                  onChange={(_e, d) => { setMaxretry(d.value); }}
                />
              </Field>
              <Field
                label="Port"
                hint={jail.port ? `Current: ${jail.port}` : undefined}
              >
                <Input
                  placeholder={jail.port ?? "e.g. ssh"}
                  value={port}
                  disabled={submitting}
                  onChange={(_e, d) => { setPort(d.value); }}
                />
              </Field>
            </div>
            <Field
              label="Log path(s)"
              hint="One path per line; leave blank to use config defaults."
              style={{ marginTop: tokens.spacingVerticalS }}
            >
              <Input
                placeholder={
                  jail.logpath.length > 0 ? jail.logpath[0] : "/var/log/example.log"
                }
                value={logpath}
                disabled={submitting}
                onChange={(_e, d) => { setLogpath(d.value); }}
              />
            </Field>
            {error && (
              <MessageBar
                intent="error"
                style={{ marginTop: tokens.spacingVerticalS }}
              >
                <MessageBarBody>{error}</MessageBarBody>
              </MessageBar>
            )}
          </DialogContent>
          <DialogActions>
            <Button
              appearance="secondary"
              onClick={handleClose}
              disabled={submitting}
            >
              Cancel
            </Button>
            <Button
              appearance="primary"
              onClick={handleConfirm}
              disabled={submitting}
              icon={submitting ? <Spinner size="tiny" /> : undefined}
            >
              {submitting ? "Activating…" : "Activate"}
            </Button>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>
  );
}
