import type {
  HapoalimAccountData,
  HapoalimForeignTransactionsBusiness,
  HapoalimForeignTransactionsPersonal,
  HapoalimILSTransactions,
  IsracardCardsTransactionsList,
  SwiftTransactions,
} from '@accounter/modern-poalim-scraper';
import type { CalPayload } from './payload-schemas/cal.schema.js';
import type { DiscountPayload } from './payload-schemas/discount.schema.js';
import type { MaxPayload } from './payload-schemas/max.schema.js';
import type { OtsarHahayalCreditCardData } from './scrapers/otsar-hahayal.js';
import type { AccountRecord } from './vault.js';

export type SourceType =
  | 'poalim'
  | 'discount'
  | 'isracard'
  | 'amex'
  | 'cal'
  | 'max'
  | 'otsar-hahayal'
  | 'otsar-hahayal-credit-card';

export type OtsarHahayalAccountsPayload = { account: string; branch: string }[];
export type OtsarHahayalCreditCardsPayload = Pick<OtsarHahayalCreditCardData, 'card'>[];

export type ValidatedPayload =
  | HapoalimAccountData[number]
  | HapoalimILSTransactions
  | HapoalimForeignTransactionsPersonal
  | HapoalimForeignTransactionsBusiness
  | SwiftTransactions
  | DiscountPayload
  | IsracardCardsTransactionsList
  | CalPayload
  | MaxPayload
  | OtsarHahayalAccountsPayload
  | OtsarHahayalCreditCardsPayload;

export type { AccountRecord } from './vault.js';

export type AccountCheckResult = { accepted: string[]; ignored: string[]; unknown: string[] };

export function extractAccountIdentifiers(type: SourceType, payload: ValidatedPayload): string[] {
  switch (type) {
    case 'poalim': {
      const p = payload as HapoalimAccountData[number];
      if (!('accountNumber' in p) || !('branchNumber' in p)) {
        return [];
      }
      return [`${p.branchNumber}-${p.accountNumber}`];
    }
    case 'discount': {
      const p = payload as DiscountPayload;
      return [...new Set(p.map(entry => entry.accountNumber))];
    }
    case 'isracard':
    case 'amex': {
      const p = payload as IsracardCardsTransactionsList;
      return p.CardsTransactionsListBean.cardNumberList
        .map(c => c.match(/\d{4}/)?.[0])
        .filter((c): c is string => c !== undefined);
    }
    case 'cal': {
      const p = payload as CalPayload;
      return [...new Set(p.map(entry => entry.card))];
    }
    case 'max': {
      const p = payload as MaxPayload;
      return [...new Set(p.map(account => account.accountNumber))];
    }
    case 'otsar-hahayal': {
      const p = payload as OtsarHahayalAccountsPayload;
      return [...new Set(p.map(a => `${a.branch}-${a.account}`))];
    }
    case 'otsar-hahayal-credit-card': {
      const p = payload as OtsarHahayalCreditCardsPayload;
      return [...new Set(p.map(({ card }) => card.maskedPan))];
    }
  }
}

export function checkAccounts(
  type: SourceType,
  payload: ValidatedPayload,
  known: AccountRecord[],
): AccountCheckResult {
  const identifiers = extractAccountIdentifiers(type, payload);
  const accepted: string[] = [];
  const ignored: string[] = [];
  const unknown: string[] = [];

  for (const id of identifiers) {
    const record = known.find(a => a.sourceType === type && a.accountNumber === id);
    if (!record) {
      unknown.push(id);
    } else if (record.status === 'ignored') {
      ignored.push(id);
    } else if (record.status === 'accepted') {
      accepted.push(id);
    } else {
      // 'pending' and any future unrecognized status blocks the run
      unknown.push(id);
    }
  }

  return { accepted, ignored, unknown };
}
