/**
 * 统计服务
 * 提供表单使用统计和数据分析功能
 */

import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { RegionId } from '../decorators/region.decorator';
import {
  StatisticsQueryDto,
  StatisticsResponseDto,
  FormStatisticsDto,
  TopFormDto,
  SubmissionTrendDto,
  CategoryDistributionDto,
  TimeRange,
} from '../dto/statistics.dto';

@Injectable()
export class StatisticsService {
  private readonly logger = new Logger(StatisticsService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 获取统计数据
   */
  async getStatistics(
    query: StatisticsQueryDto,
    regionId: RegionId,
  ): Promise<StatisticsResponseDto> {
    this.logger.log(`[getStatistics] 查询统计数据 - region: ${regionId}, timeRange: ${query.timeRange}`);

    // 计算时间范围
    const { startDate, endDate } = this.calculateTimeRange(query);

    // 并行获取各项统计数据
    const [
      stats,
      topForms,
      trends,
      categoryDistribution,
    ] = await Promise.all([
      this.getOverallStatistics(regionId, startDate, endDate, query.category),
      this.getTopForms(regionId, startDate, endDate, query.category),
      this.getSubmissionTrends(regionId, startDate, endDate, query.category),
      this.getCategoryDistribution(regionId, query.category),
    ]);

    return {
      stats,
      topForms,
      trends,
      categoryDistribution,
      timeRange: {
        from: startDate.toISOString(),
        to: endDate.toISOString(),
      },
    };
  }

  /**
   * 计算时间范围
   */
  private calculateTimeRange(query: StatisticsQueryDto): { startDate: Date; endDate: Date } {
    const endDate = query.endDate ? new Date(query.endDate) : new Date();
    let startDate: Date;

    if (query.startDate) {
      startDate = new Date(query.startDate);
    } else {
      startDate = new Date(endDate);
      switch (query.timeRange) {
        case TimeRange.LAST_7_DAYS:
          startDate.setDate(startDate.getDate() - 7);
          break;
        case TimeRange.LAST_30_DAYS:
          startDate.setDate(startDate.getDate() - 30);
          break;
        case TimeRange.LAST_90_DAYS:
          startDate.setDate(startDate.getDate() - 90);
          break;
        case TimeRange.LAST_1_YEAR:
          startDate.setFullYear(startDate.getFullYear() - 1);
          break;
        default:
          startDate.setDate(startDate.getDate() - 30);
      }
    }

    // 设置开始时间为当天 00:00:00
    startDate.setHours(0, 0, 0, 0);
    // 设置结束时间为当天 23:59:59
    endDate.setHours(23, 59, 59, 999);

    return { startDate, endDate };
  }

  /**
   * 获取总体统计
   */
  private async getOverallStatistics(
    regionId: RegionId,
    startDate: Date,
    endDate: Date,
    category?: string,
  ): Promise<FormStatisticsDto> {
    // 构建查询条件
    // v2.0: FormDefinition 无 regionId / deletedAt（见 FORM_ORGANIZATION_ARCHITECTURE.md）
    const formWhere: any = {};
    if (category) {
      formWhere.category = category;
    }

    const instanceWhere: any = {
      regionId,
      deletedAt: null,
      submittedAt: {
        gte: startDate,
        lte: endDate,
      },
    };

    // 获取表单数量统计
    const [totalForms, activeForms, draftForms] = await Promise.all([
      this.prisma.formDefinition.count({ where: formWhere }),
      this.prisma.formDefinition.count({
        where: { ...formWhere, status: 'PUBLISHED' },
      }),
      this.prisma.formDefinition.count({
        where: { ...formWhere, status: 'DRAFT' },
      }),
    ]);

    // 获取提交实例统计
    const instances = await this.prisma.formInstance.findMany({
      where: instanceWhere,
      select: {
        id: true,
        status: true,
        submittedAt: true,
        createdBy: true,
      },
    });

    const totalSubmissions = instances.length;

    // 获取审批实例详情（包含处理时间）
    const approvalInstances = await this.prisma.approvalInstance.findMany({
      where: {
        businessType: 'FORM_INSTANCE',
        businessId: {
          in: instances.map((i: any) => i.id),
        },
      },
      select: {
        businessId: true,
        status: true,
        endTime: true,
        startTime: true,
      },
    });

    // 计算审批通过率
    const completedInstances = approvalInstances.filter(
      (i: any) => i.status === 'COMPLETED' || i.status === 'REJECTED',
    );
    const approvedInstances = approvalInstances.filter((i: any) => i.status === 'COMPLETED');
    const approvalRate = completedInstances.length > 0
      ? Math.round((approvedInstances.length / completedInstances.length) * 100)
      : 0;

    // 计算平均处理时间
    const processingTimes = approvalInstances
      .filter((i: any) => i.endTime && i.startTime)
      .map((i: any) => i.endTime!.getTime() - i.startTime.getTime());
    
    const avgProcessingTimeMs = processingTimes.length > 0
      ? Math.round(processingTimes.reduce((a: number, b: number) => a + b, 0) / processingTimes.length)
      : 0;

    const avgProcessingTime = this.formatProcessingTime(avgProcessingTimeMs);

    // 计算活跃用户数
    const activeUsers = new Set(instances.map((i: any) => i.createdBy)).size;

    return {
      totalSubmissions,
      totalForms,
      activeForms,
      draftForms,
      avgProcessingTime,
      avgProcessingTimeMs,
      approvalRate,
      activeUsers,
    };
  }

  /**
   * 获取热门表单排行
   */
  private async getTopForms(
    regionId: RegionId,
    startDate: Date,
    endDate: Date,
    category?: string,
  ): Promise<TopFormDto[]> {
    // 获取所有表单实例
    const instances = await this.prisma.formInstance.findMany({
      where: {
        regionId,
        deletedAt: null,
        submittedAt: {
          gte: startDate,
          lte: endDate,
        },
      },
      select: {
        id: true,
        formDefinitionId: true,
        submittedAt: true,
        definition: {
          select: {
            id: true,
            name: true,
            key: true,
            slug: true,
            category: true,
          },
        },
      },
    });

    // 按分类筛选
    const filteredInstances = category
      ? instances.filter((i: any) => i.definition.category === category)
      : instances;

    // 按表单分组统计
    const formGroups = new Map<string, {
      formDefinitionId: string;
      formName: string;
      slug: string;
      instanceIds: string[];
    }>();

    filteredInstances.forEach((instance: any) => {
      const key = instance.formDefinitionId;
      if (!formGroups.has(key)) {
        formGroups.set(key, {
          formDefinitionId: instance.formDefinitionId,
          formName: instance.definition.name,
          slug: instance.definition.slug,
          instanceIds: [],
        });
      }
      formGroups.get(key)!.instanceIds.push(instance.id);
    });

    // 获取审批状态
    const allInstanceIds = Array.from(formGroups.values()).flatMap(g => g.instanceIds);
    const approvalInstances = await this.prisma.approvalInstance.findMany({
      where: {
        businessType: 'FORM_INSTANCE',
        businessId: {
          in: allInstanceIds,
        },
      },
      select: {
        businessId: true,
        status: true,
        endTime: true,
        startTime: true,
      },
    });

    const approvalMap = new Map(
      approvalInstances.map((a: any) => [a.businessId, a]),
    );

    // 计算每个表单的统计数据
    const topForms: TopFormDto[] = Array.from(formGroups.values()).map(group => {
      const submissions = group.instanceIds.length;
      const approvals = group.instanceIds.filter(
        (id: string) => approvalMap.get(id)?.status === 'COMPLETED',
      ).length;
      const rejections = group.instanceIds.filter(
        (id: string) => approvalMap.get(id)?.status === 'REJECTED',
      ).length;

      const completedCount = approvals + rejections;
      const approvalRate = completedCount > 0
        ? Math.round((approvals / completedCount) * 100)
        : 0;

      // 计算平均处理时间
      const processingTimes = group.instanceIds
        .map((id: string) => approvalMap.get(id))
        .filter((a: any) => a?.endTime && a?.startTime)
        .map((a: any) => a!.endTime!.getTime() - a!.startTime.getTime());

      const avgProcessingTime = processingTimes.length > 0
        ? Math.round(processingTimes.reduce((a: number, b: number) => a + b, 0) / processingTimes.length)
        : 0;

      return {
        formDefinitionId: group.formDefinitionId,
        formName: group.formName,
        slug: group.slug,
        submissions,
        approvals,
        rejections,
        approvalRate,
        avgProcessingTime,
      };
    });

    // 按提交次数排序，取前10
    return topForms.sort((a, b) => b.submissions - a.submissions).slice(0, 10);
  }

  /**
   * 获取提交趋势
   */
  private async getSubmissionTrends(
    regionId: RegionId,
    startDate: Date,
    endDate: Date,
    category?: string,
  ): Promise<SubmissionTrendDto[]> {
    // 获取所有实例
    const instances = await this.prisma.formInstance.findMany({
      where: {
        regionId,
        deletedAt: null,
        submittedAt: {
          gte: startDate,
          lte: endDate,
        },
      },
      select: {
        id: true,
        submittedAt: true,
        definition: {
          select: {
            category: true,
          },
        },
      },
    });

    // 按分类筛选
    const filteredInstances = category
      ? instances.filter((i: any) => i.definition.category === category)
      : instances;

    // 获取审批状态
    const approvalInstances = await this.prisma.approvalInstance.findMany({
      where: {
        businessType: 'FORM_INSTANCE',
        businessId: {
          in: filteredInstances.map((i: any) => i.id),
        },
      },
      select: {
        businessId: true,
        status: true,
      },
    });

    const approvalMap = new Map(
      approvalInstances.map((a: any) => [a.businessId, a.status]),
    );

    // 按日期分组
    const dateGroups = new Map<string, {
      submissions: number;
      approvals: number;
      rejections: number;
    }>();

    filteredInstances.forEach((instance: any) => {
      const date = instance.submittedAt!.toISOString().split('T')[0];
      if (!dateGroups.has(date)) {
        dateGroups.set(date, { submissions: 0, approvals: 0, rejections: 0 });
      }
      const group = dateGroups.get(date)!;
      group.submissions++;

      const status = approvalMap.get(instance.id);
      if (status === 'COMPLETED') {
        group.approvals++;
      } else if (status === 'REJECTED') {
        group.rejections++;
      }
    });

    // 填充所有日期(包括没有数据的日期)
    const trends: SubmissionTrendDto[] = [];
    const currentDate = new Date(startDate);
    while (currentDate <= endDate) {
      const dateStr = currentDate.toISOString().split('T')[0];
      const data = dateGroups.get(dateStr) || { submissions: 0, approvals: 0, rejections: 0 };
      trends.push({
        date: dateStr,
        ...data,
      });
      currentDate.setDate(currentDate.getDate() + 1);
    }

    return trends;
  }

  /**
   * 获取分类分布
   * v2.0: FormDefinition 无 regionId / deletedAt 字段（见 FORM_ORGANIZATION_ARCHITECTURE.md）。
   * 区域过滤通过 organization → organizationRegions 间接做；本接口给管理员统计用，
   * 不按区域过滤（admin 视角应看全量）。
   */
  private async getCategoryDistribution(
    _regionId: RegionId,
    categoryFilter?: string,
  ): Promise<CategoryDistributionDto[]> {
    const where: any = {
      status: 'PUBLISHED',
    };

    if (categoryFilter) {
      where.category = categoryFilter;
    }

    const forms = await this.prisma.formDefinition.findMany({
      where,
      select: {
        category: true,
      },
    });

    // 统计每个分类的数量
    const categoryMap = new Map<string, number>();
    forms.forEach((form: any) => {
      const category = form.category || '未分类';
      categoryMap.set(category, (categoryMap.get(category) || 0) + 1);
    });

    const total = forms.length;
    const distribution: CategoryDistributionDto[] = Array.from(categoryMap.entries())
      .map(([category, count]) => ({
        category,
        count,
        percentage: total > 0 ? Math.round((count / total) * 100) : 0,
      }))
      .sort((a, b) => b.count - a.count);

    return distribution;
  }

  /**
   * 格式化处理时间
   */
  private formatProcessingTime(milliseconds: number): string {
    if (milliseconds === 0) {
      return '< 1 分钟';
    }

    const hours = Math.floor(milliseconds / 3600000);
    const minutes = Math.floor((milliseconds % 3600000) / 60000);

    if (hours > 0) {
      if (minutes > 0) {
        return `${hours}.${Math.floor(minutes / 6)} 小时`;
      }
      return `${hours} 小时`;
    } else if (minutes > 0) {
      return `${minutes} 分钟`;
    } else {
      return '< 1 分钟';
    }
  }
}

