import { test, expect, Page } from '@playwright/test';

// 直接调 API 验证后端逻辑
const BASE = process.env.BASE_URL || 'http://192.168.3.151:5173';
const EMAIL = 'echo@shboka.com';
const PASSWORD = '123456';
const STORE_ID = '01KSSFPT0ZXXHE6PRVXY9RE1K2';
const ADA_ID = '01KXD532QWXQTM57HT5BTEJWGS';
const SVC_PURE = '01KT3VBKHP7V3D6JFX9F916ZF8'; // 纯色美甲 88
const SVC_SHELL = '01KT3VBKHPK4SQ2EE59DNQYVDG'; // 韩式贝壳片 228
const EMPLOYEE_ID = '01KT5RH5Z9ZT6T5VAP8XM15FFX'; // 周小雨
const SV_PLAN_100 = '01KTGSV000000000000000001'; // 入门储值100
const SV_PLAN_200 = '01KTGSV000000000000000002'; // 储值200送10
const VC_PURE_5 = '01KTGVC000000000000000001'; // 纯色美甲5次卡

let token: string;
let sessionId: string;

test.beforeAll(async ({ request }) => {
  // 登录
  const loginRes = await request.post(`${BASE}/nail/auth/login`, {
    data: { email: EMAIL, password: PASSWORD },
    headers: { 'Product': 'inail' },
  });
  expect(loginRes.status()).toBe(200);
  const loginData = await loginRes.json();
  token = loginData.access_token;

  // 选门店
  const storeRes = await request.post(`${BASE}/nail/auth/select-store`, {
    data: { org_id: STORE_ID },
    headers: { 'Product': 'inail', 'Authorization': `Bearer ${token}` },
  });
  expect(storeRes.status()).toBe(200);

  // 获取当前 POS session
  const sessionRes = await request.get(`${BASE}/nail/pos/sessions/current`, {
    headers: { 'Product': 'inail', 'Authorization': `Bearer ${token}` },
  });
  if (sessionRes.status() === 200) {
    const sessionData = await sessionRes.json();
    sessionId = sessionData.id;
  } else {
    // 开班
    const openRes = await request.post(`${BASE}/nail/pos/sessions`, {
      data: { opening_balance_cents: 0 },
      headers: { 'Product': 'inail', 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
    });
    const openData = await openRes.json();
    sessionId = openData.id;
  }
});

function headers() {
  return { 'Product': 'inail', 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' };
}

function today() {
  return new Date().toISOString().split('T')[0];
}

// ═══════════════════════════════════════════
// 购买权益
// ═══════════════════════════════════════════
test.describe('购买权益', () => {

  test('购买储值方案 - 入门储值100（现金）', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId,
        client_id: ADA_ID,
        items: [],
        goods_items: [{ goods_type: 'stored_value', goods_id: SV_PLAN_100, price_cents: 10000, name: '入门储值100', validity: { type: 'no_limit' } }],
        tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 10000 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.status).toBe('completed');
    expect(data.total_cents).toBe(10000);
  });

  test('购买储值方案 - 储值200送10（现金）', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId,
        client_id: ADA_ID,
        items: [],
        goods_items: [{ goods_type: 'stored_value', goods_id: SV_PLAN_200, price_cents: 20000, name: '储值200送10', validity: { type: 'no_limit' } }],
        tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 20000 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.status).toBe('completed');
  });

  test('购买次卡 - 纯色美甲5次卡（现金）', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId,
        client_id: ADA_ID,
        items: [],
        goods_items: [{ goods_type: 'visit_card', goods_id: VC_PURE_5, price_cents: 35800, name: '纯色美甲5次卡', validity: { type: 'purchase_day', unit: 'day', value: 365 } }],
        tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 35800 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.status).toBe('completed');
  });
});

// ═══════════════════════════════════════════
// 储值卡核销
// ═══════════════════════════════════════════
test.describe('储值卡核销', () => {

  test('储值卡全额抵扣（纯色美甲88，余额充足）', async ({ request }) => {
    // 先买一张储值卡拿到 holding_id
    const buyRes = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID, items: [],
        goods_items: [{ goods_type: 'stored_value', goods_id: SV_PLAN_100, price_cents: 10000, name: '入门储值100', validity: { type: 'no_limit' } }],
        tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 10000 }],
        stored_value_splits: [],
      },
    });
    expect(buyRes.status()).toBe(201);

    // 用储值卡抵扣服务（需要知道 holding_id，从前端流程获取）
    // 这里直接测试 stored_value 支付是否 500
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'stored_value',
        split_payments: [{ method: 'stored_value', amount_cents: 8800 }],
        stored_value_holding_id: 'test_holding',
        stored_value_splits: [{ holding_id: 'test_holding', amount_cents: 8800 }],
      },
    });
    // 不应该 500（可能是 400 holding_not_found，但不应该是 500）
    expect(res.status()).not.toBe(500);
  });

  test('储值卡部分抵扣（50储值 + 38现金）', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'split',
        split_payments: [{ method: 'stored_value', amount_cents: 5000 }, { method: 'cash', amount_cents: 3800 }],
        stored_value_holding_id: 'test_holding',
        stored_value_splits: [{ holding_id: 'test_holding', amount_cents: 5000 }],
      },
    });
    // 不应该 500
    expect(res.status()).not.toBe(500);
  });

  test('带小费的储值卡支付', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 880, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'stored_value',
        split_payments: [{ method: 'stored_value', amount_cents: 9680 }],
        stored_value_holding_id: 'test_holding',
        stored_value_splits: [{ holding_id: 'test_holding', amount_cents: 9680 }],
      },
    });
    // 不应该 500
    expect(res.status()).not.toBe(500);
  });

  test('储值卡余额不足应返回 400', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_SHELL, name: '韩式贝壳片', quantity: 1, unit_price_cents: 22800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'stored_value',
        split_payments: [{ method: 'stored_value', amount_cents: 22800 }],
        stored_value_holding_id: 'test_holding',
        stored_value_splits: [{ holding_id: 'test_holding', amount_cents: 22800 }],
      },
    });
    // 余额不足应该是 400，不是 500
    expect(res.status()).not.toBe(500);
  });
});

// ═══════════════════════════════════════════
// 次卡核销
// ═══════════════════════════════════════════
test.describe('次卡核销', () => {

  test('次卡核销 - 假 holding_id 应被拒绝', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'visit_card',
        split_payments: [{ method: 'visit_card', amount_cents: 8800 }],
        visit_card_splits: [{ holding_id: 'fake_id_should_fail', amount_cents: 8800 }],
      },
    });
    // 假 holding_id 不应该成功！应该返回 400/404
    expect(res.status()).toBeGreaterThanOrEqual(400);
  });
});

// ═══════════════════════════════════════════
// 代金券核销
// ═══════════════════════════════════════════
test.describe('代金券核销', () => {

  test('代金券核销 - 假 voucher_id 应被拒绝', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'voucher',
        split_payments: [{ method: 'voucher', amount_cents: 8800 }],
        voucher_splits: [{ voucher_id: 'fake_id_should_fail', amount_cents: 8800 }],
      },
    });
    // 假 voucher_id 不应该成功！应该返回 400/404
    expect(res.status()).toBeGreaterThanOrEqual(400);
  });
});

// ═══════════════════════════════════════════
// 正常支付对照
// ═══════════════════════════════════════════
test.describe('正常支付（对照组）', () => {

  test('散客现金结账', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 8800 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.status).toBe('completed');
  });

  test('会员现金结账', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 8800 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.status).toBe('completed');
  });

  test('member_card 支付', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [{ type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 }],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'member_card',
        split_payments: [{ method: 'member_card', amount_cents: 8800 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
  });

  test('多服务现金结账', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/pos/transactions`, {
      headers: headers(),
      data: {
        pos_session_id: sessionId, client_id: ADA_ID,
        items: [
          { type: 'service', reference_id: SVC_PURE, name: '纯色美甲', quantity: 1, unit_price_cents: 8800 },
          { type: 'service', reference_id: '01KT3VBKHPTV2NTMPSF1XJ7HQC', name: '渐变美甲', quantity: 1, unit_price_cents: 13800 },
        ],
        goods_items: [], tip_cents: 0, service_charge_cents: 0, discount_cents: 0,
        order_date: today(), method: 'cash',
        split_payments: [{ method: 'cash', amount_cents: 22600 }],
        stored_value_splits: [],
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.total_cents).toBe(22600);
  });
});

// ═══════════════════════════════════════════
// 预约 API
// ═══════════════════════════════════════════
test.describe('预约 API', () => {

  test('创建预约（完整字段）', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/appointments`, {
      headers: headers(),
      data: {
        client_id: ADA_ID,
        service_id: SVC_PURE,
        employee_id: EMPLOYEE_ID,
        start_time: '2026-07-26T10:00:00Z',
        source: 'sys_employee',
        items: [{ service_id: SVC_PURE, employee_id: EMPLOYEE_ID, start_time: '2026-07-26T10:00:00Z', price_cents: 8800 }],
        notes: 'E2E测试',
      },
    });
    expect(res.status()).toBe(201);
    const data = await res.json();
    expect(data.status).toBe('confirmed');
  });

  test('创建预约（前端格式，缺顶层字段）', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/appointments`, {
      headers: headers(),
      data: {
        items: [{ service_id: SVC_PURE, employee_id: null, start_time: '2026-07-26T14:00:00Z' }],
        notes: '',
        client_id: ADA_ID,
      },
    });
    // 不应该 500（之前修好了）
    expect(res.status()).not.toBe(500);
  });

  test('创建预约 - 无效 service_id 应报错', async ({ request }) => {
    const res = await request.post(`${BASE}/nail/appointments`, {
      headers: headers(),
      data: {
        client_id: ADA_ID,
        service_id: 'invalid_service_id',
        employee_id: EMPLOYEE_ID,
        start_time: '2026-07-26T16:00:00Z',
        source: 'sys_employee',
        items: [{ service_id: 'invalid_service_id', employee_id: EMPLOYEE_ID, start_time: '2026-07-26T16:00:00Z', price_cents: 8800 }],
        notes: '',
      },
    });
    // 无效 service_id 应该返回 400/404，不是 500
    expect(res.status()).not.toBe(500);
  });
});

// ═══════════════════════════════════════════
// 会员数据验证
// ═══════════════════════════════════════════
test.describe('会员数据验证', () => {

  test('会员详情 - 消费记录更新', async ({ request }) => {
    const res = await request.get(`${BASE}/nail/clients/${ADA_ID}`, {
      headers: headers(),
    });
    expect(res.status()).toBe(200);
    const data = await res.json();
    expect(data.name).toBe('Ada');
    expect(data.total_visits).toBeGreaterThan(0);
    expect(data.total_spent_cents).toBeGreaterThan(0);
  });

  test('会员详情 - debt_amount 不为负', async ({ request }) => {
    const res = await request.get(`${BASE}/nail/clients/${ADA_ID}`, {
      headers: headers(),
    });
    expect(res.status()).toBe(200);
    const data = await res.json();
    expect(data.debt_amount_cents).toBeGreaterThanOrEqual(0);
  });
});
