import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { responseMessages } from '../../messages/response-messages';
import { Industries } from "../../entities/industries.entity";
import { Plan } from 'src/entities/plan.entity';
import { PlanPermission } from 'src/entities/plan-permission.entity';
import { StripeServices } from 'src/common/services/payment-gateway/stripe/stripe.service';

@Injectable()
export class PlanRepository {
    constructor(
        private stripeService: StripeServices,
        @InjectRepository(Plan)
        private Plan: Repository<Plan>,
        @InjectRepository(PlanPermission)
        private PlanPermission: Repository<PlanPermission>,
    ) { }

    async createPlan(planData: any) {
        const insertPriority = planData.priority ?? 1;

        // Step 1: Shift up priorities of existing plans >= new plan's priority

        const plan = await this.Plan.save(planData);
        if (plan) {
            let planPermission = [];
            let cnt = 1;
            for (const permission of planData.permissions) {
                planPermission.push({
                    order_by: cnt,
                    plan_id: plan,
                    "feature_name": permission.feature_name,
                    "description": permission.description,
                    "type": permission.type,
                    "limits": permission.limits,
                    "time_period": permission.time_period
                })
                cnt++
            }
            await this.PlanPermission.save(planPermission);
            await this.reorderPlanPriorities();
            this.updateCustomerBillingPortal();
            return true;
        }
        throw new HttpException(responseMessages.en.plan.plan_error, HttpStatus.BAD_REQUEST);
    }

    async updateCustomerBillingPortal() {
        const plans = await this.Plan.find({ where: { plan_type: 'premium', status: true } });
        let productPrice = [];
        for (const plan of plans) {
            productPrice.push({
                "product": plan.product_id,
                "prices": [plan.year_price_id, plan.month_price_id]
            })
        }
        await this.stripeService.updateCustomerBillingPortal(productPrice);
        return true;
    }


    async updatePlan(planData: any) {

        const plan = await this.Plan.save(planData);
        if (plan) {
            await this.PlanPermission.delete({ plan: plan });
            let planPermission = [];
            let cnt = 1;
            for (const permission of planData.permissions) {
                planPermission.push({
                    order_by: cnt++,
                    plan_id: plan,
                    "feature_name": permission.feature_name,
                    "description": permission.description,
                    "type": permission.type,
                    "limits": permission.limits,
                    "is_enable": permission.is_enable,
                    "time_period": permission.time_period
                })
            }
            await this.PlanPermission.save(planPermission);
            await this.reorderPlanPriorities();
            this.updateCustomerBillingPortal();
            return true;
        }
        throw new HttpException(responseMessages.en.plan.plan_error, HttpStatus.BAD_REQUEST);
    }

    async reorderPlanPriorities(): Promise<void> {
        const plans = await this.Plan
            .createQueryBuilder('plan')
            .orderBy('plan.month_amount', 'ASC')
            .getMany();

        for (let i = 0; i < plans.length; i++) {
            plans[i].priority = i + 1;
            await this.Plan.save(plans[i]);
        }
    }
    async updatePlanPriority(planId: string, newPriority: number): Promise<Plan> {
        const plan = await this.Plan.findOne({ where: { id: planId } });

        const oldPriority = plan.priority;

        if (newPriority === oldPriority) return plan;

        if (newPriority < oldPriority) {
            // Moving up: shift down the others
            await this.Plan
                .createQueryBuilder()
                .update(Plan)
                .set({ priority: () => `"priority" + 1` })
                .where(`"priority" >= :newPriority AND "priority" < :oldPriority`, {
                    newPriority,
                    oldPriority,
                })
                .execute();
        } else {
            // Moving down: shift up the others
            await this.Plan
                .createQueryBuilder()
                .update(Plan)
                .set({ priority: () => `"priority" - 1` })
                .where(`"priority" <= :newPriority AND "priority" > :oldPriority`, {
                    newPriority,
                    oldPriority,
                })
                .execute();
        }

        // Update the selected plan
        plan.priority = newPriority;
        return await this.Plan.save(plan);
    }
}
