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 { UserEntity, Role } from '@d8d/user-module';
import { File } from '@d8d/file-module';
import disabledPersonRoutes from '../../src/routes/disabled-person.routes';
import { DisabledPerson } from '../../src/entities/disabled-person.entity';
import { DisabledBankCard } from '../../src/entities/disabled-bank-card.entity';
import { DisabledPhoto } from '../../src/entities/disabled-photo.entity';
import { DisabledRemark } from '../../src/entities/disabled-remark.entity';
import { DisabledVisit } from '../../src/entities/disabled-visit.entity';

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

describe('残疾人管理API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof disabledPersonRoutes>>;
  let testToken: string;
  let testUser: UserEntity;
  let testFile: File;

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

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

    // 创建测试用户
    const userRepository = dataSource.getRepository(UserEntity);
    testUser = userRepository.create({
      username: `test_user_${Date.now()}`,
      password: 'test_password',
      nickname: '测试用户',
      registrationSource: 'web'
    });
    await userRepository.save(testUser);

    // 创建测试文件（用于照片集成测试）
    const fileRepository = dataSource.getRepository(File);
    testFile = fileRepository.create({
      name: 'test_photo.jpg',
      path: 'test_photo.jpg',
      type: 'image/jpeg',
      size: 1024,
      uploadUserId: testUser.id,
      uploadTime: new Date()
    });
    await fileRepository.save(testFile);

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

  describe('POST /createDisabledPerson', () => {
    it('应该成功创建残疾人基本信息', async () => {
      const createData = {
        name: '张三',
        gender: '男',
        idCard: '110101199001011234',
        disabilityId: 'D123456789',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市东城区',
        phone: '13800138000',
        province: '北京市',
        city: '北京市'
      };

      const response = await client.createDisabledPerson.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data.name).toBe(createData.name);
        expect(data.idCard).toBe(createData.idCard);
        expect(data.disabilityId).toBe(createData.disabilityId);
      }
    });

    it('应该验证身份证号唯一性', async () => {
      // 先创建一个残疾人
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
      const existingPerson = disabledPersonRepository.create({
        name: '李四',
        gender: '女',
        idCard: '110101199001011235',
        disabilityId: 'D123456788',
        disabilityType: '视力残疾',
        disabilityLevel: '二级',
        idAddress: '北京市西城区',
        phone: '13900139000',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(existingPerson);

      // 尝试创建相同身份证号的残疾人
      const createData = {
        name: '王五',
        gender: '男',
        idCard: '110101199001011235', // 重复的身份证号
        disabilityId: 'D123456777',
        disabilityType: '听力残疾',
        disabilityLevel: '三级',
        idAddress: '北京市朝阳区',
        phone: '13700137000',
        province: '北京市',
        city: '北京市'
      };

      const response = await client.createDisabledPerson.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

    it('应该验证必填字段', async () => {
      const createData = {
        name: '', // 空字符串，应该验证失败
        gender: '男',
        idCard: '110101199001011236',
        disabilityId: 'D123456776',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市海淀区',
        phone: '13600136000',
        province: '北京市',
        city: '北京市'
      };

      const response = await client.createDisabledPerson.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

  describe('POST /deleteDisabledPerson', () => {
    it('应该成功删除残疾人', async () => {
      // 先创建一个残疾人
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
      const person = disabledPersonRepository.create({
        name: '测试删除人员',
        gender: '男',
        idCard: '110101199001011237',
        disabilityId: 'D123456775',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市石景山区',
        phone: '13500135000',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person);

      const deleteData = {
        id: person.id
      };

      const response = await client.deleteDisabledPerson.$post({
        json: deleteData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data.success).toBe(true);

        // 验证残疾人已被删除
        const deletedPerson = await disabledPersonRepository.findOne({ where: { id: person.id } });
        expect(deletedPerson).toBeNull();
      }
    });

    it('应该处理不存在的残疾人ID', async () => {
      const deleteData = {
        id: 99999 // 不存在的ID
      };

      const response = await client.deleteDisabledPerson.$post({
        json: deleteData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

  describe('POST /updateDisabledPerson', () => {
    it('应该成功更新残疾人信息', async () => {
      // 先创建一个残疾人
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
      const person = disabledPersonRepository.create({
        name: '原始姓名',
        gender: '男',
        idCard: '110101199001011238',
        disabilityId: 'D123456774',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市通州区',
        phone: '13400134000',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person);

      const updateData = {
        id: person.id,
        name: '更新后的姓名',
        gender: '女',
        phone: '13300133000'
      };

      const response = await client.updateDisabledPerson.$post({
        json: updateData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data.name).toBe(updateData.name);
        expect(data.gender).toBe(updateData.gender);
        expect(data.phone).toBe(updateData.phone);
      }
    });

    it('应该验证身份证号唯一性（更新时）', async () => {
      // 创建两个残疾人
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);

      const person1 = disabledPersonRepository.create({
        name: '人员A',
        gender: '男',
        idCard: '110101199001011239',
        disabilityId: 'D123456773',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市顺义区',
        phone: '13200132000',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person1);

      const person2 = disabledPersonRepository.create({
        name: '人员B',
        gender: '女',
        idCard: '110101199001011240',
        disabilityId: 'D123456772',
        disabilityType: '视力残疾',
        disabilityLevel: '二级',
        idAddress: '北京市大兴区',
        phone: '13100131000',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person2);

      // 尝试将人员2的身份证号改为人员1的身份证号
      const updateData = {
        id: person2.id,
        idCard: '110101199001011239' // 重复的身份证号
      };

      const response = await client.updateDisabledPerson.$post({
        json: updateData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

    it('应该处理不存在的残疾人', async () => {
      const updateData = {
        id: 99999, // 不存在的ID
        name: '新姓名'
      };

      const response = await client.updateDisabledPerson.$post({
        json: updateData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

  describe('GET /getAllDisabledPersons', () => {
    it('应该成功获取残疾人列表（分页）', async () => {
      // 创建一些测试数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);

      for (let i = 1; i <= 5; i++) {
        const person = disabledPersonRepository.create({
          name: `残疾人${i}`,
          gender: i % 2 === 0 ? '女' : '男',
          idCard: `1101011990010112${40 + i}`,
          disabilityId: `D1234567${70 + i}`,
          disabilityType: '肢体残疾',
          disabilityLevel: '一级',
          idAddress: `北京市测试区${i}`,
          phone: `138001380${i}`,
          province: '北京市',
          city: '北京市'
        });
        await disabledPersonRepository.save(person);
      }

      const response = await client.getAllDisabledPersons.$get({
        query: {
          skip: 0,
          take: 10
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data.data).toHaveLength(5);
        expect(data.total).toBe(5);
        expect(data.data[0].name).toBe('残疾人5'); // 按ID降序排列
      }
    });

    it('应该处理分页参数', async () => {
      // 创建更多测试数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);

      for (let i = 1; i <= 15; i++) {
        const person = disabledPersonRepository.create({
          name: `分页人员${i}`,
          gender: i % 2 === 0 ? '女' : '男',
          idCard: `1101011990010113${i}`,
          disabilityId: `D1234568${i}`,
          disabilityType: '肢体残疾',
          disabilityLevel: '一级',
          idAddress: `北京市分页区${i}`,
          phone: `138001381${i}`,
          province: '北京市',
          city: '北京市'
        });
        await disabledPersonRepository.save(person);
      }

      const response = await client.getAllDisabledPersons.$get({
        query: {
          skip: 5,
          take: 5
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

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

  describe('GET /searchDisabledPersons', () => {
    it('应该成功按姓名搜索残疾人', async () => {
      // 创建测试数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);

      const person1 = disabledPersonRepository.create({
        name: '张三',
        gender: '男',
        idCard: '110101199001011241',
        disabilityId: 'D123456771',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市昌平区',
        phone: '13000130001',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person1);

      const person2 = disabledPersonRepository.create({
        name: '李四',
        gender: '女',
        idCard: '110101199001011242',
        disabilityId: 'D123456770',
        disabilityType: '视力残疾',
        disabilityLevel: '二级',
        idAddress: '北京市平谷区',
        phone: '13000130002',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person2);

      const response = await client.searchDisabledPersons.$get({
        query: {
          keyword: '张三',
          skip: 0,
          take: 10
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data.data).toHaveLength(1);
        expect(data.data[0].name).toBe('张三');
      }
    });

    it('应该验证搜索关键词不能为空', async () => {
      const response = await client.searchDisabledPersons.$get({
        query: {
          keyword: '', // 空关键词
          skip: 0,
          take: 10
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

  describe('GET /getDisabledPerson/{id}', () => {
    it('应该成功获取单个残疾人详情', async () => {
      // 先创建一个残疾人
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
      const person = disabledPersonRepository.create({
        name: '测试人员详情',
        gender: '男',
        idCard: '110101199001011243',
        disabilityId: 'D123456769',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市怀柔区',
        phone: '13000130003',
        province: '北京市',
        city: '北京市',
        canDirectContact: 1,
        isMarried: 1
      });
      await disabledPersonRepository.save(person);

      const response = await client.getDisabledPerson[':id'].$get({
        param: {
          id: person.id
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data?.name).toBe('测试人员详情');
        expect(data?.canDirectContact).toBe(1);
      }
    });

    it('应该处理不存在的残疾人ID', async () => {
      const response = await client.getDisabledPerson[':id'].$get({
        param: {
          id: 99999 // 不存在的ID
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200); // 返回200，但数据为null

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

  describe('GET /getDisabledPersonByIdCard', () => {
    it('应该成功根据身份证号查询残疾人', async () => {
      // 先创建一个残疾人
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
      const person = disabledPersonRepository.create({
        name: '身份证查询测试',
        gender: '女',
        idCard: '110101199001011244',
        disabilityId: 'D123456768',
        disabilityType: '听力残疾',
        disabilityLevel: '三级',
        idAddress: '北京市密云区',
        phone: '13000130004',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person);

      const response = await client.findByIdCard[':idCard'].$get({
        param: {
          idCard: '110101199001011244'
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data?.name).toBe('身份证查询测试');
        expect(data?.idCard).toBe('110101199001011244');
      }
    });

    it('应该处理不存在的身份证号', async () => {
      const response = await client.findByIdCard[':idCard'].$get({
        param: {
          idCard: '999999999999999999' // 不存在的身份证号
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200); // 返回200，但数据为null

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

  describe('POST /createAggregatedDisabledPerson', () => {
    it('应该成功创建聚合残疾人信息（包含所有关联数据）', async () => {
      const createData = {
        personInfo: {
          name: '聚合创建测试',
          gender: '男',
          idCard: '110101199001011245',
          disabilityId: 'D123456767',
          disabilityType: '肢体残疾',
          disabilityLevel: '一级',
          idAddress: '北京市延庆区',
          phone: '13000130005',
          province: '北京市',
          city: '北京市'
        },
        bankCards: [
          {
            subBankName: '北京分行',
            bankName: '中国工商银行',
            cardNumber: '6222021234567890123',
            cardholderName: '聚合创建测试',
            fileId: testFile.id,
            isDefault: 0
          }
        ],
        photos: [
          {
            photoType: '身份证照片',
            fileId: testFile.id // 使用测试文件ID
          }
        ],
        remarks: [
          {
            remarkContent: '家庭经济困难，需要帮助',
            operatorId: 1
          }
        ],
        visits: [
          {
            visitDate: '2025-12-02T10:00:00Z',
            visitType: '电话回访',
            visitContent: '初次回访，了解基本情况',
            visitorId: 1
          }
        ]
      };

      const response = await client.createAggregatedDisabledPerson.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data.personInfo.name).toBe('聚合创建测试');
        expect(data.bankCards).toHaveLength(1);
        expect(data.photos).toHaveLength(1);
        expect(data.remarks).toHaveLength(1);
        expect(data.visits).toHaveLength(1);

        // 验证文件集成
        expect(data.photos[0].fileId).toBe(testFile.id);
      }
    });

    it('应该验证文件ID的有效性', async () => {
      const createData = {
        personInfo: {
          name: '文件验证测试',
          gender: '女',
          idCard: '110101199001011246',
          disabilityId: 'D123456766',
          disabilityType: '视力残疾',
          disabilityLevel: '二级',
          idAddress: '北京市房山区',
          phone: '13000130006',
          province: '北京市',
          city: '北京市'
        },
        photos: [
          {
            photoType: '身份证照片',
            fileId: 99999 // 不存在的文件ID
          }
        ]
      };

      const response = await client.createAggregatedDisabledPerson.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400); // 应该返回400，因为文件ID无效
    });
  });

  describe('GET /getAggregatedDisabledPerson/{personId}', () => {
    it('应该成功获取聚合残疾人信息', async () => {
      // 先创建一个完整的残疾人数据（包含所有关联数据）
      const dataSource = await IntegrationTestDatabase.getDataSource();

      // 创建残疾人
      const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
      const person = disabledPersonRepository.create({
        name: '聚合查询测试',
        gender: '男',
        idCard: '110101199001011247',
        disabilityId: 'D123456765',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市门头沟区',
        phone: '13000130007',
        province: '北京市',
        city: '北京市'
      });
      await disabledPersonRepository.save(person);

      // 创建银行卡
      const bankCardRepository = dataSource.getRepository(DisabledBankCard);
      const bankCard = bankCardRepository.create({
        personId: person.id,
        subBankName: '北京分行',
        bankName: '中国建设银行',
        cardNumber: '6227001234567890123',
        cardholderName: '聚合查询测试',
        fileId: testFile.id,
        isDefault: 0
      });
      await bankCardRepository.save(bankCard);

      // 创建照片（使用测试文件）
      const photoRepository = dataSource.getRepository(DisabledPhoto);
      const photo = photoRepository.create({
        personId: person.id,
        photoType: '身份证照片',
        fileId: testFile.id
      });
      await photoRepository.save(photo);

      // 创建备注
      const remarkRepository = dataSource.getRepository(DisabledRemark);
      const remark = remarkRepository.create({
        personId: person.id,
        remarkContent: '目前无工作，需要就业帮助',
        operatorId: 1
      });
      await remarkRepository.save(remark);

      // 创建回访记录
      const visitRepository = dataSource.getRepository(DisabledVisit);
      const visit = visitRepository.create({
        personId: person.id,
        visitDate: new Date('2025-12-01T14:30:00Z'),
        visitType: '上门回访',
        visitContent: '了解就业需求',
        visitorId: 2
      });
      await visitRepository.save(visit);

      const response = await client.getAggregatedDisabledPerson[':id'].$get({
        param: {
          id: person.id
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        expect(data).not.toBeNull();
        expect(data!.personInfo.name).toBe('聚合查询测试');
        expect(data!.bankCards).toHaveLength(1);
        expect(data!.photos).toHaveLength(1);
        expect(data!.remarks).toHaveLength(1);
        expect(data!.visits).toHaveLength(1);

        // 验证文件数据完整性
        expect(data!.photos[0].fileId).toBe(testFile.id);
      }
    });

    it('应该处理不存在的残疾人ID', async () => {
      const response = await client.getAggregatedDisabledPerson[':id'].$get({
        param: {
          id: 99999 // 不存在的ID
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

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

  describe('认证测试', () => {
    it('应该验证所有端点需要认证', async () => {
      // 测试没有token的情况
      const response = await client.createDisabledPerson.$post({
        json: {
          name: '测试人员',
          gender: '男',
          idCard: '110101199001011235',
          disabilityId: 'D123456789',
          disabilityType: '视力残疾',
          disabilityLevel: '一级',
          idAddress: '北京市东城区',
          phone: '13800138000',
          province: '北京市',
          city: '北京市'
        }
      });

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

    it('应该验证无效token', async () => {
      const response = await client.createDisabledPerson.$post({
        json: {
          name: '测试人员',
          gender: '男',
          idCard: '110101199001011236',
          disabilityId: 'D123456790',
          disabilityType: '视力残疾',
          disabilityLevel: '一级',
          idAddress: '北京市东城区',
          phone: '13800138001',
          province: '北京市',
          city: '北京市'
        }
      }, {
        headers: {
          'Authorization': 'Bearer invalid_token'
        }
      });

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