import { useCallback, useEffect, useState, type ChangeEvent, type FocusEvent, type KeyboardEvent, type MouseEvent } from "react";
import type { CaptureResult, RuntimeInfo } from "../../../../../types/global";
import { clampScanLimit, clampSkipRows } from "../../../../../lib/scannerSession";

export interface StepperControlModel {
  label: string;
  value: string;
  helper: string;
  min: number;
  max: number;
  presets: number[];
  onChange: (event: ChangeEvent<HTMLInputElement>) => void;
  onBlur: (event: FocusEvent<HTMLInputElement>) => void;
  onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;
  decrement: () => void;
  increment: () => void;
  applyPreset: (value: number) => void;
}

export interface ScanSettingsModalModel {
  closeSettings: () => void;
  stopPropagation: (event: MouseEvent<HTMLDivElement>) => void;
  scanLimitControl: StepperControlModel;
  skipRowsControl: StepperControlModel;
  inventoryCountText: string;
  inventoryClassName: string;
  scanLimitClassName: string;
  skipRowsClassName: string;
  activeTargetText: string;
  scanSummaryText: string;
}

export function useScanSettingsModalModel({
  setSettingsOpen,
  setScanLimit,
  setScanLimitTouched,
  setSkipRows,
  latestCapture,
  scanLimit,
  skipRows,
  activeTargetCount,
  runtimeInfo,
}: {
  latestCapture: CaptureResult | null;
  scanLimit: number;
  skipRows: number;
  activeTargetCount: number;
  runtimeInfo: RuntimeInfo | null;
  setSettingsOpen: (open: boolean) => void;
  setScanLimit: (value: number) => void;
  setScanLimitTouched: (touched: boolean) => void;
  setSkipRows: (rows: number) => void;
}): ScanSettingsModalModel {
  const [scanLimitText, setScanLimitText] = useState(String(scanLimit));
  const [skipRowsText, setSkipRowsText] = useState(String(skipRows));

  useEffect(() => {
    setScanLimitText(String(scanLimit));
  }, [scanLimit]);

  useEffect(() => {
    setSkipRowsText(String(skipRows));
  }, [skipRows]);

  const closeSettings = useCallback(() => setSettingsOpen(false), [setSettingsOpen]);
  const stopPropagation = useCallback((event: MouseEvent<HTMLDivElement>) => {
    event.stopPropagation();
  }, []);

  const applyScanLimit = useCallback((value: number) => {
    const next = clampScanLimit(value);
    setScanLimitTouched(true);
    setScanLimit(next);
    setScanLimitText(String(next));
  }, [setScanLimit, setScanLimitTouched]);

  const applySkipRows = useCallback((value: number) => {
    const next = clampSkipRows(value);
    setSkipRows(next);
    setSkipRowsText(String(next));
  }, [setSkipRows]);

  const handleScanLimitChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
    setScanLimitText(event.target.value.replace(/\D/g, "").slice(0, 4));
  }, []);

  const handleSkipRowsChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
    setSkipRowsText(event.target.value.replace(/\D/g, "").slice(0, 2));
  }, []);

  const commitScanLimit = useCallback((rawValue: string) => {
    applyScanLimit(rawValue.trim() === "" ? scanLimit : Number(rawValue));
  }, [applyScanLimit, scanLimit]);

  const commitSkipRows = useCallback((rawValue: string) => {
    applySkipRows(rawValue.trim() === "" ? skipRows : Number(rawValue));
  }, [applySkipRows, skipRows]);

  const handleScanLimitBlur = useCallback((event: FocusEvent<HTMLInputElement>) => {
    commitScanLimit(event.target.value);
  }, [commitScanLimit]);

  const handleSkipRowsBlur = useCallback((event: FocusEvent<HTMLInputElement>) => {
    commitSkipRows(event.target.value);
  }, [commitSkipRows]);

  const handleScanLimitKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) => {
    if (event.key !== "Enter") return;
    commitScanLimit(event.currentTarget.value);
    event.currentTarget.blur();
  }, [commitScanLimit]);

  const handleSkipRowsKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) => {
    if (event.key !== "Enter") return;
    commitSkipRows(event.currentTarget.value);
    event.currentTarget.blur();
  }, [commitSkipRows]);

  const detectedInventoryCount = latestCapture?.inventoryCount?.current;
  const detectedInventoryTotal = latestCapture?.inventoryCount?.total;
  const inventoryClassName = detectedInventoryCount ? "ok" : "neutral";
  const inventoryCountText = detectedInventoryCount
    ? `${detectedInventoryCount}/${detectedInventoryTotal || "?"}`
    : "Noch nicht erkannt";
  const scanLimitClassName = scanLimit !== detectedInventoryCount ? "ok" : "standard";
  const skipRowsClassName = skipRows > 0 ? "ok" : "standard";
  const focusModeText = runtimeInfo?.isElevated ? "Admin" : "Standard";
  const activeTargetText = `${activeTargetCount} Ziele · ${focusModeText}`;
  const scanSummaryText = "Auto-Scan zaehlt Positionen, verifizierte Ansichten und gespeicherte Artifacts getrennt.";

  return {
    closeSettings,
    stopPropagation,
    scanLimitControl: {
      label: "Scan-Ziel",
      value: scanLimitText,
      helper: "Wie viele sichtbare Positionen verarbeitet werden.",
      min: 1,
      max: 1800,
      presets: [16, 20, 50, 100],
      onChange: handleScanLimitChange,
      onBlur: handleScanLimitBlur,
      onKeyDown: handleScanLimitKeyDown,
      decrement: () => applyScanLimit(scanLimit - 1),
      increment: () => applyScanLimit(scanLimit + 1),
      applyPreset: applyScanLimit,
    },
    skipRowsControl: {
      label: "Startzeilen ueberspringen",
      value: skipRowsText,
      helper: "Nur nutzen, wenn du mitten in der Liste beginnst.",
      min: 0,
      max: 8,
      presets: [0, 1, 2, 3],
      onChange: handleSkipRowsChange,
      onBlur: handleSkipRowsBlur,
      onKeyDown: handleSkipRowsKeyDown,
      decrement: () => applySkipRows(skipRows - 1),
      increment: () => applySkipRows(skipRows + 1),
      applyPreset: applySkipRows,
    },
    inventoryCountText,
    inventoryClassName,
    scanLimitClassName,
    skipRowsClassName,
    activeTargetText,
    scanSummaryText,
  };
}
