/**
 * 开奖 → 结算 → 派彩 确定性流水线（poll + tick，避免 test.skip）。
 */

import { expect, type APIRequestContext } from '@playwright/test';
import {
  buildAllResultItems,
  finishDrawCooldown,
  forceCloseDraw,
  resolveDrawId,
  tickDraws,
  waitForDrawStatus,
} from '../_helper';

const CURRENCY = (process.env.LOTTERY_DEFAULT_CURRENCY ?? 'NPR').toUpperCase();

export interface DrawSettlementResult {
  drawNo: string;
  drawId: number;
  batchId: number;
  balanceBefore?: number;
  balanceAfter?: number;
}

export async function runWalletDrawSettlement(params: {
  adminToken: string;
  playerToken: string;
  drawNo: string;
  betNumber?: string;
  /** 公布头奖号码；默认与 betNumber 相同（必中）。传不同值可测玩家输单。 */
  publishWinNumber?: string;
  betAmount?: number;
  balanceBefore?: number;
  expectWalletIncrease?: boolean;
}): Promise<DrawSettlementResult> {
  const drawNo = params.drawNo;
  const betNumber = params.betNumber ?? '1234';
  const publishWinNumber = params.publishWinNumber ?? betNumber;
  const betAmount = params.betAmount ?? 10_000;

  const player = await pwPlayerCtx(params.playerToken);
  let balanceBefore: number | undefined;
  if (params.expectWalletIncrease !== false) {
    balanceBefore =
      params.balanceBefore ??
      Number((await (await player.get('/api/v1/wallet/balance')).json()).data.balance);
  }

  const place = await player.post('/api/v1/ticket/place', {
    data: {
      draw_id: drawNo,
      currency_code: CURRENCY,
      client_trace_id: `e2e-settle-${Date.now()}`,
      lines: [{ number: betNumber, play_code: 'straight', amount: betAmount }],
    },
  });
  expect(place.ok(), `place status=${place.status()}`).toBeTruthy();
  const placeBody = (await place.json()) as any;
  expect(placeBody.code).toBe(0);
  await player.dispose();

  await forceCloseDraw(drawNo);
  await waitForDrawStatus(drawNo, ['closed', 'review', 'cooldown', 'settling', 'settled'], 15);

  const admin = await pwAdminCtx(params.adminToken);
  const drawId = await resolveDrawId(admin, drawNo);

  const store = await admin.post(`/api/v1/admin/draws/${drawId}/result-batches`, {
    data: { items: buildAllResultItems(publishWinNumber) },
  });
  expect(store.ok(), `store batch status=${store.status()}`).toBeTruthy();
  const storeBody = (await store.json()) as any;
  expect(storeBody.code).toBe(0);
  const batchId: number = storeBody.data.batch.id;

  const pub = await admin.post(`/api/v1/admin/draws/${drawId}/result-batches/${batchId}/publish`);
  expect(pub.ok(), `publish status=${pub.status()}`).toBeTruthy();
  const pubBody = (await pub.json()) as any;
  expect(pubBody.code).toBe(0);

  await finishDrawCooldown(drawNo);
  await waitForDrawStatus(drawNo, ['settling', 'settled'], 25);

  const insp = await waitForDrawStatus(drawNo, ['settled'], 25);
  if (String(insp.data?.status ?? insp.status) !== 'settled') {
    const settle = await admin.post(`/api/v1/admin/draws/${drawId}/settlement/run`);
    const settleBody = (await settle.json()) as any;
    if (settleBody.code !== 0) {
      await tickDraws();
    }
    await waitForDrawStatus(drawNo, ['settled'], 25);
  }

  const list = await admin.get(`/api/v1/admin/settlement-batches?size=20`);
  const lb = (await list.json()) as any;
  const ourBatch = lb.data.items.find((b: any) => b.draw_id === drawId);
  if (ourBatch && ourBatch.status === 'pending_review') {
    await admin.post(`/api/v1/admin/settlement-batches/${ourBatch.id}/approve`, {
      data: { remark: 'e2e approve' },
    });
    await admin.post(`/api/v1/admin/settlement-batches/${ourBatch.id}/payout`);
  } else {
    await tickDraws();
    await waitForDrawStatus(drawNo, ['settled'], 15);
  }

  await admin.dispose();

  let balanceAfter: number | undefined;
  if (params.expectWalletIncrease !== false) {
    const player2 = await pwPlayerCtx(params.playerToken);
    const bal1 = (await (await player2.get('/api/v1/wallet/balance')).json()) as any;
    balanceAfter = Number(bal1.data.balance);
    await player2.dispose();
  }

  return { drawNo, drawId, batchId, balanceBefore, balanceAfter };
}

async function pwAdminCtx(token: string): Promise<APIRequestContext> {
  const { request: pwRequest } = await import('@playwright/test');
  return pwRequest.newContext({
    extraHTTPHeaders: { Authorization: `Bearer ${token}` },
  });
}

async function pwPlayerCtx(token: string): Promise<APIRequestContext> {
  const { request: pwRequest } = await import('@playwright/test');
  return pwRequest.newContext({
    extraHTTPHeaders: { Authorization: `Bearer ${token}` },
  });
}
