import { getAssistantBridge } from "../../services/assistantBridge";
import {
  type ArtifactRepositoryPort,
  type AutomationRepositoryPort,
  type CaptureRepositoryPort,
  type RendererRepositories,
  type RuntimeRepositoryPort,
  type ReviewSampleRepositoryPort,
  type LearningRepositoryPort,
  type SnapshotRepositoryPort,
  type OverlayRepositoryPort,
  type ScanExportPort,
} from "./rendererBridgeRepositoryTypes";
import type { AppSnapshot } from "../../types/domain";
import type {
  ArtifactStoreLoadResult,
  ArtifactStoreSaveResult,
  LoadScannerLearningRulesResult,
  BooleanResult,
  CaptureSourceInfo,
  FocusGenshinResult,
  RuntimeInfo,
  SaveResultWithPath,
  ScrollResult,
  AutomationGuard,
  ClickResult,
  ReviewSampleListResult,
  SaveScannerLearningRulesResult,
} from "../../types/global";

const EMPTY_SNAPSHOT: AppSnapshot | null = null;
const EMPTY_CAPTURE_SOURCE_LIST: CaptureSourceInfo[] = [];
const EMPTY_SAVE_RESULT: SaveResultWithPath = { ok: false, path: "" };
const EMPTY_RUNTIME_INFO: RuntimeInfo = {
  ok: false,
  isElevated: false,
  platform: "unknown",
};
const EMPTY_ARTIFACT_STORE_LOAD_RESULT: ArtifactStoreLoadResult = {
  ok: false,
  artifacts: [],
  total: 0,
  path: "",
};
const EMPTY_ARTIFACT_STORE_SAVE_RESULT: ArtifactStoreSaveResult = {
  ok: false,
  added: 0,
  updated: 0,
  total: 0,
  path: "",
};
const EMPTY_REVIEW_SAMPLES_RESULT: ReviewSampleListResult = {
  ok: false,
  samples: [],
  total: 0,
  path: "",
};
const EMPTY_SCANNER_LEARNING_RULES_RESULT: LoadScannerLearningRulesResult = {
  ok: false,
  path: "",
  rules: {},
};
const EMPTY_SCAN_STATUS_RESULT: SaveResultWithPath = { ok: false, path: "" };
const EMPTY_SAVE_RULES_RESULT: SaveScannerLearningRulesResult = {
  ok: false,
  path: "",
  rules: {},
  total: 0,
};

async function createBridgeSafeCall<TResult>(
  callback: () => Promise<TResult> | TResult | null | undefined,
  fallback: TResult,
): Promise<TResult> {
  try {
    const result = await callback();
    return result == null ? fallback : result;
  } catch {
    return fallback;
  }
}

function emptyAutomationGuard(): AutomationGuard {
  return { ok: false, escapePressed: false };
}

function emptyFocusGenshinResult(): FocusGenshinResult {
  return { focused: false, alreadyForeground: false };
}

function emptyClickResult(): ClickResult {
  return {
    ok: false,
    x: 0,
    y: 0,
    clicked: false,
    moved: false,
    focused: false,
    inputBlocked: false,
  };
}

function emptyScrollResult(): ScrollResult {
  return { ok: false, notchesSent: 0, inputBlocked: false };
}

function emptyBooleanResult(): BooleanResult {
  return { ok: false };
}

export function createRendererRepositories(): RendererRepositories | null {
  const bridge = getAssistantBridge();
  if (!bridge) return null;

  const artifactRepo: ArtifactRepositoryPort = {
    loadAll: () =>
      createBridgeSafeCall(
        () => bridge.loadArtifacts(),
        EMPTY_ARTIFACT_STORE_LOAD_RESULT,
      ),
    saveMany: (records) =>
      createBridgeSafeCall(
        () => bridge.saveArtifacts(records),
        EMPTY_ARTIFACT_STORE_SAVE_RESULT,
      ),
  };

  const captureRepo: CaptureRepositoryPort = {
    listSources: () => createBridgeSafeCall(() => bridge.listCaptureSources(), EMPTY_CAPTURE_SOURCE_LIST),
    captureSource: (sourceId, delayMs, focusGenshin, options) =>
      bridge.captureSource(sourceId, delayMs, focusGenshin, options),
  };

  const runtimeRepo: RuntimeRepositoryPort = {
    getRuntimeInfo: () =>
      createBridgeSafeCall(
        () => bridge.getRuntimeInfo(),
        EMPTY_RUNTIME_INFO,
      ),
  };

  const reviewSamplesRepo: ReviewSampleRepositoryPort = {
    loadSamples: (limit = 50) =>
      createBridgeSafeCall(
        () => bridge.loadReviewSamples(limit),
        EMPTY_REVIEW_SAMPLES_RESULT,
      ),
    saveSample: (sample) =>
      createBridgeSafeCall(
        () => bridge.saveReviewSample(sample),
        EMPTY_SCAN_STATUS_RESULT,
      ),
  };

  const learningRepo: LearningRepositoryPort = {
    loadRules: () =>
      createBridgeSafeCall(
        () => bridge.loadScannerLearningRules(),
        EMPTY_SCANNER_LEARNING_RULES_RESULT,
      ),
    saveRules: (rules) =>
      createBridgeSafeCall(
        () => bridge.saveScannerLearningRules(rules),
        EMPTY_SAVE_RULES_RESULT,
      ),
  };

  const snapshotRepo: SnapshotRepositoryPort = {
    load: () => createBridgeSafeCall(() => bridge.loadSnapshot(), EMPTY_SNAPSHOT),
    save: (snapshot) => createBridgeSafeCall(() => bridge.saveSnapshot(snapshot), EMPTY_SAVE_RESULT),
    runMockScan: () => createBridgeSafeCall(() => bridge.runMockScan(), EMPTY_SNAPSHOT),
    publishScannerStatus: (status) =>
      createBridgeSafeCall(() => bridge.publishScannerStatus(status), EMPTY_SCAN_STATUS_RESULT),
  };

  const automationRepo: AutomationRepositoryPort = {
    getAutomationGuard: () =>
      createBridgeSafeCall(
        () => bridge.getAutomationGuard(),
        emptyAutomationGuard(),
      ),
    focusGenshin: () =>
      createBridgeSafeCall(
        () => bridge.focusGenshin(),
        emptyFocusGenshinResult(),
      ),
    focusMainWindow: () => createBridgeSafeCall(() => bridge.focusMainWindow(), emptyBooleanResult()),
    clickScreen: (x, y) => createBridgeSafeCall(() => bridge.clickScreen(x, y), emptyClickResult()),
    scrollScreen: (notches, anchorX, anchorY) =>
      createBridgeSafeCall(() => bridge.scrollScreen(notches, anchorX, anchorY), emptyScrollResult()),
    onCommand: bridge.onScannerCommand,
  };

  const overlayRepo: OverlayRepositoryPort = {
    show: () => createBridgeSafeCall(() => bridge.showOverlay(), emptyBooleanResult()),
  };

  const exportRepo: ScanExportPort = {
    exportGood: (payload) => createBridgeSafeCall(() => bridge.exportGood(payload), EMPTY_SAVE_RESULT),
  };

  return {
    artifacts: artifactRepo,
    capture: captureRepo,
    runtime: runtimeRepo,
    reviewSamples: reviewSamplesRepo,
    learning: learningRepo,
    snapshot: snapshotRepo,
    automation: automationRepo,
    overlay: overlayRepo,
    export: exportRepo,
    canExportGood: bridge.canExportGood,
    canShowOverlay: bridge.canShowOverlay,
    canAutoScan: bridge.canAutoScan,
    canReviewSamples: bridge.canReviewSamples,
    isAvailable: true,
  };
}
