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

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

  constructor(
    @InjectRepository(Subscription)
    private subscriptionRepository: Repository<Subscription>,
    @InjectRepository(User)
    private userRepository: Repository<User>,
    @InjectRepository(Payment)
    private paymentRepository: Repository<Payment>,
    private paymentService: PaymentService,
  ) {}

  /**
   * 创建订阅
   * @param userId 用户ID
   * @param plan 订阅计划
   * @param billingCycle 计费周期
   * @returns 订阅信息
   */
  async createSubscription(
    userId: string,
    plan: 'free' | 'professional' | 'enterprise',
    billingCycle: 'monthly' | 'yearly',
  ): Promise<Subscription> {
    try {
      // 检查用户是否存在
      const user = await this.userRepository.findOne({
        where: { id: userId },
      });

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

      // 计算价格
      const prices = {
        professional: {
          monthly: 999,
          yearly: 9990,
        },
        enterprise: {
          monthly: 2999,
          yearly: 29990,
        },
      };

      const price = plan === 'free' ? 0 : prices[plan][billingCycle];

      // 计算订阅结束时间
      const startDate = new Date();
      const endDate = new Date();
      if (billingCycle === 'monthly') {
        endDate.setMonth(endDate.getMonth() + 1);
      } else {
        endDate.setFullYear(endDate.getFullYear() + 1);
      }

      // 创建订阅
      const subscription = this.subscriptionRepository.create({
        id: uuidv4(),
        userId,
        plan,
        billingCycle,
        price,
        startDate,
        endDate,
        status: 'active',
        createdAt: new Date(),
        updatedAt: new Date(),
      });

      await this.subscriptionRepository.save(subscription);

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

  /**
   * 获取用户订阅信息
   * @param userId 用户ID
   * @returns 订阅信息
   */
  async getSubscriptionByUserId(userId: string): Promise<Subscription | null> {
    try {
      const subscription = await this.subscriptionRepository.findOne({
        where: { userId, status: 'active' },
        order: { createdAt: 'DESC' },
      });

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

  /**
   * 更新订阅
   * @param subscriptionId 订阅ID
   * @param plan 新计划
   * @param billingCycle 新计费周期
   * @returns 更新后的订阅信息
   */
  async updateSubscription(
    subscriptionId: string,
    plan: 'free' | 'professional' | 'enterprise',
    billingCycle: 'monthly' | 'yearly',
  ): Promise<Subscription> {
    try {
      const subscription = await this.subscriptionRepository.findOne({
        where: { id: subscriptionId },
      });

      if (!subscription) {
        throw new NotFoundException('Subscription not found');
      }

      // 计算新价格
      const prices = {
        professional: {
          monthly: 999,
          yearly: 9990,
        },
        enterprise: {
          monthly: 2999,
          yearly: 29990,
        },
      };

      const price = plan === 'free' ? 0 : prices[plan][billingCycle];

      // 更新订阅信息
      subscription.plan = plan;
      subscription.billingCycle = billingCycle;
      subscription.price = price;
      subscription.updatedAt = new Date();

      await this.subscriptionRepository.save(subscription);

      this.logger.log(`Updated subscription ${subscriptionId}: ${plan} plan, ${billingCycle} billing`);
      return subscription;
    } catch (error) {
      this.logger.error('Failed to update subscription', error);
      throw error;
    }
  }

  /**
   * 取消订阅
   * @param subscriptionId 订阅ID
   * @returns 取消结果
   */
  async cancelSubscription(subscriptionId: string): Promise<boolean> {
    try {
      const subscription = await this.subscriptionRepository.findOne({
        where: { id: subscriptionId },
      });

      if (!subscription) {
        throw new NotFoundException('Subscription not found');
      }

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

      subscription.status = 'cancelled';
      subscription.updatedAt = new Date();

      await this.subscriptionRepository.save(subscription);

      this.logger.log(`Cancelled subscription: ${subscriptionId}`);
      return true;
    } catch (error) {
      this.logger.error('Failed to cancel subscription', error);
      throw error;
    }
  }

  /**
   * 处理订阅续费
   * @param subscriptionId 订阅ID
   * @returns 续费结果
   */
  async renewSubscription(subscriptionId: string): Promise<Subscription> {
    try {
      const subscription = await this.subscriptionRepository.findOne({
        where: { id: subscriptionId },
      });

      if (!subscription) {
        throw new NotFoundException('Subscription not found');
      }

      // 计算新的结束时间
      const endDate = new Date(subscription.endDate);
      if (subscription.billingCycle === 'monthly') {
        endDate.setMonth(endDate.getMonth() + 1);
      } else {
        endDate.setFullYear(endDate.getFullYear() + 1);
      }

      // 更新订阅信息
      subscription.endDate = endDate;
      subscription.updatedAt = new Date();

      await this.subscriptionRepository.save(subscription);

      // 创建支付记录
      const payment = this.paymentRepository.create({
        id: uuidv4(),
        userId: subscription.userId,
        subscriptionId: subscription.id,
        amount: subscription.price,
        status: 'completed',
        paymentMethod: 'credit_card',
        transactionId: uuidv4(),
        createdAt: new Date(),
      });

      await this.paymentRepository.save(payment);

      this.logger.log(`Renewed subscription: ${subscriptionId}`);
      return subscription;
    } catch (error) {
      this.logger.error('Failed to renew subscription', error);
      throw error;
    }
  }

  /**
   * 检查订阅状态
   * @param userId 用户ID
   * @returns 订阅状态
   */
  async checkSubscriptionStatus(userId: string): Promise<{
    isActive: boolean;
    subscription?: Subscription;
    daysRemaining?: number;
  }> {
    try {
      const subscription = await this.subscriptionRepository.findOne({
        where: { userId, status: 'active' },
      });

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

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

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

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

  /**
   * 清理过期订阅
   * @returns 清理结果
   */
  async cleanExpiredSubscriptions(): Promise<number> {
    try {
      const now = new Date();
      const expiredSubscriptions = await this.subscriptionRepository.find({
        where: {
          status: 'active',
          endDate: { lessThan: now },
        },
      });

      for (const subscription of expiredSubscriptions) {
        subscription.status = 'expired';
        subscription.updatedAt = new Date();
        await this.subscriptionRepository.save(subscription);
      }

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