/**
 * E2E：钱包 + 下注 + 注单查看
 *
 * 链路：
 *  1. 玩家登录 → 拿钱包余额
 *  2. 取当前 draw_no（公开 draw.current）
 *  3. POST /ticket/preview（不落库，只算钱）
 *  4. POST /ticket/place（落库 + 扣 frozen）
 *  5. GET /ticket/items/{ticket_no} 验真
 *  6. 钱包余额减少（frozen 增加）
 *  7. 同 client_trace_id 第二次 place → 幂等回放
 *
 * 不做结算（结算链路走 settlement service + command，e2e 单独测）。
 */

import { test, expect, request as pwRequest } from '@playwright/test';
import { playerLoginViaBypass, resetE2EPlayer, fetchOpenDrawNo } from './_helper';

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

test.beforeEach(async () => {
  await resetE2EPlayer();
});

test('玩家登录 → /wallet/balance 返回币种 + 余额', async () => {
  const session = await playerLoginViaBypass();
  const ctx = await pwRequest.newContext({
    extraHTTPHeaders: { Authorization: `Bearer ${session.access_token}` },
  });
  const r = await ctx.get('/api/v1/wallet/balance');
  expect(r.ok(), `balance status=${r.status()}`).toBeTruthy();
  const body = (await r.json()) as any;
  expect(body.data.currency_code).toBe(CURRENCY);
  expect(typeof body.data.balance).toBe('number');
  expect(typeof body.data.available_balance).toBe('number');
  expect(body.data.credit_line_mode).toBe(false);
  await ctx.dispose();
});

test('preview → place → 拿 ticket_no + 余额变动', async () => {
  const drawNo = await fetchOpenDrawNo();

  const session = await playerLoginViaBypass();
  const ctx = await pwRequest.newContext({
    extraHTTPHeaders: { Authorization: `Bearer ${session.access_token}` },
  });

  const bal0 = (await (await ctx.get('/api/v1/wallet/balance')).json()) as any;
  const before = Number(bal0.data.balance);

  const preview = await ctx.post('/api/v1/ticket/preview', {
    data: {
      draw_id: drawNo,
      currency_code: CURRENCY,
      client_trace_id: `e2e-preview-${Date.now()}`,
      lines: [{ number: '1234', play_code: 'straight', amount: BET_AMOUNT_MINOR }],
    },
  });
  expect(preview.ok(), `preview status=${preview.status()}`).toBeTruthy();
  const previewBody = (await preview.json()) as any;
  expect(previewBody.code).toBe(0);

  const place = await ctx.post('/api/v1/ticket/place', {
    data: {
      draw_id: drawNo,
      currency_code: CURRENCY,
      client_trace_id: `e2e-place-${Date.now()}`,
      lines: [{ number: '1234', play_code: 'straight', amount: BET_AMOUNT_MINOR }],
    },
  });
  expect(place.ok(), `place status=${place.status()}`).toBeTruthy();
  const placeBody = (await place.json()) as any;
  expect(placeBody.code).toBe(0);
  const ticketNo = placeBody.data.items?.[0]?.ticket_no ?? placeBody.data.ticket_no;
  expect(ticketNo).toMatch(/^TK[0-9]+$/);

  const show = await ctx.get(`/api/v1/ticket/items/${ticketNo}`);
  expect(show.ok(), `items show status=${show.status()}`).toBeTruthy();
  const showBody = (await show.json()) as any;
  expect(showBody.data.ticket_no).toBe(ticketNo);

  const bal1 = (await (await ctx.get('/api/v1/wallet/balance')).json()) as any;
  const afterAvailable = Number(bal1.data.available_balance);
  expect(afterAvailable).toBeLessThan(before);

  await ctx.dispose();
});

test('同 client_trace_id 第二次 place → 幂等回放，不重复扣款', async () => {
  const drawNo = await fetchOpenDrawNo();

  const session = await playerLoginViaBypass();
  const ctx = await pwRequest.newContext({
    extraHTTPHeaders: { Authorization: `Bearer ${session.access_token}` },
  });

  const trace = `e2e-idem-${Date.now()}`;
  const payload = {
    draw_id: drawNo,
    currency_code: CURRENCY,
    client_trace_id: trace,
    lines: [{ number: '5678', play_code: 'straight', amount: 500 }],
  };

  const r1 = await ctx.post('/api/v1/ticket/place', { data: payload });
  expect(r1.ok(), `place1 status=${r1.status()}`).toBeTruthy();
  const body1 = (await r1.json()) as any;
  const ticket1 = body1.data.items?.[0]?.ticket_no ?? body1.data.ticket_no;

  const r2 = await ctx.post('/api/v1/ticket/place', { data: payload });
  expect(r2.ok(), `place2 status=${r2.status()}`).toBeTruthy();
  const body2 = (await r2.json()) as any;
  const ticket2 = body2.data.items?.[0]?.ticket_no ?? body2.data.ticket_no;

  expect(ticket1).toBe(ticket2);
  await ctx.dispose();
});
