/**
 * CreateFilterDialog — dialog for creating a new user-defined fail2ban filter.
 *
 * Asks for a filter name and optional failregex / ignoreregex patterns, then
 * calls ``POST /api/config/filters`` on confirmation.
 */

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

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

export interface CreateFilterDialogProps {
  /** Whether the dialog is currently open. */
  open: boolean;
  /** Called when the dialog should close without taking action. */
  onClose: () => void;
  /** Called when the form is submitted with valid dialog data. */
  onCreateFilter: (payload: FilterCreateRequest) => Promise<FilterConfig>;
  /**
   * Called after the filter has been successfully created.
   *
   * @param filter - The newly created FilterConfig returned by the API.
   */
  onCreate: (filter: FilterConfig) => void;
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

/** Split a multiline string into non-empty trimmed lines. */
function splitLines(value: string): string[] {
  return value
    .split("\n")
    .map((l) => l.trim())
    .filter((l) => l.length > 0);
}

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

/**
 * Dialog for creating a new filter in ``filter.d/{name}.local``.
 *
 * The name field accepts a plain base name (e.g. ``my-app``); the ``.local``
 * extension is added by the backend.  failregex and ignoreregex are entered as
 * one pattern per line.
 *
 * @param props - Component props.
 * @returns JSX element.
 */
export function CreateFilterDialog({
  open,
  onClose,
  onCreateFilter,
  onCreate,
}: CreateFilterDialogProps): React.JSX.Element {
  const [name, setName] = useState("");
  const [failregex, setFailregex] = useState("");
  const [ignoreregex, setIgnoreregex] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Reset form when the dialog opens.
  useEffect(() => {
    if (open) {
      setName("");
      setFailregex("");
      setIgnoreregex("");
      setError(null);
    }
  }, [open]);

  const handleClose = useCallback((): void => {
    if (submitting) return;
    onClose();
  }, [submitting, onClose]);

  const handleConfirm = useCallback((): void => {
    const trimmedName = name.trim();
    if (!trimmedName || submitting) return;

    const req: FilterCreateRequest = {
      name: trimmedName,
      failregex: splitLines(failregex),
      ignoreregex: splitLines(ignoreregex),
    };

    setSubmitting(true);
    setError(null);

    onCreateFilter(req)
      .then((filter) => {
        onCreate(filter);
      })
      .catch((err: unknown) => {
        setError(
          err instanceof ApiError ? err.message : "Failed to create filter.",
        );
      })
      .finally(() => {
        setSubmitting(false);
      });
  }, [name, failregex, ignoreregex, submitting, onCreate]);

  const canConfirm = name.trim() !== "" && !submitting;

  return (
    <Dialog open={open} onOpenChange={(_e, data) => { if (!data.open) handleClose(); }}>
      <DialogSurface>
        <DialogBody>
          <DialogTitle>Create Filter</DialogTitle>
          <DialogContent>
            <Text
              as="p"
              size={300}
              style={{ marginBottom: tokens.spacingVerticalM }}
            >
              Creates a new filter definition at{" "}
              <code>filter.d/&lt;name&gt;.local</code>.
            </Text>

            {error !== null && (
              <MessageBar
                intent="error"
                style={{ marginBottom: tokens.spacingVerticalS }}
              >
                <MessageBarBody>{error}</MessageBarBody>
              </MessageBar>
            )}

            <Field
              label="Filter name"
              required
              hint='Base name without extension, e.g. "my-app". Must not already exist.'
            >
              <Input
                value={name}
                onChange={(_e, d) => { setName(d.value); }}
                placeholder="my-app"
                disabled={submitting}
              />
            </Field>

            <Field
              label="failregex patterns"
              hint="One regex pattern per line. Leave blank to add patterns later."
              style={{ marginTop: tokens.spacingVerticalS }}
            >
              <Textarea
                value={failregex}
                onChange={(_e, d) => { setFailregex(d.value); }}
                placeholder={"^%(__prefix_line)s Authentication failure.*<HOST>"}
                rows={4}
                style={{ fontFamily: "monospace", fontSize: 12 }}
                disabled={submitting}
              />
            </Field>

            <Field
              label="ignoreregex patterns"
              hint="Patterns that bypass ban logic. One per line."
              style={{ marginTop: tokens.spacingVerticalS }}
            >
              <Textarea
                value={ignoreregex}
                onChange={(_e, d) => { setIgnoreregex(d.value); }}
                placeholder=""
                rows={2}
                style={{ fontFamily: "monospace", fontSize: 12 }}
                disabled={submitting}
              />
            </Field>
          </DialogContent>
          <DialogActions>
            <Button
              appearance="secondary"
              onClick={handleClose}
              disabled={submitting}
            >
              Cancel
            </Button>
            <Button
              appearance="primary"
              onClick={handleConfirm}
              disabled={!canConfirm}
              icon={submitting ? <Spinner size="extra-small" /> : undefined}
            >
              {submitting ? "Creating…" : "Create Filter"}
            </Button>
          </DialogActions>
        </DialogBody>
      </DialogSurface>
    </Dialog>
  );
}
