import { Injectable, Logger, BadRequestException, NotFoundException } from '@nestjs/common';
import { Subscription, SubscriptionEntity } from '../entities/Subscription';
import { User, UserEntity } from '../entities/User';
import { Payment, PaymentEntity } from '../entities/Payment';
import { v4 as uuidv4 } from 'uuid';
import db from '../../config/database';

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

  async createSubscription(
    userId: string,
    plan: 'free' | 'basic' | 'pro' | 'enterprise',
    billingCycle: 'monthly' | 'yearly',
  ): Promise<Subscription> {
    try {
      const user = await db('cf_user').where('id', userId).first();
      if (!user) {
        throw new NotFoundException('User not found');
      }

      const prices: Record<string, Record<string, number>> = {
        basic: { monthly: 29, yearly: 290 },
        pro: { monthly: 99, yearly: 990 },
        enterprise: { monthly: 299, yearly: 2990 },
      };

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

      const startDate = new Date();
      const endDate = new Date();
      if (billingCycle === 'monthly') {
        endDate.setMonth(endDate.getMonth() + 1);
      } else {
        endDate.setFullYear(endDate.getFullYear() + 1);
      }

      const subscriptionId = uuidv4();
      await db('cf_subscription').insert({
        id: subscriptionId,
        userId,
        tenantId: user.tenantId,
        plan,
        status: 'active',
        startDate,
        endDate,
        autoRenew: true,
        createdAt: new Date(),
        updatedAt: new Date()
      });

      this.logger.log(`Created subscription for user ${userId}: ${plan} plan`);
      return SubscriptionEntity.create({
        id: subscriptionId,
        userId,
        tenantId: user.tenantId,
        plan,
        status: 'active',
        startDate,
        endDate,
        autoRenew: true
      });
    } catch (error) {
      this.logger.error('Failed to create subscription', error);
      throw error;
    }
  }

  async getSubscriptionByUserId(userId: string): Promise<Subscription | null> {
    try {
      const subscription = await db('cf_subscription')
        .where('userId', userId)
        .where('status', 'active')
        .orderBy('createdAt', 'desc')
        .first();
      return subscription ? SubscriptionEntity.create(subscription) : null;
    } catch (error) {
      this.logger.error('Failed to get subscription', error);
      throw error;
    }
  }

  async updateSubscription(
    subscriptionId: string,
    plan: 'free' | 'basic' | 'pro' | 'enterprise',
    billingCycle: 'monthly' | 'yearly',
  ): Promise<Subscription> {
    try {
      const subscription = await db('cf_subscription').where('id', subscriptionId).first();
      if (!subscription) {
        throw new NotFoundException('Subscription not found');
      }

      await db('cf_subscription').where('id', subscriptionId).update({
        plan,
        updatedAt: new Date()
      });

      return SubscriptionEntity.create({ ...subscription, plan });
    } catch (error) {
      this.logger.error('Failed to update subscription', error);
      throw error;
    }
  }

  async cancelSubscription(subscriptionId: string): Promise<boolean> {
    try {
      const subscription = await db('cf_subscription').where('id', subscriptionId).first();
      if (!subscription) {
        throw new NotFoundException('Subscription not found');
      }

      await db('cf_subscription').where('id', subscriptionId).update({
        status: 'cancelled',
        updatedAt: new Date()
      });

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

  async checkSubscriptionStatus(userId: string): Promise<{
    isActive: boolean;
    subscription?: Subscription;
    daysRemaining?: number;
  }> {
    try {
      const subscription = await db('cf_subscription')
        .where('userId', userId)
        .where('status', 'active')
        .first();

      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) {
        await db('cf_subscription').where('id', subscription.id).update({
          status: 'expired',
          updatedAt: new Date()
        });
        return { isActive: false };
      }

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