/**
 * E2E 测试: 自动创建账号 (MPC 2-of-3)
 *
 * 测试流程:
 * 1. 调用 POST /user/auto-create 创建账号
 * 2. 验证返回的账号信息
 * 3. 验证钱包地址格式
 * 4. 验证 MPC 分片数据
 */

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';

describe('AutoCreateAccount (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    app.useGlobalPipes(new ValidationPipe({ transform: true }));
    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  describe('POST /user/auto-create', () => {
    it('should create account with MPC 2-of-3 wallet', async () => {
      const deviceId = `test-device-${Date.now()}`;

      const response = await request(app.getHttpServer())
        .post('/user/auto-create')
        .send({
          deviceId,
          deviceName: 'Test Device',
        })
        .expect(201);

      const body = response.body;

      // 验证基本字段
      expect(body).toHaveProperty('userId');
      expect(body).toHaveProperty('accountSequence');
      expect(body).toHaveProperty('referralCode');
      expect(body).toHaveProperty('accessToken');
      expect(body).toHaveProperty('refreshToken');
      expect(body).toHaveProperty('walletAddresses');

      // 验证钱包地址格式
      // BSC 和 KAVA 是 EVM 兼容链，使用 0x 前缀的地址
      expect(body.walletAddresses.bsc).toMatch(/^0x[a-fA-F0-9]{40}$/);
      expect(body.walletAddresses.kava).toMatch(/^0x[a-fA-F0-9]{40}$/);
      // DST 是 Cosmos 链，使用 Bech32 格式 (dst1...)
      expect(body.walletAddresses.dst).toMatch(/^dst1[a-z0-9]{38,58}$/);

      // BSC 和 KAVA 地址应该相同 (同一个 MPC 公钥派生的 EVM 地址)
      expect(body.walletAddresses.bsc).toBe(body.walletAddresses.kava);
      // DST 地址是不同格式，不应该与 EVM 地址相同
      expect(body.walletAddresses.dst).not.toBe(body.walletAddresses.bsc);

      // 验证 MPC 相关字段
      expect(body).toHaveProperty('clientShareData');
      expect(body).toHaveProperty('publicKey');
      expect(body.clientShareData).toBeTruthy();
      expect(body.publicKey).toBeTruthy();

      // MPC 模式下 mnemonic 应该为空
      expect(body.mnemonic).toBe('');

      // 验证账号序列号是正整数
      expect(typeof body.accountSequence).toBe('number');
      expect(body.accountSequence).toBeGreaterThan(0);

      // 验证推荐码格式 (假设是 6-10 位字母数字)
      expect(body.referralCode).toMatch(/^[A-Z0-9]{6,10}$/);

      console.log('Created account:', {
        userId: body.userId,
        accountSequence: body.accountSequence,
        referralCode: body.referralCode,
        publicKey: body.publicKey?.substring(0, 20) + '...',
        bscAddress: body.walletAddresses.bsc,
      });
    });

    it('should create different accounts for different devices', async () => {
      const deviceId1 = `test-device-a-${Date.now()}`;
      const deviceId2 = `test-device-b-${Date.now()}`;

      const [response1, response2] = await Promise.all([
        request(app.getHttpServer())
          .post('/user/auto-create')
          .send({ deviceId: deviceId1 }),
        request(app.getHttpServer())
          .post('/user/auto-create')
          .send({ deviceId: deviceId2 }),
      ]);

      // 两个账号应该有不同的序列号和钱包地址
      expect(response1.body.accountSequence).not.toBe(
        response2.body.accountSequence,
      );
      expect(response1.body.walletAddresses.bsc).not.toBe(
        response2.body.walletAddresses.bsc,
      );
      expect(response1.body.publicKey).not.toBe(response2.body.publicKey);
    });

    it('should reject invalid device id', async () => {
      await request(app.getHttpServer())
        .post('/user/auto-create')
        .send({
          deviceId: '', // 空设备ID
        })
        .expect(400);
    });

    it('should handle inviter referral code', async () => {
      // 先创建一个账号作为邀请人
      const inviterResponse = await request(app.getHttpServer())
        .post('/user/auto-create')
        .send({ deviceId: `inviter-${Date.now()}` })
        .expect(201);

      const inviterReferralCode = inviterResponse.body.referralCode;

      // 使用邀请码创建新账号
      const inviteeResponse = await request(app.getHttpServer())
        .post('/user/auto-create')
        .send({
          deviceId: `invitee-${Date.now()}`,
          inviterReferralCode,
        })
        .expect(201);

      expect(inviteeResponse.body.accountSequence).toBeGreaterThan(
        inviterResponse.body.accountSequence,
      );
    });
  });
});
