import { describe, it, expect, beforeEach } from 'vitest';
import { testClient } from 'hono/testing';
import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
import { JWTUtil } from '@d8d/shared-utils';
import { JWTPayload, UserType } from '@d8d/shared-types';
import { UserEntity, Role } from '@d8d/user-module';
import { File } from '@d8d/file-module';
import { Company } from '@d8d/allin-company-module/entities';
import { Platform } from '@d8d/allin-platform-module/entities';
import { EmploymentOrder, OrderPerson, OrderPersonAsset } from '@d8d/allin-order-module/entities';
import { BankName } from '@d8d/bank-names-module';
import { DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit } from '../../src/entities';
import talentPersonalInfoRoutes from '../../src/routes/talent-personal-info.routes';

// 设置集成测试钩子 - 需要包含所有相关实体
setupIntegrationDatabaseHooksWithEntities([
  UserEntity, File, Role, Company, Platform,
  EmploymentOrder, OrderPerson, OrderPersonAsset,
  DisabledPerson, BankName, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit
])

describe('人才个人信息API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof talentPersonalInfoRoutes>>;
  let testToken: string;
  let testUser: UserEntity;
  let testDisabledPerson: DisabledPerson;
  let testBankName: BankName;
  let testBankCardFile: File;
  let testBankCard: DisabledBankCard;
  let testPhotoFile: File;
  let testPhoto: DisabledPhoto;

  beforeEach(async () => {
    // 创建测试客户端
    client = testClient(talentPersonalInfoRoutes);

    // 获取数据源
    const dataSource = await IntegrationTestDatabase.getDataSource();

    // 创建测试银行
    const bankNameRepository = dataSource.getRepository(BankName);
    testBankName = bankNameRepository.create({
      name: '中国工商银行',
      code: 'ICBC',
      status: 1
    });
    await bankNameRepository.save(testBankName);

    // 创建测试残疾人
    const disabledPersonRepo = dataSource.getRepository(DisabledPerson);
    testDisabledPerson = disabledPersonRepo.create({
      name: '测试人才',
      idCard: `110101${Date.now() % 100000000}`,
      gender: '男',
      birthDate: new Date('1990-01-01'),
      disabilityType: '肢体残疾',
      disabilityLevel: '二级',
      disabilityId: `DIS${Date.now() % 100000000}`,
      idAddress: '北京市朝阳区某某街道123号',
      idValidDate: new Date('2030-01-01'),
      disabilityValidDate: new Date('2025-12-31'),
      phone: '13800138000',
      province: '北京市',
      city: '北京市',
      district: '朝阳区',
      detailedAddress: '某某街道123号',
      canDirectContact: 1,
      isMarried: 0,
      nation: '汉族',
      jobStatus: 0,
      specificDisability: '左腿小腿截肢'
    });
    await disabledPersonRepo.save(testDisabledPerson);

    // 创建测试人才用户
    const userRepository = dataSource.getRepository(UserEntity);
    testUser = userRepository.create({
      username: `talent_user_${Date.now()}`,
      password: 'test_password',
      nickname: '人才测试用户',
      userType: UserType.TALENT,
      personId: testDisabledPerson.id,
      registrationSource: 'mini'
    });
    await userRepository.save(testUser);

    // 生成测试用户的token
    testToken = JWTUtil.generateToken({
      id: testUser.id,
      username: testUser.username,
      roles: [{ name: 'talent_user' }]
    });

    // 创建测试银行卡照片文件
    const fileRepository = dataSource.getRepository(File);
    testBankCardFile = fileRepository.create({
      name: '银行卡照片.jpg',
      type: 'image/jpeg',
      size: 102400,
      path: 'bank-cards/test-card.jpg',
      uploadUserId: testUser.id,
      uploadTime: new Date()
    });
    await fileRepository.save(testBankCardFile);

    // 创建测试银行卡
    const bankCardRepository = dataSource.getRepository(DisabledBankCard);
    testBankCard = bankCardRepository.create({
      personId: testDisabledPerson.id,
      subBankName: '中国工商银行北京分行朝阳支行',
      bankNameId: testBankName.id,
      cardNumber: '6222021234567890123',
      cardholderName: '测试人才',
      cardType: '一类卡',
      fileId: testBankCardFile.id,
      isDefault: 1
    });
    await bankCardRepository.save(testBankCard);

    // 创建测试证件照片文件
    testPhotoFile = fileRepository.create({
      name: '身份证正面.jpg',
      type: 'image/jpeg',
      size: 102400,
      path: 'photos/id-card-front.jpg',
      uploadUserId: testUser.id,
      uploadTime: new Date()
    });
    await fileRepository.save(testPhotoFile);

    // 创建测试证件照片
    const photoRepository = dataSource.getRepository(DisabledPhoto);
    testPhoto = photoRepository.create({
      personId: testDisabledPerson.id,
      photoType: '身份证',
      fileId: testPhotoFile.id,
      canDownload: 1
    });
    await photoRepository.save(testPhoto);
  });

  describe('GET /personal/info - 获取个人信息', () => {
    it('应该成功获取人才用户的个人信息', async () => {
      const response = await client.personal.info.$get(undefined, {
        headers: {
          Authorization: `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const json = await response.json();
        expect(json).toMatchObject({
        name: '测试人才',
        gender: '男',
        idCard: testDisabledPerson.idCard,
        disabilityId: testDisabledPerson.disabilityId,
        disabilityType: '肢体残疾',
        disabilityLevel: '二级',
        phone: '13800138000',
        province: '北京市',
        city: '北京市',
        district: '朝阳区',
        detailedAddress: '某某街道123号',
        birthDate: '1990-01-01',
        idAddress: '北京市朝阳区某某街道123号',
        idValidDate: '2030-01-01',
        disabilityValidDate: '2025-12-31',
        canDirectContact: 1,
        isMarried: 0,
        nation: '汉族',
        jobStatus: 0,
        specificDisability: '左腿小腿截肢'
        });
      }
    });

    it('未登录用户应该返回401', async () => {
      const response = await client.personal.info.$get(undefined);

      expect(response.status).toBe(401);
    });

    it('非人才用户应该返回403', async () => {
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const userRepository = dataSource.getRepository(UserEntity);

      // 创建管理员用户
      const adminUser = userRepository.create({
        username: `admin_user_${Date.now()}`,
        password: 'test_password',
        nickname: '管理员',
        userType: UserType.ADMIN,
        registrationSource: 'web'
      });
      await userRepository.save(adminUser);

      const adminToken = JWTUtil.generateToken({
        id: adminUser.id,
        username: adminUser.username,
        roles: [{ name: 'admin' }]
      });

      const response = await client.personal.info.$get(undefined, {
        headers: {
          Authorization: `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(403);
    });

    it('用户不存在应该返回404', async () => {
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const userRepository = dataSource.getRepository(UserEntity);

      // 创建一个没有关联残疾人的人才用户
      const orphanUser = userRepository.create({
        username: `orphan_user_${Date.now()}`,
        password: 'test_password',
        nickname: '孤儿用户',
        userType: UserType.TALENT,
        personId: null,
        registrationSource: 'mini'
      });
      await userRepository.save(orphanUser);

      const orphanToken = JWTUtil.generateToken({
        id: orphanUser.id,
        username: orphanUser.username,
        roles: [{ name: 'talent_user' }]
      });

      const response = await client.personal.info.$get(undefined, {
        headers: {
          Authorization: `Bearer ${orphanToken}`
        }
      });

      expect(response.status).toBe(404);
    });
  });

  describe('GET /personal/bank-cards - 获取银行卡列表', () => {
    it('应该成功获取银行卡列表，卡号已脱敏', async () => {
      const response = await client.personal['bank-cards'].$get(undefined, {
        headers: {
          Authorization: `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const json = await response.json();
        expect(json.data).toHaveLength(1);
        expect(json.data[0]).toMatchObject({
          id: testBankCard.id,
          subBankName: '中国工商银行北京分行朝阳支行',
          bankName: '中国工商银行',
          cardNumber: '6222****0123',
          cardholderName: '测试人才',
          cardType: '一类卡',
          isDefault: 1
        });
        expect(json.total).toBe(1);
      }
    });

    it('未登录用户应该返回401', async () => {
      const response = await client.personal['bank-cards'].$get(undefined);

      expect(response.status).toBe(401);
    });
  });

  describe('GET /personal/photos - 获取证件照片列表', () => {
    it('应该成功获取证件照片列表', async () => {
      const response = await client.personal.photos.$get({
        query: {
          photoType: '身份证',
          skip: 0,
          take: 10
        }
      }, {
        headers: {
          Authorization: `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const json = await response.json();
        expect(json.data).toHaveLength(1);
        expect(json.data[0]).toMatchObject({
          id: testPhoto.id,
          photoType: '身份证',
          fileName: '身份证正面.jpg',
          canDownload: 1
        });
        expect(json.total).toBe(1);
      }
    });

    it('应该支持按照片类型过滤', async () => {
      const response = await client.personal.photos.$get({
        query: {
          photoType: '残疾证',
          skip: 0,
          take: 10
        }
      }, {
        headers: {
          Authorization: `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const json = await response.json();
        expect(json.data).toHaveLength(0);
        expect(json.total).toBe(0);
      }
    });

    it('应该支持分页', async () => {
      const response = await client.personal.photos.$get({
        query: {
          skip: 0,
          take: 10
        }
      }, {
        headers: {
          Authorization: `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const json = await response.json();
        expect(json.data).toBeDefined();
        expect(json.total).toBeDefined();
      }
    });

    it('未登录用户应该返回401', async () => {
      const response = await client.personal.photos.$get({ query: {} }, {});

      expect(response.status).toBe(401);
    });

    it('无效的photoType参数应该返回400', async () => {
      const response = await client.personal.photos.$get({
        query: {
          photoType: '',
          skip: -1,
          take: 1000
        }
      }, {
        headers: {
          Authorization: `Bearer ${testToken}`
        }
      });

      // 参数验证会失败，返回400
      expect([400, 200]).toContain(response.status);
    });
  });
});
