import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { AuditOrderEntity } from '../entity/order';

/**
 * 筛选参数
 */
interface StatsQuery {
  startTime?: string;
  endTime?: string;
  orderType?: string;
  oemId?: number;
  insuranceCompany?: string;
  productName?: string;
  factoryName?: string;
}

/**
 * 审核经营数据统计服务
 */
@Provide()
@Scope(ScopeEnum.Prototype)
export class AuditStatsService {
  @InjectEntityModel(AuditOrderEntity)
  auditOrderEntity: Repository<AuditOrderEntity>;

  /**
   * 构建公共筛选条件
   */
  private applyFilters(qb: any, query: StatsQuery, alias = 'o') {
    if (query.startTime) {
      qb.andWhere(`${alias}.createTime >= :startTime`, { startTime: query.startTime });
    }
    if (query.endTime) {
      qb.andWhere(`${alias}.createTime <= :endTime`, { endTime: query.endTime });
    }
    if (query.orderType) {
      qb.andWhere(`${alias}.orderType = :orderType`, { orderType: query.orderType });
    }
    if (query.oemId) {
      qb.andWhere(`${alias}.oemId = :oemId`, { oemId: query.oemId });
    }
    if (query.insuranceCompany) {
      qb.andWhere(`${alias}.insuranceCompany = :insuranceCompany`, { insuranceCompany: query.insuranceCompany });
    }
    if (query.productName) {
      qb.andWhere(`${alias}.productName = :productName`, { productName: query.productName });
    }
    if (query.factoryName) {
      qb.andWhere(`${alias}.factoryName = :factoryName`, { factoryName: query.factoryName });
    }
  }

  /**
   * 综合概览数据
   */
  async getOverview(query: StatsQuery) {
    // 基础统计
    const qb = this.auditOrderEntity.createQueryBuilder('o')
      .select([
        'COUNT(*) AS total',
        "SUM(CASE WHEN o.status='approved' THEN 1 ELSE 0 END) AS approved",
        "SUM(CASE WHEN o.status='rejected' THEN 1 ELSE 0 END) AS rejected",
        "SUM(CASE WHEN o.status='manual_review' THEN 1 ELSE 0 END) AS manualReview",
        "SUM(CASE WHEN o.status='processing' THEN 1 ELSE 0 END) AS processing",
        "SUM(CASE WHEN o.status='failed' THEN 1 ELSE 0 END) AS failed",
        'AVG(o.duration) AS avgDuration',
        "SUM(CAST(IFNULL(o.policyFee,'0') AS DECIMAL(12,2))) AS totalPolicyFee",
        "SUM(CAST(IFNULL(o.fee,'0') AS DECIMAL(12,2))) AS totalSalesAmount",
        "SUM(CASE WHEN o.orderType='insure' THEN 1 ELSE 0 END) AS insureCount",
        "SUM(CASE WHEN o.orderType='claim' THEN 1 ELSE 0 END) AS claimCount",
      ]);
    this.applyFilters(qb, query);
    const raw = await qb.getRawOne();

    const total = parseInt(raw.total) || 0;
    const approved = parseInt(raw.approved) || 0;
    const insureApproved = approved; // 目前只有投保
    const claimCount = parseInt(raw.claimCount) || 0;

    // 平均保费（仅投保通过的）
    const avgQb = this.auditOrderEntity.createQueryBuilder('o')
      .select("AVG(CAST(IFNULL(o.policyFee,'0') AS DECIMAL(12,2)))", 'avgPolicyFee')
      .where("o.orderType = 'insure'")
      .andWhere("o.status = 'approved'")
      .andWhere("o.policyFee IS NOT NULL");
    this.applyFilters(avgQb, query);
    const avgRaw = await avgQb.getRawOne();

    // 每日趋势（跟随筛选时间范围，无时间范围时默认近30天）
    const trendQb = this.auditOrderEntity.createQueryBuilder('o')
      .select([
        'DATE(o.createTime) AS date',
        'COUNT(*) AS count',
        "SUM(CASE WHEN o.status='approved' THEN 1 ELSE 0 END) AS approved",
        "SUM(CASE WHEN o.status='rejected' THEN 1 ELSE 0 END) AS rejected",
        "SUM(CAST(IFNULL(o.policyFee,'0') AS DECIMAL(12,2))) AS policyFee",
      ]);
    if (!query.startTime && !query.endTime) {
      trendQb.where('o.createTime >= DATE_SUB(NOW(), INTERVAL 30 DAY)');
    }
    this.applyFilters(trendQb, query);
    trendQb.groupBy('DATE(o.createTime)').orderBy('date', 'ASC');
    const trendRaw = await trendQb.getRawMany();

    // 满期赔付率计算
    // 满期保费 = serviceEnd < 当前日期 的投保订单 policyFee 总和
    // 赔款 = 关联满期保单(通过relatedPolicyNo)的理赔订单 claimAmount 总和
    const lossRatio = await this.calcLossRatio(query);

    return {
      total,
      approved,
      rejected: parseInt(raw.rejected) || 0,
      manualReview: parseInt(raw.manualReview) || 0,
      processing: parseInt(raw.processing) || 0,
      failed: parseInt(raw.failed) || 0,
      passRate: total > 0 ? (approved / total * 100).toFixed(1) : '0',
      avgDuration: Math.round(parseFloat(raw.avgDuration) || 0),
      totalPolicyFee: parseFloat(raw.totalPolicyFee) || 0,
      totalSalesAmount: parseFloat(raw.totalSalesAmount) || 0,
      avgPolicyFee: parseFloat(avgRaw?.avgPolicyFee) || 0,
      insureCount: parseInt(raw.insureCount) || 0,
      claimCount,
      claimRate: claimCount > 0 && insureApproved > 0
        ? (claimCount / insureApproved * 100).toFixed(1)
        : '--',
      lossRatio,
      dailyTrend: trendRaw.map(r => ({
        date: r.date,
        count: parseInt(r.count) || 0,
        approved: parseInt(r.approved) || 0,
        rejected: parseInt(r.rejected) || 0,
        policyFee: parseFloat(r.policyFee) || 0,
      })),
    };
  }

  /**
   * 计算满期赔付率
   * 公式: (已决赔款 + 未决赔款) / 满期保费 × 100%
   * - 满期保费: serviceEnd < NOW() 的投保订单 policyFee 总和
   * - 已决赔款: 关联满期保单的已完成理赔(approved) claimAmount 总和
   * - 未决赔款: 关联满期保单的处理中理赔(processing/pending) claimAmount 总和
   */
  private async calcLossRatio(query: StatsQuery): Promise<string> {
    // 1. 满期保费
    const premiumQb = this.auditOrderEntity.createQueryBuilder('o')
      .select("SUM(CAST(IFNULL(o.policyFee,'0') AS DECIMAL(12,2)))", 'earnedPremium')
      .where("o.orderType = 'insure'")
      .andWhere("o.serviceEnd IS NOT NULL")
      .andWhere("o.serviceEnd != ''")
      .andWhere('o.serviceEnd < NOW()');
    this.applyFilters(premiumQb, query);
    const premiumRaw = await premiumQb.getRawOne();
    const earnedPremium = parseFloat(premiumRaw?.earnedPremium) || 0;
    if (earnedPremium <= 0) return '--';

    // 2. 已决赔款 + 未决赔款（通过 relatedPolicyNo 关联满期保单）
    const claimQb = this.auditOrderEntity.createQueryBuilder('c')
      .select('SUM(IFNULL(c.claimAmount, 0))', 'totalClaim')
      .where("c.orderType = 'claim'")
      .andWhere("c.status IN ('approved', 'processing', 'pending')")
      .andWhere(qb => {
        const subQuery = qb.subQuery()
          .select('p.policyNo')
          .from(AuditOrderEntity, 'p')
          .where("p.orderType = 'insure'")
          .andWhere("p.serviceEnd IS NOT NULL")
          .andWhere("p.serviceEnd != ''")
          .andWhere('p.serviceEnd < NOW()')
          .getQuery();
        return `c.relatedPolicyNo IN ${subQuery}`;
      });
    // 对理赔订单也应用筛选（主机厂、保险公司等）
    if (query.oemId) {
      claimQb.andWhere('c.oemId = :oemId', { oemId: query.oemId });
    }
    if (query.insuranceCompany) {
      claimQb.andWhere('c.insuranceCompany = :insuranceCompany', { insuranceCompany: query.insuranceCompany });
    }
    const claimRaw = await claimQb.getRawOne();
    const totalClaim = parseFloat(claimRaw?.totalClaim) || 0;

    return (totalClaim / earnedPremium * 100).toFixed(1);
  }

  /**
   * 通用维度统计
   */
  private async statsByDimension(query: StatsQuery, field: string, nameAlias = 'name') {
    const qb = this.auditOrderEntity.createQueryBuilder('o')
      .select([
        `o.${field} AS ${nameAlias}`,
        'COUNT(*) AS orderCount',
        "SUM(CASE WHEN o.status='approved' THEN 1 ELSE 0 END) AS approvedCount",
        "SUM(CASE WHEN o.status='rejected' THEN 1 ELSE 0 END) AS rejectedCount",
        "SUM(CAST(IFNULL(o.policyFee,'0') AS DECIMAL(12,2))) AS totalPolicyFee",
        "SUM(CAST(IFNULL(o.fee,'0') AS DECIMAL(12,2))) AS totalFee",
        'AVG(o.duration) AS avgDuration',
      ])
      .where(`o.${field} IS NOT NULL`)
      .andWhere(`o.${field} != ''`);
    this.applyFilters(qb, query);
    qb.groupBy(`o.${field}`).orderBy('orderCount', 'DESC');
    const rows = await qb.getRawMany();

    return rows.map(r => {
      const orderCount = parseInt(r.orderCount) || 0;
      const approvedCount = parseInt(r.approvedCount) || 0;
      return {
        name: r[nameAlias],
        orderCount,
        approvedCount,
        rejectedCount: parseInt(r.rejectedCount) || 0,
        passRate: orderCount > 0 ? (approvedCount / orderCount * 100).toFixed(1) : '0',
        totalPolicyFee: parseFloat(r.totalPolicyFee) || 0,
        totalFee: parseFloat(r.totalFee) || 0,
        avgDuration: Math.round(parseFloat(r.avgDuration) || 0),
      };
    });
  }

  /** 按产品统计 */
  async statsByProduct(query: StatsQuery) {
    return this.statsByDimension(query, 'productName');
  }

  /** 按门店统计 */
  async statsByDealer(query: StatsQuery) {
    return this.statsByDimension(query, 'factoryName');
  }

  /** 按车企统计 */
  async statsByOem(query: StatsQuery) {
    const qb = this.auditOrderEntity.createQueryBuilder('o')
      .select([
        'o.oemId AS code',
        'o.oemName AS name',
        'COUNT(*) AS orderCount',
        "SUM(CASE WHEN o.status='approved' THEN 1 ELSE 0 END) AS approvedCount",
        "SUM(CASE WHEN o.status='rejected' THEN 1 ELSE 0 END) AS rejectedCount",
        "SUM(CAST(IFNULL(o.policyFee,'0') AS DECIMAL(12,2))) AS totalPolicyFee",
        "SUM(CAST(IFNULL(o.fee,'0') AS DECIMAL(12,2))) AS totalFee",
        'AVG(o.duration) AS avgDuration',
      ])
      .where('o.oemId IS NOT NULL');
    this.applyFilters(qb, query);
    qb.groupBy('o.oemId').addGroupBy('o.oemName').orderBy('orderCount', 'DESC');
    const rows = await qb.getRawMany();

    return rows.map(r => {
      const orderCount = parseInt(r.orderCount) || 0;
      const approvedCount = parseInt(r.approvedCount) || 0;
      return {
        name: r.name || `主机厂${r.code}`,
        code: r.code?.toString(),
        orderCount,
        approvedCount,
        rejectedCount: parseInt(r.rejectedCount) || 0,
        passRate: orderCount > 0 ? (approvedCount / orderCount * 100).toFixed(1) : '0',
        totalPolicyFee: parseFloat(r.totalPolicyFee) || 0,
        totalFee: parseFloat(r.totalFee) || 0,
        avgDuration: Math.round(parseFloat(r.avgDuration) || 0),
      };
    });
  }

  /** 按保险公司统计 */
  async statsByInsurance(query: StatsQuery) {
    return this.statsByDimension(query, 'insuranceCompany');
  }

  /** 获取筛选下拉选项（主机厂、保险公司、订单来源数量少，全量返回） */
  async getFilterOptions() {
    const [oems, insurances, orderSources] = await Promise.all([
      this.auditOrderEntity.createQueryBuilder('o')
        .select('DISTINCT o.oemId', 'id')
        .addSelect('o.oemName', 'name')
        .where('o.oemId IS NOT NULL')
        .getRawMany(),
      this.auditOrderEntity.createQueryBuilder('o')
        .select('DISTINCT o.insuranceCompany', 'name')
        .where('o.insuranceCompany IS NOT NULL')
        .andWhere("o.insuranceCompany != ''")
        .getRawMany(),
      this.auditOrderEntity.createQueryBuilder('o')
        .select('DISTINCT o.orderSource', 'name')
        .where('o.orderSource IS NOT NULL')
        .andWhere("o.orderSource != ''")
        .getRawMany(),
    ]);

    return {
      oems: oems.map(r => ({ id: r.id, name: r.name || `主机厂${r.id}` })),
      insurances: insurances.map(r => r.name).filter(Boolean),
      orderSources: orderSources.map(r => r.name).filter(Boolean),
    };
  }

  /** 远程搜索门店（关键词模糊匹配，最多返回50条） */
  async searchDealers(keyword: string) {
    const qb = this.auditOrderEntity.createQueryBuilder('o')
      .select('DISTINCT o.factoryName', 'name')
      .addSelect('o.dealerCode', 'code')
      .where('o.factoryName IS NOT NULL')
      .andWhere("o.factoryName != ''");
    if (keyword) {
      qb.andWhere('o.factoryName LIKE :kw', { kw: `%${keyword}%` });
    }
    qb.limit(50);
    const rows = await qb.getRawMany();
    return rows.map(r => ({ name: r.name, code: r.code })).filter(r => r.name);
  }

  /** 远程搜索产品（关键词模糊匹配，最多返回50条） */
  async searchProducts(keyword: string) {
    const qb = this.auditOrderEntity.createQueryBuilder('o')
      .select('DISTINCT o.productName', 'name')
      .addSelect('o.productNo', 'code')
      .where('o.productName IS NOT NULL')
      .andWhere("o.productName != ''");
    if (keyword) {
      qb.andWhere('o.productName LIKE :kw', { kw: `%${keyword}%` });
    }
    qb.limit(50);
    const rows = await qb.getRawMany();
    return rows.map(r => ({ name: r.name, code: r.code })).filter(r => r.name);
  }

  /** 导出数据（返回指定维度的全量数据） */
  async exportData(query: StatsQuery, dimension: string) {
    switch (dimension) {
      case 'product': return this.statsByProduct(query);
      case 'dealer': return this.statsByDealer(query);
      case 'oem': return this.statsByOem(query);
      case 'insurance': return this.statsByInsurance(query);
      default: return [];
    }
  }
}
