/**
 * SET 37b — empirical solution strata (seeded from session-13-runs analysis).
 * Optional re-mine via scripts/gen-solution-strata.ts when a run corpus is available.
 * Strategy ORDER per class = descending observed resolution rate.
 */

export type Strategy =
  | 'mechanical'
  | 'oracle-hint-repair'
  | 'draws'
  | 'lessons-repair'
  | 'surgery'
  | 'reset';

export interface SolutionStratumRow {
  /** classKey prefix / family matcher (first segment or full key). */
  classFamily: string;
  /** Share of findings in the seed session (0–1). */
  findingShare: number;
  /** Observed resolution rate by strategy (0–1); missing ⇒ 0. */
  resolutionByStrategy: Partial<Record<Strategy, number>>;
  note?: string;
}

/**
 * Seed: assertion ~40% @ ~50% via draws; throw-mismatch ~25% @ ~60%;
 * mock-API ~15% @ 0% via draws (mechanical only); transpile ~8% @ ~55% via
 * lessons-repair; surgery ~70% when invoked.
 */
export const SOLUTION_STRATA: SolutionStratumRow[] = [
  {
    classFamily: 'assertion',
    findingShare: 0.40,
    resolutionByStrategy: {
      draws: 0.50,
      'oracle-hint-repair': 0.35,
      surgery: 0.70,
      mechanical: 0.05,
      'lessons-repair': 0.25,
      reset: 0.10,
    },
    note: '~40% of findings; ~50% resolve via draws',
  },
  {
    classFamily: 'throw-mismatch',
    findingShare: 0.25,
    resolutionByStrategy: {
      draws: 0.60,
      'oracle-hint-repair': 0.40,
      surgery: 0.70,
      mechanical: 0.02,
      'lessons-repair': 0.20,
      reset: 0.10,
    },
    note: '~25% of findings; ~60% resolve via draws',
  },
  {
    classFamily: 'undefined-symbol|jest',
    findingShare: 0.05,
    resolutionByStrategy: {
      mechanical: 0.95,
      draws: 0,
      'oracle-hint-repair': 0,
      surgery: 0,
      'lessons-repair': 0,
      reset: 0,
    },
    note: 'mock-API mechanical only — 0% via draws',
  },
  {
    classFamily: 'undefined-symbol|fn',
    findingShare: 0.05,
    resolutionByStrategy: {
      mechanical: 0.95,
      draws: 0,
      'oracle-hint-repair': 0,
      surgery: 0,
      'lessons-repair': 0,
      reset: 0,
    },
    note: 'mock-API mechanical only — 0% via draws',
  },
  {
    classFamily: 'is-not-a-function|spyOn',
    findingShare: 0.05,
    resolutionByStrategy: {
      mechanical: 0.95,
      draws: 0,
      'oracle-hint-repair': 0,
      surgery: 0,
      'lessons-repair': 0,
      reset: 0,
    },
    note: 'mock-API mechanical only — 0% via draws',
  },
  {
    classFamily: 'mock-api',
    findingShare: 0.15,
    resolutionByStrategy: {
      mechanical: 0.95,
      draws: 0,
      'oracle-hint-repair': 0,
      surgery: 0,
      'lessons-repair': 0,
      reset: 0,
    },
    note: 'aggregate mock-API family (~15% findings, 0% draws)',
  },
  {
    classFamily: 'transpile',
    findingShare: 0.08,
    resolutionByStrategy: {
      'lessons-repair': 0.55,
      mechanical: 0.40,
      surgery: 0.70,
      'oracle-hint-repair': 0.25,
      draws: 0.15,
      reset: 0.10,
    },
    note: '~8% of findings; ~55% via lessons-repair',
  },
  {
    classFamily: 'undefined-symbol',
    findingShare: 0.10,
    resolutionByStrategy: {
      mechanical: 0.70,
      'oracle-hint-repair': 0.40,
      draws: 0.30,
      'lessons-repair': 0.25,
      surgery: 0.70,
      reset: 0.10,
    },
  },
  {
    classFamily: 'is-not-a-function',
    findingShare: 0.05,
    resolutionByStrategy: {
      mechanical: 0.20,
      'oracle-hint-repair': 0.45,
      draws: 0.40,
      surgery: 0.70,
      'lessons-repair': 0.20,
      reset: 0.10,
    },
  },
  {
    classFamily: 'regex-literal',
    findingShare: 0.03,
    resolutionByStrategy: {
      mechanical: 0.80,
      surgery: 0.70,
      'lessons-repair': 0.30,
      draws: 0.10,
      'oracle-hint-repair': 0.20,
      reset: 0.05,
    },
  },
  {
    classFamily: 'empty-draw',
    findingShare: 0.04,
    resolutionByStrategy: {
      mechanical: 0.60,
      reset: 0.20,
      draws: 0,
      surgery: 0.40,
      'oracle-hint-repair': 0,
      'lessons-repair': 0.10,
    },
    note: 'empty draws skip model attempts; clade/template first',
  },
  {
    classFamily: 'runtime',
    findingShare: 0.08,
    resolutionByStrategy: {
      'oracle-hint-repair': 0.40,
      draws: 0.35,
      surgery: 0.70,
      mechanical: 0.10,
      'lessons-repair': 0.25,
      reset: 0.15,
    },
  },
  {
    classFamily: 'crash',
    findingShare: 0.05,
    resolutionByStrategy: {
      mechanical: 0.50,
      surgery: 0.70,
      'lessons-repair': 0.30,
      draws: 0.15,
      'oracle-hint-repair': 0.20,
      reset: 0.10,
    },
  },
  {
    classFamily: 'catalog-drift',
    findingShare: 0,
    resolutionByStrategy: {
      surgery: 0.70,
      reset: 0.30,
      draws: 0.10,
      mechanical: 0,
      'oracle-hint-repair': 0.05,
      'lessons-repair': 0.05,
    },
    note: 'tripwire residual — escalate only after catalog miss',
  },
];

const DEFAULT_ORDER: Strategy[] = [
  'mechanical',
  'oracle-hint-repair',
  'lessons-repair',
  'draws',
  'surgery',
  'reset',
];

function rowForClass(classKey: string): SolutionStratumRow | undefined {
  if (!classKey) return undefined;
  // Exact family match first (mock-API keys), then prefix.
  const exact = SOLUTION_STRATA.find(r => r.classFamily === classKey);
  if (exact) return exact;
  const prefix = classKey.split('|')[0]!;
  const byPrefix = SOLUTION_STRATA.find(r => r.classFamily === prefix);
  if (byPrefix) return byPrefix;
  // mock-API aggregate when classKey is a known mock surface.
  if (
    classKey === 'undefined-symbol|jest'
    || classKey === 'undefined-symbol|fn'
    || classKey === 'is-not-a-function|spyOn'
  ) {
    return SOLUTION_STRATA.find(r => r.classFamily === 'mock-api');
  }
  return undefined;
}

/**
 * Strategy order for a classKey — descending by observed resolution rate.
 * Unknown classes get the default substrate-first order.
 */
export function strategyOrderForClass(classKey: string): Strategy[] {
  const row = rowForClass(classKey);
  if (!row) return [...DEFAULT_ORDER];
  const rates = row.resolutionByStrategy;
  return [...DEFAULT_ORDER].sort((a, b) => (rates[b] ?? 0) - (rates[a] ?? 0));
}
