export type ReconciliationBreakType =
  | 'amount_mismatch'
  | 'missing_event'
  | 'duplicate_event'
  | 'status_mismatch'
  | 'ledger_drift'
  | 'chain_drift';

export type ReconciliationBreak = {
  breakId: string;
  type: ReconciliationBreakType;
  source: 'hybx' | 'fineract' | 'chain' | 'internal';
  referenceId: string;
  expected?: string;
  actual?: string;
  detectedAt: string;
};

export type ReconciliationSnapshot = {
  snapshotId: string;
  tenantId: string;
  entityId: string;
  asOf: string;
  hybxEventCount: number;
  fineractPostingCount: number;
  chainSettlementCount: number;
  breaks: ReconciliationBreak[];
  status: 'matched' | 'breaks_found' | 'pending';
};

export interface ReconciliationEngine {
  reconcileTripleState(input: {
    tenantId: string;
    entityId: string;
    hybxRefs: string[];
    fineractRefs: string[];
    chainRefs: string[];
  }): Promise<ReconciliationSnapshot>;
}

export class MockReconciliationEngine implements ReconciliationEngine {
  async reconcileTripleState(input: {
    tenantId: string;
    entityId: string;
    hybxRefs: string[];
    fineractRefs: string[];
    chainRefs: string[];
  }): Promise<ReconciliationSnapshot> {
    const breaks: ReconciliationBreak[] = [];
    const hybxSet = new Set(input.hybxRefs);
    const fineractSet = new Set(input.fineractRefs);
    const chainSet = new Set(input.chainRefs);

    for (const ref of input.hybxRefs) {
      if (!fineractSet.has(ref)) {
        breaks.push({
          breakId: `brk-fineract-${ref}`,
          type: 'missing_event',
          source: 'fineract',
          referenceId: ref,
          detectedAt: new Date().toISOString(),
        });
      }
      if (!chainSet.has(ref)) {
        breaks.push({
          breakId: `brk-chain-${ref}`,
          type: 'missing_event',
          source: 'chain',
          referenceId: ref,
          detectedAt: new Date().toISOString(),
        });
      }
    }

    for (const ref of input.fineractRefs) {
      if (!hybxSet.has(ref)) {
        breaks.push({
          breakId: `brk-hybx-${ref}`,
          type: 'missing_event',
          source: 'hybx',
          referenceId: ref,
          detectedAt: new Date().toISOString(),
        });
      }
    }

    return {
      snapshotId: `recon-${Date.now()}`,
      tenantId: input.tenantId,
      entityId: input.entityId,
      asOf: new Date().toISOString(),
      hybxEventCount: input.hybxRefs.length,
      fineractPostingCount: input.fineractRefs.length,
      chainSettlementCount: input.chainRefs.length,
      breaks,
      status: breaks.length === 0 ? 'matched' : 'breaks_found',
    };
  }
}
