import { useCallback, useEffect, useMemo } from "react";
import type { Dispatch, MutableRefObject, SetStateAction } from "react";
import { runAutoReviewScan as runAutoReviewScanAction, runVisibleGridScan as runVisibleGridScanAction } from "./scanViewScanActions";
import {
  initializeLearningState,
  loadReviewQueue as loadReviewQueueFromRepo,
  persistParsedArtifact as persistParsedArtifactHelper,
  saveReviewSample as saveReviewSampleHelper,
} from "./scanViewReviewHelpers";
import { createReviewContext, createScanActionContext } from "./scanViewControllerService";
import { useScanCommandListener } from "./useScanCommandListener";
import type { ParsedArtifactCandidate } from "../../../lib/artifactOcrParser";
import type { ScannerLearningRules } from "../../../lib/scannerLearning";
import type { BooleanResult, CaptureOptions, CaptureResult, ClickResult, ReviewSampleRecord } from "../../../types/global";
import type {
  ArtifactRepositoryPort,
  ReviewSampleRepositoryPort,
  LearningRepositoryPort,
  RuntimeRepositoryPort,
  AutomationRepositoryPort,
} from "../../../infrastructure/repositories/rendererBridgeRepositoryTypes";
import type { AutoScanStats, ScanSummary } from "../../../lib/scannerSession";
import type { RuntimeInfo } from "../../../types/global";

type BooleanSetter = Dispatch<SetStateAction<boolean>>;
type NumberSetter = Dispatch<SetStateAction<number>>;
type StringSetter = Dispatch<SetStateAction<string>>;
type NumberOrNullSetter = Dispatch<SetStateAction<number | null>>;
type ScannerRulesSetter = Dispatch<SetStateAction<ScannerLearningRules>>;
type ReviewSamplesSetter = Dispatch<SetStateAction<ReviewSampleRecord[]>>;
type ScanSummarySetter = Dispatch<SetStateAction<ScanSummary | null>>;
type AutoScanStatsSetter = Dispatch<SetStateAction<AutoScanStats>>;

interface ScanViewActionInput {
  autoScanRunning: boolean;
  setAutoScanRunning: BooleanSetter;
  isScanning: boolean;
  stopVisibleScanRef: MutableRefObject<boolean>;
  selectedSourceId: string;
  bridgeReady: boolean;
  automationRepo?: AutomationRepositoryPort;
  runtimeInfo?: RuntimeInfo | null;
  runtimeRepo?: RuntimeRepositoryPort;
  scanLimit: number;
  skipRows: number;
  detectedInventoryCount: number;
  setScanSummary: ScanSummarySetter;
  setAutoScanStats: AutoScanStatsSetter;
  setReviewStatus: StringSetter;
  appendAutomationLog: (line: string) => void;
  appendClickDiagnostics: (result: ClickResult, prefix?: string) => void;
  parseArtifact: (capture: CaptureResult | null) => ParsedArtifactCandidate | null;
  artifactRepo?: ArtifactRepositoryPort;
  reviewSamplesRepo?: ReviewSampleRepositoryPort;
  learningRepo?: LearningRepositoryPort;
  onStoredArtifactsChanged?: (() => Promise<void>) | (() => void);
  setReviewSampleTotal: NumberSetter;
  setReviewSamples: ReviewSamplesSetter;
  setLearningRulesLoaded: BooleanSetter;
  setScannerLearningRules: ScannerRulesSetter;
  setStoredTotal: NumberOrNullSetter;
  scannerLearningRules: ScannerLearningRules;
  captureSelectedSource: (delayMs?: number, focusGenshin?: boolean, options?: CaptureOptions) => Promise<CaptureResult | null>;
  latestCapture: CaptureResult | null;
  parsedArtifact: ParsedArtifactCandidate | null;
  canCaptureSource: boolean;
  setReviewQueueOpen: BooleanSetter;
}

export interface ScanViewActionResult {
  requestScanStop: (reason?: string) => void;
  saveReviewSample: (
    capture?: CaptureResult | null,
    parsed?: ParsedArtifactCandidate | null,
    reason?: string,
  ) => Promise<BooleanResult | null>;
  loadReviewQueue: () => Promise<void>;
  openReviewQueue: () => Promise<void>;
  runAutoReviewScan: () => Promise<void>;
  runVisibleGridScan: () => Promise<void>;
}

export function useScanViewActions(input: ScanViewActionInput): ScanViewActionResult {
  const {
    autoScanRunning,
    setAutoScanRunning,
    isScanning,
    stopVisibleScanRef,
    selectedSourceId,
    bridgeReady,
    automationRepo,
    runtimeInfo,
    runtimeRepo,
    scanLimit,
    skipRows,
    detectedInventoryCount,
    setScanSummary,
    setAutoScanStats,
    setReviewStatus,
    appendAutomationLog,
    appendClickDiagnostics,
    parseArtifact,
    artifactRepo,
    reviewSamplesRepo,
    learningRepo,
    onStoredArtifactsChanged,
    setReviewSampleTotal,
    setReviewSamples,
    setLearningRulesLoaded,
    setScannerLearningRules,
    setStoredTotal,
    scannerLearningRules,
    captureSelectedSource,
    latestCapture,
    parsedArtifact,
    canCaptureSource,
    setReviewQueueOpen,
  } = input;

  const requestScanStop = useCallback((reason = "Stop angefordert.") => {
    stopVisibleScanRef.current = true;
    appendAutomationLog(`stop requested: ${reason}`);
    setReviewStatus(`${reason} Der aktuelle Klick/Capture-Schritt wird noch sauber beendet.`);
  }, [appendAutomationLog, setReviewStatus, stopVisibleScanRef]);

  const reviewContext = useMemo(
    () =>
      createReviewContext({
        artifactRepo,
        reviewSamplesRepo,
        learningRepo,
        onStoredArtifactsChanged,
        setReviewSampleTotal,
        setReviewSamples,
        setLearningRulesLoaded,
        setScannerLearningRules,
        setReviewStatus,
        setStoredTotal,
        appendAutomationLog,
      }),
    [
      artifactRepo,
      reviewSamplesRepo,
      learningRepo,
      onStoredArtifactsChanged,
      setReviewSampleTotal,
      setReviewSamples,
      setLearningRulesLoaded,
      setScannerLearningRules,
      setReviewStatus,
      setStoredTotal,
      appendAutomationLog,
    ],
  );

  useEffect(() => {
    void initializeLearningState(reviewContext);
  }, [reviewContext]);

  const focusDashboard = useCallback(async () => {
    try {
      await automationRepo?.focusMainWindow?.();
    } catch {
      // Best-effort fallback; state remains in renderer.
    }
  }, [automationRepo?.focusMainWindow]);

  const parseArtifactAndPersist = useCallback(
    async function parseArtifactAndPersist(
      capture: CaptureResult | null,
      parsed: ParsedArtifactCandidate,
      source: string,
      needsReview: boolean,
    ) {
      return persistParsedArtifactHelper(capture, parsed, source, needsReview, reviewContext);
    },
    [reviewContext],
  );

  const handleSaveReviewSample = useCallback(
    async function handleSaveReviewSample(
      capture: CaptureResult | null = latestCapture,
      parsed: ParsedArtifactCandidate | null = parsedArtifact,
      reason = "manual",
    ): Promise<BooleanResult | null> {
      const result = await saveReviewSampleHelper(
        capture,
        parsed,
        reason,
        scannerLearningRules,
        reviewContext,
      );
      return result.result ? { ok: result.result.ok } : null;
    },
    [latestCapture, parsedArtifact, reviewContext, scannerLearningRules],
  );

  const scanActionContext = useMemo(
    () =>
      createScanActionContext({
        autoScanRunning,
        setAutoScanRunning,
        isScanning,
        stopVisibleScanRef,
        selectedSourceId,
        bridgeReady,
        automationRepo,
        runtimeInfo,
        runtimeRepo,
        scanLimit,
        skipRows,
        detectedInventoryCount,
        setScanSummary,
        setAutoScanStats,
        setReviewStatus,
        appendAutomationLog,
        appendClickDiagnostics,
        parseArtifact,
        persistParsedArtifact: parseArtifactAndPersist,
        saveReviewSample: handleSaveReviewSample,
        focusDashboard,
        captureSelectedSource,
        captureFastSelectedSource: (delayMs = 0, focusGenshin = false) => captureSelectedSource(delayMs, focusGenshin, { skipOcr: true }),
      }),
    [
      autoScanRunning,
      setAutoScanRunning,
      isScanning,
      stopVisibleScanRef,
      selectedSourceId,
      bridgeReady,
      automationRepo,
      runtimeInfo,
      runtimeRepo,
      scanLimit,
      skipRows,
      detectedInventoryCount,
      setScanSummary,
      setAutoScanStats,
      setReviewStatus,
      appendAutomationLog,
      appendClickDiagnostics,
      parseArtifact,
      parseArtifactAndPersist,
      handleSaveReviewSample,
      focusDashboard,
      captureSelectedSource,
    ],
  );

  const loadReviewQueueAction = useCallback(async () => {
    await loadReviewQueueFromRepo(reviewContext);
  }, [reviewContext]);

  const openReviewQueueModal = useCallback(async () => {
    await loadReviewQueueAction();
    setReviewQueueOpen(true);
  }, [loadReviewQueueAction, setReviewQueueOpen]);

  const runAutoReviewScan = useCallback(async () => {
    if (autoScanRunning || !selectedSourceId || !canCaptureSource) return;
    await runAutoReviewScanAction(scanActionContext);
  }, [autoScanRunning, canCaptureSource, selectedSourceId, scanActionContext]);

  const runVisibleGridScan = useCallback(async () => {
    if (autoScanRunning || !bridgeReady || !selectedSourceId || !automationRepo?.clickScreen || !automationRepo?.scrollScreen) {
      return;
    }
    await runVisibleGridScanAction(scanActionContext);
  }, [
    autoScanRunning,
    bridgeReady,
    selectedSourceId,
    automationRepo?.clickScreen,
    automationRepo?.scrollScreen,
    scanActionContext,
  ]);

  useScanCommandListener({
    automationRepo,
    autoScanRunning,
    isScanning,
    selectedSourceId,
    requestScanStop,
    runVisibleGridScan,
  });

  return {
    requestScanStop,
    saveReviewSample: handleSaveReviewSample,
    loadReviewQueue: loadReviewQueueAction,
    openReviewQueue: openReviewQueueModal,
    runAutoReviewScan,
    runVisibleGridScan,
  };
}
