import { GenericCrudService } from '@d8d/shared-crud';
import { DataSource, Not } from 'typeorm';
import { SalaryLevel } from '../entities/salary-level.entity';
import { AreaService, AreaLevel } from '@d8d/geo-areas';

export class SalaryService extends GenericCrudService<SalaryLevel> {
  private areaService: AreaService;

  constructor(dataSource: DataSource) {
    super(dataSource, SalaryLevel);
    this.areaService = new AreaService(dataSource);
  }

  /**
   * 创建薪资记录 - 覆盖父类方法，添加区域验证和唯一性检查
   */
  async create(data: Partial<SalaryLevel>, userId?: string | number): Promise<SalaryLevel> {
    // 验证区域数据
    await this.validateAreaData(data);

    // 检查是否已存在相同省份和城市的薪资记录
    if (data.provinceId && data.cityId) {
      const existingSalary = await this.repository.findOne({
        where: { provinceId: data.provinceId, cityId: data.cityId }
      });
      if (existingSalary) {
        throw new Error('该省份城市的薪资记录已存在');
      }
    }

    // 计算总薪资
    const totalSalary = this.calculateTotalSalary(data);

    // 设置创建数据
    const salaryData = {
      ...data,
      totalSalary,
      updateTime: new Date()
    };

    return super.create(salaryData, userId);
  }

  /**
   * 更新薪资记录 - 覆盖父类方法，添加存在性和区域验证
   */
  async update(id: number, data: Partial<SalaryLevel>, userId?: string | number): Promise<SalaryLevel | null> {
    // 检查薪资记录是否存在
    const salary = await this.repository.findOne({ where: { id } });
    if (!salary) {
      throw new Error('薪资记录不存在');
    }

    // 验证区域数据（如果提供了区域字段）
    if (data.provinceId || data.cityId || data.districtId) {
      await this.validateAreaData({
        provinceId: data.provinceId ?? salary.provinceId,
        cityId: data.cityId ?? salary.cityId,
        districtId: data.districtId ?? salary.districtId
      });
    }

    // 检查省份城市唯一性（如果省份或城市有变化）
    if ((data.provinceId && data.provinceId !== salary.provinceId) ||
        (data.cityId && data.cityId !== salary.cityId)) {
      const provinceId = data.provinceId ?? salary.provinceId;
      const cityId = data.cityId ?? salary.cityId;

      const existingSalary = await this.repository.findOne({
        where: { provinceId, cityId, id: Not(id) }
      });
      if (existingSalary) {
        throw new Error('该省份城市的薪资记录已存在');
      }
    }

    // 重新计算总薪资
    const updatedData = {
      ...data,
      totalSalary: this.calculateTotalSalary({ ...salary, ...data }),
      updateTime: new Date()
    };

    return super.update(id, updatedData, userId);
  }

  /**
   * 获取所有薪资记录（分页） - 自定义方法，返回源服务的格式
   */
  async findAll(
    skip: number = 0,
    take: number = 10,
    provinceId?: number,
    cityId?: number,
    districtId?: number
  ): Promise<{ data: SalaryLevel[], total: number }> {
    const where: any = {};

    if (provinceId) where.provinceId = provinceId;
    if (cityId) where.cityId = cityId;
    if (districtId) where.districtId = districtId;

    const [data, total] = await this.repository.findAndCount({
      where,
      skip,
      take,
      order: { updateTime: 'DESC' },
      relations: ['province', 'city', 'district']
    });

    return { data, total };
  }

  /**
   * 根据省份和城市查询薪资记录 - 自定义方法
   */
  async findByProvinceCity(provinceId: number, cityId: number): Promise<SalaryLevel | null> {
    const salary = await this.repository.findOne({
      where: { provinceId, cityId },
      relations: ['province', 'city', 'district']
    });

    if (!salary) {
      throw new Error('该省份城市的薪资记录不存在');
    }

    return salary;
  }

  /**
   * 获取单个薪资记录 - 自定义方法
   */
  async findOne(id: number): Promise<SalaryLevel | null> {
    return this.repository.findOne({
      where: { id },
      relations: ['province', 'city', 'district']
    });
  }

  /**
   * 验证区域数据
   */
  private async validateAreaData(data: Partial<SalaryLevel>): Promise<void> {
    if (!data.provinceId || !data.cityId) {
      throw new Error('省份和城市为必填项');
    }

    // 验证省份存在且为省级
    const province = await this.areaService.getSubTree(data.provinceId);
    if (!province || province.level !== AreaLevel.PROVINCE) {
      throw new Error('省份不存在或不是有效的省级区域');
    }

    // 验证城市存在且为市级，且父级为指定的省份
    const city = await this.areaService.getSubTree(data.cityId);
    if (!city || city.level !== AreaLevel.CITY) {
      throw new Error('城市不存在或不是有效的市级区域');
    }
    if (city.parentId !== data.provinceId) {
      throw new Error('城市不属于指定的省份');
    }

    // 验证区县（如果提供了区县ID）
    if (data.districtId) {
      const district = await this.areaService.getSubTree(data.districtId);
      if (!district || district.level !== AreaLevel.DISTRICT) {
        throw new Error('区县不存在或不是有效的区县级区域');
      }
      if (district.parentId !== data.cityId) {
        throw new Error('区县不属于指定的城市');
      }
    }
  }

  /**
   * 计算总薪资
   */
  private calculateTotalSalary(data: Partial<SalaryLevel>): number {
    // 将字符串转换为数字进行计算
    const basicSalary = typeof data.basicSalary === 'string' ? parseFloat(data.basicSalary) : (data.basicSalary ?? 0);
    const allowance = typeof data.allowance === 'string' ? parseFloat(data.allowance) : (data.allowance ?? 0);
    const insurance = typeof data.insurance === 'string' ? parseFloat(data.insurance) : (data.insurance ?? 0);
    const housingFund = typeof data.housingFund === 'string' ? parseFloat(data.housingFund) : (data.housingFund ?? 0);

    const total = basicSalary + allowance + insurance + housingFund;
    // 保留2位小数，转换为数字
    return parseFloat(total.toFixed(2));
  }
}