// useSecurityMalware — TanStack Query hooks for the M33 malware admin
// endpoints. Wire contract per panel-api/internal/api/security_malware.go
// (verified against handler — feedback_verify_wire_contract).
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

import { apiClient } from "../apiClient";

export type MalwareScanner = "maldet" | "clamav" | "yara";
export type MalwareSeverity = "info" | "warn" | "critical";

export interface MalwareStatus {
  // ClamAV fully removed (M33 amendment 3, 2026-04-29). maldet 2.0 native
  // HEX/MD5/SHA-256 + yara-x covers the same coverage at <1/10 the RAM.
  maldet_version?: string;
  maldet_sig_version?: string;
  monitor_active: boolean;
  watch_count_configured?: number;
  watch_ceiling?: number;
  // YARA scanner — yara-x (`yr`) bundled with maldet 2.0.1; legacy
  // `yara` is the fallback engine on hosts without yr.
  yara_engine_version?: string;
  // Built-in YARA rule packs (read-only — refreshed via timers).
  rfxn_rules_present: boolean;
  rfxn_rules_count?: number;
  rfxn_rules_updated?: string;
  rfxn_rules_path?: string;
  signature_base_present: boolean;
  signature_base_files?: number;
  signature_base_updated?: string;
  signature_base_path?: string;
}

export interface MalwareQuarantineRow {
  id: string;
  user_id?: string;
  username?: string;
  original_path: string;
  quarantine_path: string;
  signature: string;
  scanner: MalwareScanner;
  sha256: string;
  size_bytes: number;
  detected_at: string;
  restored_at?: string;
  restored_reason?: string;
  restored_by?: string;
  deleted_at?: string;
}

export interface MalwareEventRow {
  id: string;
  event_type: string;
  source: MalwareScanner;
  severity: MalwareSeverity;
  user_id?: string;
  target_path?: string;
  target_pid?: number;
  signature?: string;
  raw_json: Record<string, unknown>;
  notified: boolean;
  created_at: string;
}

export interface MalwareSettings {
  id: number;
  schedule_cron: string;
  quarantine_retain_days: number;
  max_scan_mb: number;
  notify_threshold: MalwareSeverity;
  realtime_enabled: boolean;
  // M33.2 mail YARA scanner. ADR-0079.
  mail_scan_enabled: boolean;
  mail_scan_all_folders: boolean;
  mail_scan_skip_addresses: string;
  mail_scan_max_attachment_mb: number;
  mail_scan_timeout_sec: number;
  mail_scan_per_tick_budget: number;
}

export interface MalwarePagedResponse<T> {
  data: T[];
  total: number;
  page: number;
  page_size: number;
}

export interface MalwareScanStartResponse {
  session_id: string;
  unit: string;
}

export interface MalwareScanStatus {
  state: string;
  exit_code: number;
  log_tail: string[];
  done: boolean;
}

const BASE = "/admin/security/malware";

export function useMalwareStatus() {
  return useQuery({
    queryKey: ["security", "malware", "status"],
    queryFn: async () => {
      const { data } = await apiClient.get<MalwareStatus>(`${BASE}/status`);
      return data;
    },
    refetchInterval: 30_000,
  });
}

export function useMalwareQuarantine(page = 1, pageSize = 50) {
  return useQuery({
    queryKey: ["security", "malware", "quarantine", page, pageSize],
    queryFn: async () => {
      const { data } = await apiClient.get<MalwarePagedResponse<MalwareQuarantineRow>>(
        `${BASE}/quarantine`,
        { params: { page, limit: pageSize } },
      );
      return data;
    },
    refetchInterval: 30_000,
  });
}

export function useRestoreQuarantine() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (args: { id: string; reason: string }) => {
      const { data } = await apiClient.post(`${BASE}/quarantine/${args.id}/restore`, {
        reason: args.reason,
      });
      return data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["security", "malware", "quarantine"] });
      qc.invalidateQueries({ queryKey: ["security", "malware", "events"] });
    },
  });
}

export function useDeleteQuarantine() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (id: string) => {
      const { data } = await apiClient.delete(`${BASE}/quarantine/${id}`);
      return data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["security", "malware", "quarantine"] });
    },
  });
}

export function useMalwareEvents(filter: {
  source?: MalwareScanner;
  severity?: MalwareSeverity;
  user?: string;
  page?: number;
  pageSize?: number;
} = {}) {
  return useQuery({
    queryKey: ["security", "malware", "events", filter],
    queryFn: async () => {
      const { data } = await apiClient.get<MalwarePagedResponse<MalwareEventRow>>(
        `${BASE}/events`,
        {
          params: {
            source: filter.source,
            severity: filter.severity,
            user: filter.user,
            page: filter.page ?? 1,
            limit: filter.pageSize ?? 100,
          },
        },
      );
      return data;
    },
    refetchInterval: 30_000,
  });
}

export function useStartMalwareScan() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (args: { path?: string; user?: string }) => {
      const { data } = await apiClient.post<MalwareScanStartResponse>(`${BASE}/scan`, args);
      return data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["security", "malware", "user-scans"] });
    },
  });
}

export interface MalwareUserScanRow {
  username: string;
  user_id?: string;
  session_id: string;
  target_path: string;
  state: "running" | "done" | "failed";
  hits: number;
  exit_code?: number;
  started_at: string;
  finished_at?: string;
}

export function useMalwareUserScans() {
  return useQuery({
    queryKey: ["security", "malware", "user-scans"],
    queryFn: async () => {
      const { data } = await apiClient.get<{ data: MalwareUserScanRow[] }>(
        `${BASE}/scan/users`,
      );
      return data.data;
    },
    refetchInterval: (query) => {
      // Poll every 3s while any row is still running; idle to 30s otherwise.
      const rows = query.state.data ?? [];
      return rows.some((r) => r.state === "running") ? 3_000 : 30_000;
    },
  });
}

export function useMalwareScanStatus(sessionId: string | null) {
  return useQuery({
    queryKey: ["security", "malware", "scan-status", sessionId],
    queryFn: async () => {
      const { data } = await apiClient.get<MalwareScanStatus>(
        `${BASE}/scan/${sessionId}/status`,
      );
      return data;
    },
    enabled: !!sessionId,
    refetchInterval: (query) => {
      const last = query.state.data;
      return last && last.done ? false : 1500;
    },
  });
}

export function useUpdateMalwareSignatures() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async () => {
      const { data } = await apiClient.post(`${BASE}/update-signatures`);
      return data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["security", "malware", "status"] });
    },
  });
}

export function useMalwareSettings() {
  return useQuery({
    queryKey: ["security", "malware", "settings"],
    queryFn: async () => {
      const { data } = await apiClient.get<{ data: MalwareSettings }>(`${BASE}/settings`);
      return data.data;
    },
  });
}

export function useUpdateMalwareSettings() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (s: MalwareSettings) => {
      const { data } = await apiClient.put(`${BASE}/settings`, s);
      return data;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["security", "malware", "settings"] });
    },
  });
}

// ---- YARA admin (M33 Step 8) ----

export interface YARARuleEntry {
  filename: string;
  enabled: boolean;
  size_bytes: number;
  sha256: string;
  last_modified: string;
}

export function useYARARules() {
  return useQuery({
    queryKey: ["security", "malware", "yara"],
    queryFn: async () => {
      const { data } = await apiClient.get<{ entries: YARARuleEntry[] }>(`${BASE}/yara`);
      return data.entries;
    },
  });
}

export function useUploadYARARule() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (args: { filename: string; content: string }) => {
      const content_base64 = btoa(args.content);
      const { data } = await apiClient.post(`${BASE}/yara`, {
        filename: args.filename,
        content_base64,
      });
      return data;
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["security", "malware", "yara"] }),
  });
}

export function useToggleYARARule() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (args: { filename: string; enabled: boolean }) => {
      const { data } = await apiClient.patch(`${BASE}/yara/${args.filename}`, {
        enabled: args.enabled,
      });
      return data;
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["security", "malware", "yara"] }),
  });
}

export function useDeleteYARARule() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (filename: string) => {
      const { data } = await apiClient.delete(`${BASE}/yara/${filename}`);
      return data;
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["security", "malware", "yara"] }),
  });
}

// Tetragon hooks removed by M39 (2026-04-30) — see ADR-0072 amendment + ADR-0085.

// ---- Exec audit (M39 ADR-0085) ----

export interface AuditEvent {
  ts: string;
  auid: number;
  username?: string;
  comm?: string;
  exe?: string;
  ppid?: number;
  pid?: number;
}

export interface AuditEventsResponse {
  events: AuditEvent[];
}

export function useAuditRecent(limit = 100) {
  return useQuery({
    queryKey: ["security", "malware", "audit", "recent", limit],
    queryFn: async () => {
      const { data } = await apiClient.get<AuditEventsResponse>(
        `${BASE}/audit/recent`,
        { params: { limit } },
      );
      return data;
    },
    refetchInterval: 60_000,
  });
}
