import { LOCALE_MAP } from 'src/constants/locale';
import { type LokaliseTFunction } from 'src/utils/i18n';

import { type CollaboratorLoanPlanResponse } from '../types';

import {
  buildMicroloansStatusViewModel,
  formatMicroloanOverdueMessage,
} from './buildMicroloansStatusViewModel';

const t: LokaliseTFunction = (key, opts) =>
  opts ? `${key}:${JSON.stringify(opts)}` : key;

const locale = LOCALE_MAP.es;

describe('formatMicroloanOverdueMessage', () => {
  it('picks the 1 payment 1 day key', () => {
    expect(formatMicroloanOverdueMessage(t, 1, 1)).toBe('status.overdue_1_1');
  });

  it('picks the n payments n days key', () => {
    expect(formatMicroloanOverdueMessage(t, 2, 5)).toBe(
      'status.overdue_n_n:{"payments":2,"days":5}',
    );
  });
});

describe('buildMicroloansStatusViewModel', () => {
  const basePlan: CollaboratorLoanPlanResponse = {
    id: 'plan-1',
    status: 'ACTIVE',
    installmentsChosen: 12,
    totalAmount: 510_000,
    amountPerCycle: 42_500,
    totalToRepay: 627_610,
    paidInstallments: 0,
  };

  it('sets planStatus ON_TRACK for active on-time plan with no payments', () => {
    const vm = buildMicroloansStatusViewModel(basePlan, [], t, locale);
    expect(vm.planStatus).toBe('ON_TRACK');
    expect(vm.summaryCards).toHaveLength(3);
    expect(vm.summaryCards[0]?.kind).toBe('balance');
    expect(
      vm.summaryCards.find(c => c.kind === 'nextDue')?.gridColumnSpan,
    ).toBe(2);
  });

  it('sets planStatus PENDING_DISBURSEMENT when plan is PENDING', () => {
    const vm = buildMicroloansStatusViewModel(
      { ...basePlan, status: 'PENDING' },
      [],
      t,
      locale,
    );
    expect(vm.planStatus).toBe('PENDING_DISBURSEMENT');
  });

  it('sets planStatus PAUSED when plan is PAUSED', () => {
    const vm = buildMicroloansStatusViewModel(
      { ...basePlan, status: 'PAUSED' },
      [],
      t,
      locale,
    );
    expect(vm.planStatus).toBe('PAUSED');
  });

  it('sets planStatus OVERDUE when overdueInstallmentsCount > 0', () => {
    const vm = buildMicroloansStatusViewModel(
      { ...basePlan, overdueInstallmentsCount: 1 },
      [],
      t,
      locale,
    );
    expect(vm.planStatus).toBe('OVERDUE');
  });

  it('treats SCHEDULED payment as overdue when due date is before today (CDMX calendar)', () => {
    const vm = buildMicroloansStatusViewModel(
      basePlan,
      [
        {
          installmentNumber: 1,
          dueDate: '2020-06-01',
          dueAmount: 42_500,
          status: 'SCHEDULED',
        },
      ],
      t,
      locale,
    );
    expect(vm.scheduleRows).toHaveLength(1);
    expect(vm.scheduleRows[0]?.tone).toBe('error');
    expect(vm.planStatus).toBe('OVERDUE');
  });

  it('skips CANCELLED rows when resolving the next unpaid installment', () => {
    const vm = buildMicroloansStatusViewModel(
      basePlan,
      [
        {
          installmentNumber: 1,
          dueDate: '2030-01-01',
          dueAmount: 42_500,
          status: 'CANCELLED',
        },
        {
          installmentNumber: 2,
          dueDate: '2030-02-01',
          dueAmount: 42_500,
          status: 'SCHEDULED',
        },
      ],
      t,
      locale,
    );
    expect(vm.scheduleRows[0]?.status).toBe('status.cancelled');
    expect(vm.scheduleRows[0]?.tone).toBe('muted');
    expect(vm.scheduleRows[1]?.tone).toBe('brand');
    expect(vm.scheduleRows[1]?.status).toBe('status.next');
  });

  it('exposes disclosureCatPercent and disclosureTnaPercent from plan when present', () => {
    const vm = buildMicroloansStatusViewModel(
      { ...basePlan, cat: 453.7383, tna: 150 },
      [],
      t,
      locale,
    );
    expect(vm.disclosureCatPercent).toBe(453.7383);
    expect(vm.disclosureTnaPercent).toBe(150);
  });

  it('omits disclosure fields when plan has no cat/tna', () => {
    const vm = buildMicroloansStatusViewModel(basePlan, [], t, locale);
    expect(vm.disclosureCatPercent).toBeUndefined();
    expect(vm.disclosureTnaPercent).toBeUndefined();
  });

  it('exposes credit details for modal from totalAmount and totalToRepay', () => {
    const vm = buildMicroloansStatusViewModel(basePlan, [], t, locale);
    expect(vm.creditDetailsPrincipal).toBe(5100);
    expect(vm.creditDetailsTotalToPay).toBe(6276.1);
    expect(vm.creditDetailsTotalInterests).toBe(1176.1);
    expect(vm.creditDetailsInstallmentsCount).toBe(12);
  });

  it('uses plan.cost for credit details interests when present', () => {
    const vm = buildMicroloansStatusViewModel(
      { ...basePlan, cost: 50_000 },
      [],
      t,
      locale,
    );
    expect(vm.creditDetailsTotalInterests).toBe(500);
  });

  it('defaults periodicity to weekly when arg is omitted', () => {
    const vm = buildMicroloansStatusViewModel(basePlan, [], t, locale);
    expect(vm.periodicity).toBe('weekly');
    expect(vm.scheduleTitleSuffix).toBe(
      'status.installments_summary_weekly:{"count":12}',
    );
  });

  it('propagates biweekly periodicity into scheduleTitleSuffix key', () => {
    const vm = buildMicroloansStatusViewModel(
      basePlan,
      [],
      t,
      locale,
      'biweekly',
    );
    expect(vm.periodicity).toBe('biweekly');
    expect(vm.scheduleTitleSuffix).toBe(
      'status.installments_summary_biweekly:{"count":12}',
    );
  });
});
