import { Injectable, Logger, Inject } from '@nestjs/common';
import { DashboardPeriod, DashboardPeriodDays } from '../../domain/value-objects';
import {
  DashboardStatItemDto,
  DashboardStatsResponseDto,
} from '../../api/dto/response/dashboard-stats.dto';
import {
  DashboardTrendDataDto,
  DashboardTrendResponseDto,
  TrendDataPointDto,
} from '../../api/dto/response/dashboard-trend.dto';
import {
  DashboardActivityItemDto,
  DashboardActivitiesResponseDto,
  ActivityType,
} from '../../api/dto/response/dashboard-activity.dto';
import {
  RegionDistributionItemDto,
  DashboardRegionResponseDto,
} from '../../api/dto/response/dashboard-region.dto';
import {
  IDashboardStatsSnapshotRepository,
  IDashboardTrendDataRepository,
  ISystemActivityRepository,
  IRealtimeStatsRepository,
  IGlobalStatsRepository,
  DASHBOARD_STATS_SNAPSHOT_REPOSITORY,
  DASHBOARD_TREND_DATA_REPOSITORY,
  SYSTEM_ACTIVITY_REPOSITORY,
  REALTIME_STATS_REPOSITORY,
  GLOBAL_STATS_REPOSITORY,
} from '../../domain/repositories';

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

  constructor(
    @Inject(DASHBOARD_STATS_SNAPSHOT_REPOSITORY)
    private readonly statsSnapshotRepo: IDashboardStatsSnapshotRepository,
    @Inject(DASHBOARD_TREND_DATA_REPOSITORY)
    private readonly trendDataRepo: IDashboardTrendDataRepository,
    @Inject(SYSTEM_ACTIVITY_REPOSITORY)
    private readonly activityRepo: ISystemActivityRepository,
    @Inject(REALTIME_STATS_REPOSITORY)
    private readonly realtimeStatsRepo: IRealtimeStatsRepository,
    @Inject(GLOBAL_STATS_REPOSITORY)
    private readonly globalStatsRepo: IGlobalStatsRepository,
  ) {}

  /**
   * 获取仪表板统计卡片数据
   * 直接从本地 GlobalStats 和 RealtimeStats 表读取（通过 Kafka 事件累加）
   */
  async getStats(): Promise<DashboardStatsResponseDto> {
    this.logger.debug('Fetching dashboard stats from local tables');

    try {
      // 从本地表获取全局统计和今日统计
      const [globalStats, todayStats, yesterdayStats] = await Promise.all([
        this.globalStatsRepo.getGlobalStats(),
        this.realtimeStatsRepo.findByDate(new Date()),
        this.realtimeStatsRepo.findByDate(this.getYesterday()),
      ]);

      // 计算环比变化
      const todayPlanting = todayStats?.dailyPlantingCount || 0;
      const yesterdayPlanting = yesterdayStats?.dailyPlantingCount || 0;
      const plantingChange = this.calculateChangePercent(todayPlanting, yesterdayPlanting);

      const todayNewUsers = todayStats?.dailyNewUserCount || 0;
      const yesterdayNewUsers = yesterdayStats?.dailyNewUserCount || 0;
      const userChange = this.calculateChangePercent(todayNewUsers, yesterdayNewUsers);

      const todayProvinceAuth = todayStats?.dailyProvinceAuthCount || 0;
      const yesterdayProvinceAuth = yesterdayStats?.dailyProvinceAuthCount || 0;
      const provinceChange = this.calculateChangePercent(todayProvinceAuth, yesterdayProvinceAuth);

      const todayCityAuth = todayStats?.dailyCityAuthCount || 0;
      const yesterdayCityAuth = yesterdayStats?.dailyCityAuthCount || 0;
      const cityChange = this.calculateChangePercent(todayCityAuth, yesterdayCityAuth);

      const stats: DashboardStatItemDto[] = [
        {
          title: '总认种量',
          value: globalStats.totalPlantingCount,
          suffix: '棵',
          change: {
            value: Math.abs(plantingChange),
            trend: plantingChange >= 0 ? 'up' : 'down',
          },
          color: '#1565C0',
        },
        {
          title: '总用户数',
          value: globalStats.totalUserCount,
          suffix: '人',
          change: {
            value: Math.abs(userChange),
            trend: userChange >= 0 ? 'up' : 'down',
          },
          color: '#4CAF50',
        },
        {
          title: '省级公司',
          value: globalStats.totalProvinceCompanyCount,
          suffix: '家',
          change: {
            value: Math.abs(provinceChange),
            trend: provinceChange >= 0 ? 'up' : 'down',
          },
          color: '#F5A623',
        },
        {
          title: '市级公司',
          value: globalStats.totalCityCompanyCount,
          suffix: '家',
          change: {
            value: Math.abs(cityChange),
            trend: cityChange >= 0 ? 'up' : 'down',
          },
          color: '#9C27B0',
        },
      ];

      return { stats };
    } catch (error) {
      this.logger.error('Failed to fetch dashboard stats from local tables', error);
      // 返回默认值
      return {
        stats: [
          { title: '总认种量', value: 0, suffix: '棵', change: { value: 0, trend: 'up' }, color: '#1565C0' },
          { title: '总用户数', value: 0, suffix: '人', change: { value: 0, trend: 'up' }, color: '#4CAF50' },
          { title: '省级公司', value: 0, suffix: '家', change: { value: 0, trend: 'up' }, color: '#F5A623' },
          { title: '市级公司', value: 0, suffix: '家', change: { value: 0, trend: 'up' }, color: '#9C27B0' },
        ],
      };
    }
  }

  /**
   * 计算环比变化百分比
   */
  private calculateChangePercent(current: number, previous: number): number {
    if (previous === 0) {
      return current > 0 ? 100 : 0;
    }
    return Math.round(((current - previous) / previous) * 100 * 10) / 10;
  }

  /**
   * 获取昨天的日期
   */
  private getYesterday(): Date {
    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    return yesterday;
  }

  /**
   * 获取趋势图表数据
   * 从 RealtimeStats 表读取每日统计数据，无数据时返回空数组
   */
  async getTrendData(period: DashboardPeriod): Promise<DashboardTrendResponseDto> {
    this.logger.debug(`Fetching dashboard trend data for period: ${period}`);

    const days = DashboardPeriodDays[period];

    // 从 RealtimeStats 获取最近N天的数据
    const realtimeStats = await this.realtimeStatsRepo.findRecentDays(days);

    let data: TrendDataPointDto[];

    if (realtimeStats.length > 0) {
      // 使用真实数据
      data = realtimeStats.map((item) => ({
        date: this.formatDate(item.statsDate),
        value: item.dailyPlantingCount,
      }));
    } else {
      // 如果没有数据，尝试从旧的 trendDataRepo 获取
      const trendData = await this.trendDataRepo.findRecentDays(days);
      if (trendData.length > 0) {
        data = trendData.map((item) => ({
          date: this.formatDate(item.trendDate),
          value: item.plantingCount,
        }));
      } else {
        // 无数据时返回空数组
        data = [];
      }
    }

    return {
      trend: {
        period,
        data,
      },
    };
  }

  /**
   * 获取最近活动数据
   * 从数据库获取真实数据，无数据时返回空数组
   */
  async getActivities(limit: number): Promise<DashboardActivitiesResponseDto> {
    this.logger.debug(`Fetching dashboard activities, limit: ${limit}`);

    // 从数据库获取活动记录
    const dbActivities = await this.activityRepo.findRecent(limit);

    const activities: DashboardActivityItemDto[] = dbActivities.map((activity) => ({
      id: String(activity.id),
      type: activity.activityType as ActivityType,
      icon: activity.icon || '📌',
      title: activity.title,
      description: activity.description,
      timestamp: this.formatRelativeTime(
        Math.floor((Date.now() - (activity.createdAt?.getTime() || Date.now())) / 60000),
      ),
      createdAt: activity.createdAt?.toISOString() || new Date().toISOString(),
    }));

    return { activities };
  }

  /**
   * 记录系统活动
   */
  async recordActivity(
    activityType: ActivityType | string,
    title: string,
    description: string,
    options?: {
      icon?: string;
      relatedUserId?: bigint;
      relatedEntityId?: string;
      relatedEntityType?: string;
      metadata?: Record<string, unknown>;
    },
  ): Promise<void> {
    await this.activityRepo.create({
      activityType,
      title,
      description,
      icon: options?.icon,
      relatedUserId: options?.relatedUserId,
      relatedEntityId: options?.relatedEntityId,
      relatedEntityType: options?.relatedEntityType,
      metadata: options?.metadata,
    });
  }

  /**
   * 获取区域分布数据
   * 无数据时返回空数组
   */
  async getRegionDistribution(): Promise<DashboardRegionResponseDto> {
    this.logger.debug('Fetching region distribution');

    // TODO: 从 planting-service 获取真实区域分布数据
    // 目前无真实数据源，返回空数组
    const regions: RegionDistributionItemDto[] = [];

    return { regions };
  }

  /**
   * 格式化日期为 MM-DD 格式
   */
  private formatDate(date: Date): string {
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${month}-${day}`;
  }

  /**
   * 格式化相对时间
   */
  private formatRelativeTime(minutesAgo: number): string {
    if (minutesAgo < 60) {
      return `${minutesAgo}分钟前`;
    }
    const hoursAgo = Math.floor(minutesAgo / 60);
    if (hoursAgo < 24) {
      return `${hoursAgo}小时前`;
    }
    const daysAgo = Math.floor(hoursAgo / 24);
    return `${daysAgo}天前`;
  }

  /**
   * 获取当月开始日期
   */
  private getStartOfMonth(): Date {
    const now = new Date();
    return new Date(now.getFullYear(), now.getMonth(), 1);
  }

  /**
   * 获取指定日期的开始时间（00:00:00）
   */
  private getStartOfDay(date: Date): Date {
    return new Date(date.getFullYear(), date.getMonth(), date.getDate());
  }
}
