import { Injectable, Logger, BadRequestException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Trial } from '../entities/Trial';
import { User } from '../entities/User';
import { v4 as uuidv4 } from 'uuid';

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

  constructor(
    @InjectRepository(Trial)
    private trialRepository: Repository<Trial>,
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}

  /**
   * 创建试用
   * @param userId 用户ID
   * @param plan 试用计划
   * @returns 试用信息
   */
  async createTrial(userId: string, plan: 'professional' | 'enterprise'): Promise<Trial> {
    try {
      // 检查用户是否存在
      const user = await this.userRepository.findOne({
        where: { id: userId },
      });

      if (!user) {
        throw new NotFoundException('User not found');
      }

      // 检查用户是否已有试用
      const existingTrial = await this.trialRepository.findOne({
        where: { userId, status: 'active' },
      });

      if (existingTrial) {
        throw new BadRequestException('User already has an active trial');
      }

      // 计算试用结束时间（14天）
      const startDate = new Date();
      const endDate = new Date();
      endDate.setDate(endDate.getDate() + 14);

      // 创建试用
      const trial = this.trialRepository.create({
        id: uuidv4(),
        userId,
        plan,
        startDate,
        endDate,
        status: 'active',
        createdAt: new Date(),
        updatedAt: new Date(),
      });

      await this.trialRepository.save(trial);

      this.logger.log(`Created trial for user ${userId}: ${plan} plan`);
      return trial;
    } catch (error) {
      this.logger.error('Failed to create trial', error);
      throw error;
    }
  }

  /**
   * 获取用户试用信息
   * @param userId 用户ID
   * @returns 试用信息
   */
  async getTrialByUserId(userId: string): Promise<Trial | null> {
    try {
      const trial = await this.trialRepository.findOne({
        where: { userId },
        order: { createdAt: 'DESC' },
      });

      return trial;
    } catch (error) {
      this.logger.error('Failed to get trial', error);
      throw error;
    }
  }

  /**
   * 结束试用
   * @param trialId 试用ID
   * @returns 结束结果
   */
  async endTrial(trialId: string): Promise<boolean> {
    try {
      const trial = await this.trialRepository.findOne({
        where: { id: trialId },
      });

      if (!trial) {
        throw new NotFoundException('Trial not found');
      }

      if (trial.status !== 'active') {
        throw new BadRequestException('Trial is not active');
      }

      trial.status = 'ended';
      trial.updatedAt = new Date();

      await this.trialRepository.save(trial);

      this.logger.log(`Ended trial: ${trialId}`);
      return true;
    } catch (error) {
      this.logger.error('Failed to end trial', error);
      throw error;
    }
  }

  /**
   * 检查试用状态
   * @param userId 用户ID
   * @returns 试用状态
   */
  async checkTrialStatus(userId: string): Promise<{
    isActive: boolean;
    trial?: Trial;
    daysRemaining?: number;
  }> {
    try {
      const trial = await this.trialRepository.findOne({
        where: { userId, status: 'active' },
      });

      if (!trial) {
        return { isActive: false };
      }

      // 计算剩余天数
      const now = new Date();
      const endDate = new Date(trial.endDate);
      const daysRemaining = Math.ceil((endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));

      // 检查是否过期
      if (daysRemaining < 0) {
        trial.status = 'expired';
        trial.updatedAt = new Date();
        await this.trialRepository.save(trial);
        return { isActive: false };
      }

      return {
        isActive: true,
        trial,
        daysRemaining,
      };
    } catch (error) {
      this.logger.error('Failed to check trial status', error);
      throw error;
    }
  }

  /**
   * 清理过期试用
   * @returns 清理结果
   */
  async cleanExpiredTrials(): Promise<number> {
    try {
      const now = new Date();
      const expiredTrials = await this.trialRepository.find({
        where: {
          status: 'active',
          endDate: { lessThan: now },
        },
      });

      for (const trial of expiredTrials) {
        trial.status = 'expired';
        trial.updatedAt = new Date();
        await this.trialRepository.save(trial);
      }

      this.logger.log(`Cleaned ${expiredTrials.length} expired trials`);
      return expiredTrials.length;
    } catch (error) {
      this.logger.error('Failed to clean expired trials', error);
      throw error;
    }
  }
}
