import type {
  Detector,
  DetectorContext,
  DetectorOutcome,
  LaneEligibility,
} from "../../../core/src/sdk/detector.js";
import { isIntentionallyExcepted } from "./contracts.js";
import {
  detectLocaleSweepViolations,
  detectResponsiveSweepViolations,
} from "./detect.js";
import { buildUi001Evidence } from "./evidence.js";
import type {
  SweepsCellEvidence,
  SweepsMatrixEvidence,
  SweepsRuleId,
  SweepsViolationFact,
  Ui001EvidenceRecord,
} from "./types.js";
import { SWEEPS_DETECTOR_VERSION } from "./types.js";

type CellDetectorConfig = {
  id: string;
  className: string;
  ruleId: SweepsRuleId;
  defaultLane: LaneEligibility;
  detect: (evidence: SweepsCellEvidence) => SweepsViolationFact[];
  classificationBasis: (violation: SweepsViolationFact) => string;
};

function browserContext(cellId: string) {
  return { kind: "browser" as const, cell: { id: cellId } };
}

function buildCellOutcome(
  config: CellDetectorConfig,
  evidence: SweepsCellEvidence,
  violation: SweepsViolationFact,
  context: DetectorContext,
): DetectorOutcome<Ui001EvidenceRecord> {
  const ui001 = buildUi001Evidence(
    evidence,
    config.ruleId,
    violation,
    config.classificationBasis(violation),
  );

  void context;
  return {
    detector: { id: config.id, version: SWEEPS_DETECTOR_VERSION },
    class: config.className,
    severity: config.defaultLane === "advisory" ? "medium" : "high",
    target: { kind: "dom", canonical: violation.locator },
    context: browserContext(evidence.cell.id),
    summary: violation.summary,
    evidence: [
      {
        truthSource: config.defaultLane === "advisory" ? "observed" : "universal",
        payload: ui001,
      },
    ],
    artifacts: [],
    laneEligibility: config.defaultLane,
    scope: {
      id: `${config.id}:${evidence.cell.id}:${violation.locator}:${violation.kind}`,
      detectorId: config.id,
      surfaceId: evidence.cell.id,
    },
    violation,
    contextDimensions: {
      route: evidence.cell.routeId,
      role: evidence.cell.role,
      locale: evidence.cell.locale,
      rule: config.ruleId,
    },
  };
}

function evaluateCellDetector(
  config: CellDetectorConfig,
  evidence: SweepsCellEvidence,
  context: DetectorContext,
): DetectorOutcome<Ui001EvidenceRecord>[] {
  if (isIntentionallyExcepted(context, evidence.cell, config.id, config.ruleId)) {
    return [];
  }

  const violations = config.detect(evidence);
  if (violations.length === 0) {
    return [];
  }

  return violations.map((violation) => buildCellOutcome(config, evidence, violation, context));
}

function makeCellDetector(
  config: CellDetectorConfig,
): Detector<SweepsCellEvidence, Ui001EvidenceRecord> {
  return {
    id: config.id,
    version: SWEEPS_DETECTOR_VERSION,
    defaultLane: config.defaultLane,
    evaluate(evidence, context) {
      return Promise.resolve(evaluateCellDetector(config, evidence, context));
    },
  };
}

export const localeSweepDetector = makeCellDetector({
  id: "ui-052-locale-sweep",
  className: "locale-sweep",
  ruleId: "UI-052",
  defaultLane: "blocking",
  detect: detectLocaleSweepViolations,
  classificationBasis: (violation) =>
    `locale sweep check ${violation.kind} failed with measured locale evidence`,
});

export const responsiveSweepDetector = makeCellDetector({
  id: "ui-053-responsive-sweep",
  className: "responsive-sweep",
  ruleId: "UI-053",
  defaultLane: "advisory",
  detect: detectResponsiveSweepViolations,
  classificationBasis: (violation) =>
    `responsive sweep check ${violation.kind} failed with measured viewport evidence`,
});

export const dimensionReachabilityDetector: Detector<SweepsMatrixEvidence, Ui001EvidenceRecord> = {
  id: "ui-054-dimension-reachability",
  version: SWEEPS_DETECTOR_VERSION,
  defaultLane: "advisory",
  evaluate() {
    return Promise.resolve([]);
  },
};

export const sweepsDetectors = [
  localeSweepDetector,
  responsiveSweepDetector,
  dimensionReachabilityDetector,
] as const;

export const sweepsDetectorByRuleId = {
  "UI-052": localeSweepDetector,
  "UI-053": responsiveSweepDetector,
  "UI-054": dimensionReachabilityDetector,
} as const;
