import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Types } from 'mongoose'
import { ModelService } from '../model/model.service';
import Razorpay from "razorpay";
import * as dto from './dto/index';
import { subscription_plan_type } from '../model/schema/subscription.plan';
import { subscription_payment_status } from '../model/schema/subscription.schema';

@Injectable()
export class SubscriptionService {

    protected razorpay: Razorpay;
    constructor(
        private configService: ConfigService,
        private Model: ModelService,
    ) {

        const key_id = this.configService.get<string>("RAZORPAY_KEY_ID")
        const key_secret = this.configService.get<string>("RAZORPAY_KEY_SECRET")
        
        this.razorpay = new Razorpay({
            key_id: process.env.RAZORPAY_KEY_ID,
            key_secret: process.env.RAZORPAY_KEY_SECRET,
        });

    }

    /**
     * Create a new Razorpay plan and save it to MongoDB
     * @param planData
     */
    async create_plan(planData: dto.subscription_plan.create_plan) {
        try {
            const { name, description, amount, period, interval_count, currency, benefits } = planData;

            const amount_in_inr = amount * 100;

            console.log('planData', planData)

            // Create Razorpay plan
            const plan = await this.razorpay.plans.create({
                period: period,
                interval: interval_count,
                item: {
                    name,
                    description,
                    amount: amount_in_inr,
                    currency,
                },
            });

            console.log('plan', plan)

            // Save to DB
            const savedPlan = await this.Model.SubscriptionPlan.create({
                plan_id: plan.id,
                name: plan.item.name,
                description: plan.item.description,
                interval: plan.period,
                interval_count: plan.interval,
                amount: amount, // plan.item.amount,
                currency: plan.item.currency,
                benefits, // Save benefits
            });

            return savedPlan;
        } catch (error) {
            console.error("Error creating plan:", error);
            throw error;
        }
    }


    /**
     * Get a list of plans
     */
    async getPlanList() {
        try {
            const plans = await this.Model.SubscriptionPlan.find({ is_deleted: false });
            return plans;
        } catch (error) {
            console.error("Error fetching plan list:", error.message);
            throw error;
        }
    }

    async purchase_subscription_plan(planData: dto.subscription_plan.purchase_plan, req: any) {
        try {
            const { _id: user_id } = req.user_data;
            const { subscription_plan_id, workspace_id } = planData;

            const subscription_plan = await this.Model.SubscriptionPlan.findOne({ _id: new Types.ObjectId(subscription_plan_id), is_deleted: false })
            if(!subscription_plan) throw new HttpException('Invalid plan selected!', HttpStatus.BAD_REQUEST)

            const subscription_purchased = await this.Model.subscriptionModel.findOne({ 
              subscription_plan_id: new Types.ObjectId(subscription_plan_id),
              workspace_id: new Types.ObjectId(workspace_id), 
              status: "authenticated" 
            });
            if(subscription_purchased) throw new HttpException(`It seems you’ve already purchased or activated a plan. Please check your account for details.`, HttpStatus.BAD_REQUEST)

            const currentTime = Math.floor(new Date().getTime() / 1000); // Current time in seconds
            const expireTime = currentTime + 30 * 24 * 60 * 60; // Add 30 days (30 * 24 hours * 60 mins * 60 secs)

            console.log('currentTime', currentTime)
            console.log('expireTime', expireTime)
            console.log('expire_by', new Date(expireTime))

            const subscription = await this.razorpay.subscriptions.create({
                plan_id: subscription_plan?.plan_id, 
                customer_notify: 1,
                total_count: 1,
                quantity: 1,
                start_at: currentTime + 180, // Start 3 minute from now
                expire_by: expireTime,    // Expiration time (30 days from now)
                notes: {
                    note1: "One-month subscription",
                    plan_name: subscription_plan?.name,
                    workspace_id: workspace_id
                },
            });
            console.log('Subscription created successfully:', subscription);

            if(subscription){
                const subscription_payload = {
                    user_id,
                    workspace_id: new Types.ObjectId(workspace_id),
                    subscription_plan_id: new Types.ObjectId(subscription_plan_id),
                    subscription_id: subscription.id,
                    plan_id: subscription.plan_id,
                    status: subscription.status,
                    start_date: subscription.start_at,
                    end_date: subscription.expire_by,
                    renewal_date: subscription.expire_by,
                    short_url: subscription.short_url,
                    plan_name: subscription_plan?.name,
                    amount:  subscription_plan?.amount,
                    benifites: {
                      chat_token_limit: (subscription_plan?.chat_token_limit * 1000000),
                      tele_duration_limit: (subscription_plan?.call_limit * 60 * 60),
                      voice_duration_limit: (subscription_plan?.call_limit * 60 * 60),
                      knowledgebase_limit: subscription_plan?.knowledgebase_limit,
                      agent_limit: subscription_plan?.agent_limit,
                      workspace_member_limit: subscription_plan?.workspace_member_limit,
                    },
                    chat_token_limit_left: (subscription_plan?.chat_token_limit * 1000000), // in million to token 
                    tele_duration_limit_left: (subscription_plan?.call_limit * 60 * 60), // in seconds
                    voice_duration_limit_left: (subscription_plan?.call_limit * 60 * 60), // in seconds
                    knowledgebase_limit_left: subscription_plan?.knowledgebase_limit,
                    agent_limit_left: subscription_plan?.agent_limit,
                    workspace_member_limit_left: subscription_plan?.workspace_member_limit,
                }
                await this.Model.subscriptionModel.create(subscription_payload);
            }
            
            return {
                id: subscription.id,
                amount: subscription_plan.amount,
                currency: subscription_plan.currency
            }
            
        } catch (error) {
            console.error("Error creating plan:", error);
            throw error;
        }
    }

    /**
     * Get a list of plans with user active plan
     */
    async getPlanListWithActivePlan(req: any, query: dto.subscription_plan.plan_list, workspace_id: string) {
        try {
            const { _id: vendor_id } = req.user_data;
            const { interval } = query;
            const intervalFilter = interval ? { interval: interval } : {};

            const plans = await this.Model.SubscriptionPlan.aggregate([
                {
                  $match: {
                    is_deleted: false,
                    plan_type: { $ne: subscription_plan_type.FREE_TIRE },
                    ...intervalFilter
                  }
                },
                {
                  $lookup: {
                    from: "subscriptions", 
                    let: { subscriptionPlanId: "$_id" }, 
                    pipeline: [
                      {
                        $match: {
                          $expr: {
                            $and: [
                              { $eq: ["$subscription_plan_id", "$$subscriptionPlanId"] }, 
                              // { $eq: ["$user_id", vendor_id] },
                              { $eq: ["$workspace_id", new Types.ObjectId(workspace_id)] },
                              { $eq: ["$status", "authenticated"] } 
                            ]
                          }
                        }
                      }
                    ],
                    as: "subscriptions"
                  }
                },
                {
                  $addFields: {
                    is_plan_active: { $gt: [{ $size: "$subscriptions" }, 0] }
                  }
                },
                {
                  $project: {
                    subscriptions: 0 
                  }
                }
            ]);
            return plans;
        } catch (error) {
            console.error("Error fetching plan list:", error.message);
            throw error;
        }
    }

    /**
     * Update a new Razorpay plan and save it to MongoDB
     * @param planData
     */
    async update_plan(planData: dto.subscription_plan.update_plan, _id: string) {
      try {
          const subscription_plan_id = new Types.ObjectId(_id)
          const { chat_token_limit, call_limit, knowledgebase_limit, agent_limit, workspace_member_limit, benefits } = planData;

          const updatePlan = await this.Model.SubscriptionPlan.findOneAndUpdate(
            { _id: subscription_plan_id },
            {
              ...(chat_token_limit && { chat_token_limit: chat_token_limit }),
              ...(call_limit && { call_limit: call_limit }),
              ...(knowledgebase_limit && { knowledgebase_limit: knowledgebase_limit }),
              ...(agent_limit && { agent_limit: agent_limit }),
              ...(workspace_member_limit && { workspace_member_limit: workspace_member_limit }),
              ...(benefits && benefits.length && { benefits: benefits }),
            }, 
            { lean: true, new: true }
          );

          return updatePlan;
      } catch (error) {
          console.error("Error updating plan:", error);
          throw error;
      }
    }

    async get_active_subscription(workspace_id: string) {
      try {

        const bulk_update = await this.Model.subscriptionModel.updateMany(
          { status: "authenticated", is_active: true },
          { payment_status:  subscription_payment_status.PAYMENT_COMPLETED} 
        )

          const data = await this.Model.subscriptionModel.findOne(
              { 
                  workspace_id: new Types.ObjectId(workspace_id), 
                  payment_status: {
                      $in: [
                          subscription_payment_status.PAYMENT_INITIATED, 
                          subscription_payment_status.PAYMENT_COMPLETED
                      ]
                  }
              },
              {},
              { lean: true }
          );
  
          return data;
      } catch (error) {
          console.error("Error getting subscription:", error);
          throw error;
      }
  }
  

  async payment_initiated_success(subscription_id: string) {
    try {
      const data = await this.Model.subscriptionModel.findOneAndUpdate(
        { subscription_id: subscription_id},
        { payment_status: subscription_payment_status.PAYMENT_INITIATED },
        { new: true, }
      );

      return data;
    } catch (error) {
      console.error("Error getting subscription:", error);
      throw error;
    }
  }
    
}
