/**
 * E2E：部分收付后坏账核销 → settlement_confirm 累计释额至账单全额。
 */

import { test, expect } from '@playwright/test';
import {
  adminLoginViaBypass,
  adminCtxOf,
  adminLoginWithAccount,
  fetchBillCreditLedgerRows,
  fetchOpenDrawNo,
  openSettlementPeriod,
  playerLoginViaBypass,
  setupCreditPlayer,
  setupSiteOperator,
} from './_helper';
import { runWalletDrawSettlement } from './helpers/draw-settlement';

const DEFAULT_PASS = process.env.E2E_PLAYER_PASSWORD ?? '12345678';

test('部分收付后坏账核销 → credit_ledger 累计至全额', async () => {
  test.setTimeout(360_000);

  const credit = await setupCreditPlayer({
    credit_limit: 100_000,
    username: `e2e_bd_partial_${Date.now()}`,
  });
  const finance = await setupSiteOperator({
    username: `e2e_fin_bd_${Date.now()}`,
    password: DEFAULT_PASS,
    role_slug: 'site_finance',
  });
  const drawNo = await fetchOpenDrawNo();

  const superSession = await adminLoginViaBypass();
  const superAdmin = await adminCtxOf(superSession.accessToken);
  const periodId = await openSettlementPeriod(superAdmin, credit.admin_site_id);

  const playerSession = await playerLoginViaBypass({
    site_code: credit.site_code,
    username: credit.username,
    password: credit.password,
  });

  await runWalletDrawSettlement({
    adminToken: superSession.accessToken,
    playerToken: playerSession.access_token,
    drawNo,
    betNumber: '4321',
    publishWinNumber: '9999',
    betAmount: 10_000,
    expectWalletIncrease: false,
  });

  const close = await superAdmin.post(`/api/v1/admin/settlement-periods/${periodId}/close`);
  expect(close.ok()).toBeTruthy();

  const bills = await superAdmin.get(
    `/api/v1/admin/settlement-bills?settlement_period_id=${periodId}&size=20`,
  );
  const billsBody = (await bills.json()) as any;
  const playerBill = billsBody.data.items.find(
    (b: any) => b.bill_type === 'player' && Number(b.owner_id) === credit.player_id,
  );
  expect(playerBill).toBeTruthy();
  expect(Number(playerBill.net_amount)).toBeGreaterThan(0);

  const billId = Number(playerBill.id);
  await superAdmin.post(`/api/v1/admin/settlement-bills/${billId}/confirm`);

  const billDetail = (await (await superAdmin.get(`/api/v1/admin/settlement-bills/${billId}`)).json()) as any;
  const unpaid = Math.abs(Number(billDetail.data.bill.unpaid_amount));
  const firstPay = Math.floor(unpaid / 2);
  expect(firstPay).toBeGreaterThan(0);

  const financeSession = await adminLoginWithAccount(finance.username, finance.password);
  const financeAdmin = await adminCtxOf(financeSession.accessToken);

  const pay1 = await financeAdmin.post(`/api/v1/admin/settlement-bills/${billId}/payments`, {
    data: { amount: firstPay, method: 'e2e_bd_partial', remark: 'partial before write-off' },
  });
  expect(pay1.ok()).toBeTruthy();
  expect((await pay1.json()).data.bill.status).toBe('partial_paid');

  const ledgerAfterPay1 = await fetchBillCreditLedgerRows(credit.player_id, billId, 'settlement_confirm');
  expect(ledgerAfterPay1).toHaveLength(1);
  expect(Number(ledgerAfterPay1[0].amount)).toBe(firstPay);

  const writeOff = await financeAdmin.post(`/api/v1/admin/settlement-bills/${billId}/bad-debt-write-off`, {
    data: { reason: 'e2e partial then bad debt' },
  });
  expect(writeOff.ok(), `bad debt status=${writeOff.status()}`).toBeTruthy();
  expect((await writeOff.json()).code).toBe(0);

  const settledBill = (await (await superAdmin.get(`/api/v1/admin/settlement-bills/${billId}`)).json()) as any;
  expect(settledBill.data.bill.status).toBe('settled');
  expect(Number(settledBill.data.bill.unpaid_amount)).toBe(0);

  const ledgerAfterWriteOff = await fetchBillCreditLedgerRows(credit.player_id, billId, 'settlement_confirm');
  expect(ledgerAfterWriteOff).toHaveLength(1);
  expect(Number(ledgerAfterWriteOff[0].amount)).toBe(unpaid);

  await financeAdmin.dispose();
  await superAdmin.dispose();
});
