/**
 * TypeScript interfaces for the configuration and server settings API.
 */

// ---------------------------------------------------------------------------
// Ban-time escalation
// ---------------------------------------------------------------------------

/** Incremental ban-time escalation settings for a jail. */
export interface BantimeEscalation {
  /** Whether incremental banning is enabled. */
  increment: boolean;
  /** Multiplier applied to base ban time on each repeat offence, or null. */
  factor: number | null;
  /** Python expression for escalated ban time, or null. */
  formula: string | null;
  /** Space-separated per-offence multipliers, or null. */
  multipliers: string | null;
  /** Maximum ban duration in seconds, or null (no cap). */
  max_time: number | null;
  /** Random jitter (seconds) added to escalated ban time, or null. */
  rnd_time: number | null;
  /** Count repeat offences across all jails, not just the current one. */
  overall_jails: boolean;
}

/** Partial update payload for ban-time escalation settings. */
export interface BantimeEscalationUpdate {
  increment?: boolean | null;
  factor?: number | null;
  formula?: string | null;
  multipliers?: string | null;
  max_time?: number | null;
  rnd_time?: number | null;
  overall_jails?: boolean | null;
}

// ---------------------------------------------------------------------------
// Jail Configuration
// ---------------------------------------------------------------------------

export interface JailConfig {
  name: string;
  ban_time: number;
  max_retry: number;
  find_time: number;
  fail_regex: string[];
  ignore_regex: string[];
  log_paths: string[];
  date_pattern: string | null;
  log_encoding: string;
  backend: string;
  /** DNS look-up mode reported by fail2ban: "yes" | "warn" | "no" | "raw". */
  use_dns: string;
  /** Prefix regex prepended to every failregex; empty string means disabled. */
  prefregex: string;
  actions: string[];
  bantime_escalation: BantimeEscalation | null;
}

export interface JailConfigResponse {
  jail: JailConfig;
}

export interface JailConfigListResponse {
  jails: JailConfig[];
  total: number;
}

export interface JailConfigUpdate {
  ban_time?: number | null;
  max_retry?: number | null;
  find_time?: number | null;
  fail_regex?: string[] | null;
  ignore_regex?: string[] | null;
  /** Prefix regex; undefined/null = skip, "" = clear, non-empty = set. */
  prefregex?: string | null;
  date_pattern?: string | null;
  dns_mode?: string | null;
  backend?: string | null;
  log_encoding?: string | null;
  enabled?: boolean | null;
  bantime_escalation?: BantimeEscalationUpdate | null;
}

// ---------------------------------------------------------------------------
// Global Configuration
// ---------------------------------------------------------------------------

export interface GlobalConfig {
  log_level: string;
  log_target: string;
  db_purge_age: number;
  db_max_matches: number;
}

export interface GlobalConfigUpdate {
  log_level?: string | null;
  log_target?: string | null;
  db_purge_age?: number | null;
  db_max_matches?: number | null;
}

// ---------------------------------------------------------------------------
// Server Settings
// ---------------------------------------------------------------------------

export interface ServerSettings {
  log_level: string;
  log_target: string;
  syslog_socket: string | null;
  db_path: string;
  db_purge_age: number;
  db_max_matches: number;
}

export interface ServerSettingsResponse {
  settings: ServerSettings;
}

export interface ServerSettingsUpdate {
  log_level?: string | null;
  log_target?: string | null;
  db_purge_age?: number | null;
  db_max_matches?: number | null;
}

// ---------------------------------------------------------------------------
// Regex Tester
// ---------------------------------------------------------------------------

export interface RegexTestRequest {
  log_line: string;
  fail_regex: string;
}

export interface RegexTestResponse {
  matched: boolean;
  groups: string[];
  error: string | null;
}

// ---------------------------------------------------------------------------
// Log Preview
// ---------------------------------------------------------------------------

export interface LogPreviewRequest {
  log_path: string;
  fail_regex: string;
  num_lines?: number;
}

export interface LogPreviewLine {
  line: string;
  matched: boolean;
  groups: string[];
}

export interface LogPreviewResponse {
  lines: LogPreviewLine[];
  total_lines: number;
  matched_count: number;
  regex_error: string | null;
}

// ---------------------------------------------------------------------------
// Add Log Path
// ---------------------------------------------------------------------------

export interface AddLogPathRequest {
  log_path: string;
  tail?: boolean;
}

// ---------------------------------------------------------------------------
// Map Color Thresholds
// ---------------------------------------------------------------------------

export interface MapColorThresholdsResponse {
  threshold_high: number;
  threshold_medium: number;
  threshold_low: number;
}

export interface MapColorThresholdsUpdate {
  threshold_high: number;
  threshold_medium: number;
  threshold_low: number;
}

// ---------------------------------------------------------------------------
// Jail config files (Task 4a)
// ---------------------------------------------------------------------------

export interface JailConfigFile {
  /** File stem, e.g. "sshd". */
  name: string;
  /** Actual filename, e.g. "sshd.conf". */
  filename: string;
  /** Whether the jail is currently enabled in its config file. */
  enabled: boolean;
}

export interface JailConfigFilesResponse {
  files: JailConfigFile[];
  total: number;
}

export interface JailConfigFileContent extends JailConfigFile {
  content: string;
}

export interface JailConfigFileEnabledUpdate {
  enabled: boolean;
}

// ---------------------------------------------------------------------------
// Generic conf-file entry (filter.d / action.d)
// ---------------------------------------------------------------------------

export interface ConfFileEntry {
  /** Base name without extension, e.g. "sshd". */
  name: string;
  /** Full filename, e.g. "sshd.conf". */
  filename: string;
}

export interface ConfFilesResponse {
  files: ConfFileEntry[];
  total: number;
}

export interface ConfFileContent {
  name: string;
  filename: string;
  content: string;
}

export interface ConfFileUpdateRequest {
  content: string;
}

export interface ConfFileCreateRequest {
  name: string;
  content: string;
}

// ---------------------------------------------------------------------------
// Parsed filter config (Task 2.1 / 2.2)
// ---------------------------------------------------------------------------

/**
 * Structured representation of a ``filter.d/*.conf`` file.
 * Maps 1-to-1 with the backend ``FilterConfig`` Pydantic model.
 */
export interface FilterConfig {
  /** Base name without extension, e.g. "sshd". */
  name: string;
  /** Actual filename, e.g. "sshd.conf". */
  filename: string;
  /** [INCLUDES] before directive, or null. */
  before: string | null;
  /** [INCLUDES] after directive, or null. */
  after: string | null;
  /** [DEFAULT] section key-value pairs (e.g. _daemon, __prefix). */
  variables: Record<string, string>;
  /** prefregex line, or null. */
  prefregex: string | null;
  /** failregex patterns (one per entry). */
  failregex: string[];
  /** ignoreregex patterns (one per entry). */
  ignoreregex: string[];
  /** maxlines, or null. */
  maxlines: number | null;
  /** datepattern, or null. */
  datepattern: string | null;
  /** journalmatch, or null. */
  journalmatch: string | null;
  /**
   * True when this filter is referenced by at least one currently running jail.
   * Defaults to false when the status was not computed (e.g. /parsed endpoint).
   */
  active: boolean;
  /**
   * Names of currently enabled jails that reference this filter.
   * Empty when active is false.
   */
  used_by_jails: string[];
  /** Absolute path to the .conf source file. Empty string when not computed. */
  source_file: string;
  /** True when a .local override file exists alongside the base .conf. */
  has_local_override: boolean;
}

/**
 * Response for GET /api/config/filters.
 * Lists all discovered filters with active/inactive status.
 */
export interface FilterListResponse {
  filters: FilterConfig[];
  total: number;
}

/**
 * Partial update payload for a filter config.
 * All fields are optional; ``null`` means leave unchanged.
 */
export interface FilterConfigUpdate {
  before?: string | null;
  after?: string | null;
  variables?: Record<string, string> | null;
  prefregex?: string | null;
  failregex?: string[] | null;
  ignoreregex?: string[] | null;
  maxlines?: number | null;
  datepattern?: string | null;
  journalmatch?: string | null;
}

// ---------------------------------------------------------------------------
// Parsed action config (Task 3.1 / 3.2)
// ---------------------------------------------------------------------------

/**
 * Structured representation of an ``action.d/*.conf`` file.
 * Maps 1-to-1 with the backend ``ActionConfig`` Pydantic model.
 */
export interface ActionConfig {
  /** Base name without extension, e.g. "iptables". */
  name: string;
  /** Actual filename, e.g. "iptables.conf". */
  filename: string;
  /** [INCLUDES] before directive, or null. */
  before: string | null;
  /** [INCLUDES] after directive, or null. */
  after: string | null;
  /** actionstart command, or null. */
  actionstart: string | null;
  /** actionstop command, or null. */
  actionstop: string | null;
  /** actioncheck command, or null. */
  actioncheck: string | null;
  /** actionban command, or null. */
  actionban: string | null;
  /** actionunban command, or null. */
  actionunban: string | null;
  /** actionflush command, or null. */
  actionflush: string | null;
  /** [Definition] key-value pairs that are not lifecycle commands. */
  definition_vars: Record<string, string>;
  /** [Init] section key-value pairs. */
  init_vars: Record<string, string>;
  /**
   * True when this action is referenced by at least one currently running jail.
   */
  active: boolean;
  /**
   * Names of currently enabled jails that reference this action.
   * Empty when active is false.
   */
  used_by_jails: string[];
  /** Absolute path to the .conf source file. Empty string when not computed. */
  source_file: string;
  /** True when a .local override file exists alongside the base .conf. */
  has_local_override: boolean;
}

/**
 * Response for GET /api/config/actions.
 * Lists all discovered actions with active/inactive status.
 */
export interface ActionListResponse {
  actions: ActionConfig[];
  total: number;
}

/**
 * Payload for ``PUT /api/config/actions/{name}``.
 *
 * Only editable lifecycle fields are accepted.
 * Fields set to ``null`` or omitted leave the existing value unchanged.
 */
export interface ActionUpdateRequest {
  actionstart?: string | null;
  actionstop?: string | null;
  actioncheck?: string | null;
  actionban?: string | null;
  actionunban?: string | null;
  actionflush?: string | null;
  definition_vars?: Record<string, string> | null;
  init_vars?: Record<string, string> | null;
}

/**
 * Payload for ``POST /api/config/actions``.
 *
 * Creates a new user-defined action at ``action.d/{name}.local``.
 */
export interface ActionCreateRequest {
  /** Base name without extension (e.g. ``my-action``). */
  name: string;
  actionstart?: string | null;
  actionstop?: string | null;
  actioncheck?: string | null;
  actionban?: string | null;
  actionunban?: string | null;
  actionflush?: string | null;
  definition_vars?: Record<string, string> | null;
  init_vars?: Record<string, string> | null;
}

/**
 * Payload for ``POST /api/config/jails/{jail_name}/action``.
 *
 * Adds an action to a jail's action list.
 */
export interface AssignActionRequest {
  action_name: string;
  /** Optional parameters for the action (e.g. ``{ port: "ssh" }``). */
  params?: Record<string, string>;
}

/**
 * Partial update payload for an action config.
 * All fields are optional; ``null`` means leave unchanged.
 */
export interface ActionConfigUpdate {
  before?: string | null;
  after?: string | null;
  actionstart?: string | null;
  actionstop?: string | null;
  actioncheck?: string | null;
  actionban?: string | null;
  actionunban?: string | null;
  actionflush?: string | null;
  definition_vars?: Record<string, string> | null;
  init_vars?: Record<string, string> | null;
}

// ---------------------------------------------------------------------------
// Parsed jail file config (Task 6.1 / 6.2)
// ---------------------------------------------------------------------------

/**
 * Settings within a single [jailname] section of a jail.d/*.conf file.
 * Maps 1-to-1 with the backend ``JailSectionConfig`` Pydantic model.
 */
export interface JailSectionConfig {
  enabled: boolean | null;
  port: string | null;
  filter: string | null;
  logpath: string[];
  maxretry: number | null;
  findtime: number | null;
  bantime: number | null;
  action: string[];
  backend: string | null;
  extra: Record<string, string>;
}

/**
 * Structured representation of a ``jail.d/*.conf`` file.
 * Maps 1-to-1 with the backend ``JailFileConfig`` Pydantic model.
 */
export interface JailFileConfig {
  filename: string;
  jails: Record<string, JailSectionConfig>;
}

/**
 * Partial update payload for a jail file config.
 */
export interface JailFileConfigUpdate {
  jails?: Record<string, JailSectionConfig> | null;
}

// ---------------------------------------------------------------------------
// Inactive jail models (Stage 1)
// ---------------------------------------------------------------------------

/**
 * A jail discovered in fail2ban config files that is not currently active.
 *
 * Maps 1-to-1 with the backend ``InactiveJail`` Pydantic model.
 */
export interface InactiveJail {
  /** Jail name from the config section header. */
  name: string;
  /** Filter name (may include mode suffix, e.g. ``sshd[mode=normal]``). */
  filter: string;
  /** Action references listed in the config (raw strings). */
  actions: string[];
  /** Port(s) to monitor, or null. */
  port: string | null;
  /** Log file paths to monitor. */
  logpath: string[];
  /** Ban duration as a raw config string (e.g. ``"10m"``), or null. */
  bantime: string | null;
  /** Failure-counting window as a raw config string, or null. */
  findtime: string | null;
  /** Number of failures before a ban is issued, or null. */
  maxretry: number | null;
  /** Ban duration in seconds, parsed from bantime. */
  ban_time_seconds: number;
  /** Failure-counting window in seconds, parsed from findtime. */
  find_time_seconds: number;
  /** Log encoding, e.g. ``"auto"`` or ``"utf-8"``. */
  log_encoding: string;
  /** Log-monitoring backend. */
  backend: string;
  /** Date pattern for log parsing, or null for auto-detect. */
  date_pattern: string | null;
  /** DNS resolution mode. */
  use_dns: string;
  /** Prefix regex prepended to every failregex. */
  prefregex: string;
  /** List of failure regex patterns. */
  fail_regex: string[];
  /** List of ignore regex patterns. */
  ignore_regex: string[];
  /** Ban-time escalation configuration, or null. */
  bantime_escalation: BantimeEscalation | null;
  /** Absolute path to the config file where this jail is defined. */
  source_file: string;
  /** Effective ``enabled`` value — always ``false`` for inactive jails. */
  enabled: boolean;
  /**
   * True when a ``jail.d/{name}.local`` override file exists for this jail.
   * Indicates that a "Deactivate Jail" cleanup action is available.
   */
  has_local_override: boolean;
}

export interface InactiveJailListResponse {
  jails: InactiveJail[];
  total: number;
}

/**
 * Optional override values when activating an inactive jail.
 */
export interface ActivateJailRequest {
  bantime?: string | null;
  findtime?: string | null;
  maxretry?: number | null;
  port?: string | null;
  logpath?: string[] | null;
}

export interface JailActivationResponse {
  /** Name of the affected jail. */
  name: string;
  /** New activation state: true after activate, false after deactivate. */
  active: boolean;
  /** Human-readable result message. */
  message: string;
  /** Whether fail2ban was still running after the reload. Defaults to true. */
  fail2ban_running: boolean;
  /** Non-fatal pre-activation validation warnings (e.g. missing log path). */
  validation_warnings: string[];
  /**
   * Set when activation failed after the config file was already written.
   * `true` = the system rolled back and recovered automatically.
   * `false` = rollback also failed — manual intervention required.
   * `undefined` = activation succeeded or failed before the file was written.
   */
  recovered?: boolean;
}

// ---------------------------------------------------------------------------
// Jail config recovery models (Task 3)
// ---------------------------------------------------------------------------

/** A single validation issue found in a jail's config. */
export interface JailValidationIssue {
  /** Config field that has the issue, e.g. "filter", "failregex". */
  field: string;
  /** Human-readable description of the issue. */
  message: string;
}

/** Full result of pre-activation validation for a single jail. */
export interface JailValidationResult {
  jail_name: string;
  valid: boolean;
  issues: JailValidationIssue[];
}

/** Response from `POST /api/config/jails/{name}/rollback`. */
export interface RollbackResponse {
  jail_name: string;
  disabled: boolean;
  fail2ban_running: boolean;
  active_jails: number;
  message: string;
}

// ---------------------------------------------------------------------------
// Filter write requests (Task 2.3)
// ---------------------------------------------------------------------------

/**
 * Payload for ``PUT /api/config/filters/{name}``.
 *
 * Only the user-editable ``[Definition]`` fields are accepted.
 * Fields set to ``null`` or omitted leave the existing value unchanged.
 */
export interface FilterUpdateRequest {
  failregex?: string[] | null;
  ignoreregex?: string[] | null;
  datepattern?: string | null;
  journalmatch?: string | null;
}

/**
 * Payload for ``POST /api/config/filters``.
 *
 * Creates a new user-defined filter at ``filter.d/{name}.local``.
 */
export interface FilterCreateRequest {
  /** Base name without extension (e.g. ``my-custom-filter``). */
  name: string;
  failregex?: string[];
  ignoreregex?: string[];
  prefregex?: string | null;
  datepattern?: string | null;
  journalmatch?: string | null;
}

/**
 * Payload for ``POST /api/config/jails/{jail_name}/filter``.
 *
 * Assigns a filter to a jail by writing ``filter = {filter_name}`` to the
 * jail's ``.local`` config file.
 */
export interface AssignFilterRequest {
  filter_name: string;
}

// ---------------------------------------------------------------------------
// fail2ban log viewer types (Task 2)
// ---------------------------------------------------------------------------

/** Response for ``GET /api/config/fail2ban-log``. */
export interface Fail2BanLogResponse {
  /** Resolved absolute path of the log file being read. */
  log_path: string;
  /** Log lines (tail of file, optionally filtered by substring). */
  lines: string[];
  /** Total number of lines in the file before any filtering. */
  total_lines: number;
  /** Current fail2ban log level, e.g. "INFO". */
  log_level: string;
  /** Current fail2ban log target (file path or special value like "STDOUT"). */
  log_target: string;
}

/** Response for ``GET /api/config/service-status``. */
export interface ServiceStatusResponse {
  /** Whether fail2ban is reachable via its socket. */
  online: boolean;
  /** BanGUI application version (or null when offline). */
  version: string | null;
  /** Number of currently active jails. */
  jail_count: number;
  /** Aggregated current ban count across all jails. */
  total_bans: number;
  /** Aggregated current failure count across all jails. */
  total_failures: number;
  /** Current fail2ban log level. */
  log_level: string;
  /** Current fail2ban log target. */
  log_target: string;
}
