const request = require('supertest');
const app = require('../final-backend');
const db = require('../db-sqlite');

describe('核销申请流程测试', () => {
  let server;
  let advanceId;
  let verificationId1;
  let verificationId2;

  beforeAll(async () => {
    server = app.listen(3006);
    
    // 清理测试数据
    await db.query('DELETE FROM verifications WHERE 1=1');
    await db.query('DELETE FROM advances WHERE 1=1');
    
    // 创建测试预支申请
    const advanceResult = await db.query(
      'INSERT INTO advances (user_id, project_id, amount, currency, reason, advance_date, advance_code, status, applicant, attachments) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
      [1, null, 10000, 'CNY', '测试预支', '2026-03-25', 'ADV-TEST', 'executed', '测试用户', '[]']
    );
    advanceId = advanceResult.lastID;
    
    // 更新预支单状态为待核销
    await db.query('UPDATE advances SET status = ? WHERE id = ?', ['pending_verification', advanceId]);
  });

  afterAll(async () => {
    server.close();
  });

  describe('预支单状态管理', () => {
    test('预支单初始状态应该是待核销', async () => {
      const result = await db.query('SELECT status FROM advances WHERE id = ?', [advanceId]);
      expect(result.rows[0].status).toBe('pending_verification');
    });
  });

  describe('核销申请创建', () => {
    test('创建第一张核销申请（非结算）', async () => {
      const response = await request(server)
        .post('/api/verifications')
        .send({
          verification_date: '2026-03-25',
          advance_id: advanceId,
          advance_code: 'ADV-TEST',
          advance_amount: 10000,
          currency: 'CNY',
          reason: '测试核销1',
          detail_items: [{ description: '测试费用1', amount: 6000, category: 'accommodation' }],
          attachments: [],
          applicant: '测试用户',
          expense_type: 'company',
          project_id: null,
          settlement: false
        });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      verificationId1 = response.body.data.id;
      
      // 检查预支单已核销金额是否更新
      const advanceResult = await db.query('SELECT total_reimbursed FROM advances WHERE id = ?', [advanceId]);
      expect(advanceResult.rows[0].total_reimbursed).toBe(6000);
    });

    test('创建第二张核销申请（结算）', async () => {
      const response = await request(server)
        .post('/api/verifications')
        .send({
          verification_date: '2026-03-25',
          advance_id: advanceId,
          advance_code: 'ADV-TEST',
          advance_amount: 10000,
          currency: 'CNY',
          reason: '测试核销2',
          detail_items: [{ description: '测试费用2', amount: 5000, category: 'food' }],
          attachments: [],
          applicant: '测试用户',
          expense_type: 'company',
          project_id: null,
          settlement: true,
          settlement_amount: -1000
        });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      verificationId2 = response.body.data.id;
      
      // 检查预支单已核销金额是否更新
      const advanceResult = await db.query('SELECT total_reimbursed FROM advances WHERE id = ?', [advanceId]);
      expect(advanceResult.rows[0].total_reimbursed).toBe(11000);
    });
  });

  describe('核销申请审批和执行', () => {
    test('审批第一张核销申请', async () => {
      const response = await request(server)
        .post(`/api/verifications/${verificationId1}/approve`)
        .send({ remark: '批准' });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    test('执行第一张核销申请（非结算）', async () => {
      const response = await request(server)
        .post(`/api/verifications/${verificationId1}/execute`)
        .send({ execute_method: '银行转账', voucher_no: 'VOUCHER-001' });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      
      // 检查预支单状态应该变为部分核销
      const advanceResult = await db.query('SELECT status FROM advances WHERE id = ?', [advanceId]);
      expect(advanceResult.rows[0].status).toBe('partial_verification');
    });

    test('审批第二张核销申请', async () => {
      const response = await request(server)
        .post(`/api/verifications/${verificationId2}/approve`)
        .send({ remark: '批准' });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    test('执行第二张核销申请（结算）', async () => {
      const response = await request(server)
        .post(`/api/verifications/${verificationId2}/execute`)
        .send({ execute_method: '银行转账', voucher_no: 'VOUCHER-002' });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      
      // 检查预支单状态应该变为已完成
      const advanceResult = await db.query('SELECT status FROM advances WHERE id = ?', [advanceId]);
      expect(advanceResult.rows[0].status).toBe('completed');
    });
  });

  describe('核销申请退回', () => {
    test('创建测试核销申请', async () => {
      const response = await request(server)
        .post('/api/verifications')
        .send({
          verification_date: '2026-03-25',
          advance_id: advanceId,
          advance_code: 'ADV-TEST',
          advance_amount: 10000,
          currency: 'CNY',
          reason: '测试退回',
          detail_items: [{ description: '测试费用', amount: 2000, category: 'transportation' }],
          attachments: [],
          applicant: '测试用户',
          expense_type: 'company',
          project_id: null,
          settlement: false
        });
      
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      const testVerificationId = response.body.data.id;
      
      // 检查预支单已核销金额是否更新
      let advanceResult = await db.query('SELECT total_reimbursed FROM advances WHERE id = ?', [advanceId]);
      expect(advanceResult.rows[0].total_reimbursed).toBe(13000);
      
      // 退回核销申请
      const rejectResponse = await request(server)
        .post(`/api/verifications/${testVerificationId}/reject`)
        .send({ remark: '退回' });
      
      expect(rejectResponse.status).toBe(200);
      expect(rejectResponse.body.success).toBe(true);
      
      // 检查预支单已核销金额是否恢复
      advanceResult = await db.query('SELECT total_reimbursed FROM advances WHERE id = ?', [advanceId]);
      expect(advanceResult.rows[0].total_reimbursed).toBe(11000);
    });
  });
});
