import { Injectable, HttpException, HttpStatus, forwardRef, Inject } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { responseMessages } from '../../messages/response-messages';
import { Subscription, SubscriptionStatus } from 'src/entities/subscription.entity';
import { NotificationService } from 'src/common/services/notification/notification.service';
import { UserRoles, Users } from 'src/entities/users.entity';
import { UserPermissions } from 'src/entities/user-permissions.entity';
import { notificationMessages } from 'src/messages/notifications-messages';
import { RedirectType } from 'src/entities/notifications.entity';
import { StripeServices } from 'src/common/services/payment-gateway/stripe/stripe.service';
import { Constants } from 'src/common/constants';
import { SendMailService } from 'src/common/config/send-mail.service';
import { notificationSettings } from 'src/messages/notification-settings';
import { emailMessages } from 'src/messages/email-messages';

@Injectable()
export class PaymentRepository {
    constructor(
        @Inject(forwardRef(() => StripeServices))
        private readonly stripeServices: StripeServices,
        private notificationService: NotificationService,
        private sendMailService: SendMailService,
        @InjectRepository(Subscription)
        private readonly Subscription: Repository<Subscription>,
        @InjectRepository(Users)
        private readonly Users: Repository<Users>,

        @InjectRepository(UserPermissions)
        private readonly UserPermissions: Repository<UserPermissions>,
    ) { }


    async createSubscription(subscriptionData, isPermissionChanged) {
        try {
            const subscription = await this.Subscription.save(subscriptionData);
            if (subscription) {
                let userPermissions = [];
                if (isPermissionChanged) {
                    const previousPermissions = await this.UserPermissions.find({
                        where: { users: { id: subscriptionData.users.id } }
                    });
                    const previousUsedByType = previousPermissions.reduce((acc, perm) => {
                        acc[perm.type] = perm.used || 0;
                        return acc;
                    }, {} as Record<string, number>);

                    await this.UserPermissions.delete({ users: { id: subscriptionData.users.id } });
                    for (const permission of subscriptionData.plan.permission) {
                        const type = permission.time_period ? `${permission.type}_time_period` : permission.type;
                        const used = Math.min(previousUsedByType[type] || 0, permission.limits);
                        userPermissions.push({
                            users: subscriptionData.users,
                            subscription: subscription,
                            type,
                            limit: permission.limits,
                            used,
                            remaining: permission.limits - used,
                            time_period: permission.time_period
                        })
                    }
                    await this.UserPermissions.save(userPermissions);
                }
                return subscription;
            }
        } catch (error) {
            console.log(error)
            throw new HttpException(responseMessages.en.subscription.error, HttpStatus.BAD_REQUEST);
        }

    }

    async notification(type, description, sender = null, redirect_type = null, redirect_id = null, redirect_slug = null) {
        const notificationSetting = notificationSettings[type] || {};
        if (notificationSetting?.in_app) {
            const receivers = await this.Users.find({ where: { role: UserRoles.ADMIN, is_active: true } });
            for (const receiver of receivers) {
                const notification = {
                    sender,
                    receiver,
                    description,
                    redirect_type,
                    redirect_id,
                    redirect_slug
                };
                await this.notificationService.save(notification);
            }
        }
    }

    async brandNotification(type, receiver, description, sender = null, redirect_type = null, redirect_id = null, redirect_slug = null, mailObj: any) {

        const notificationSetting = notificationSettings[type];
        if (notificationSetting?.in_app) {
            const notification = {
                sender,
                receiver,
                description,
                redirect_type,
                redirect_id,
                redirect_slug
            };
            await this.notificationService.save(notification);
        }
        if (notificationSetting?.email) {
            if (mailObj.subject == emailMessages.en.subscription.subject) {
                if (receiver.is_invoice_sent) {
                    return;
                }
                await this.Users.update(receiver.id, { is_invoice_sent: true });
            }
            this.sendMailService.sendMailObjectWithTemplates(receiver.email, mailObj.subject, 'common_mail', mailObj);
        }

    }

    async cancelFreeActiveSubscription(authUser, planExists, interval) {
        const activeSubscription = await this.Subscription.findOne({ relations: ['plan'], where: { users: { id: authUser.id }, is_active: true } });
        if (activeSubscription) {
            console.log('Active Subscription:', activeSubscription);
            if (activeSubscription.payment_mode == 'online' && activeSubscription.status == SubscriptionStatus.ACTIVE) {
                const param = { subscription_id: activeSubscription.id }
                await this.stripeServices.cancelSubscription(activeSubscription.stripe_subscription_id);
            }
            await this.Subscription.update(activeSubscription.id, { status: SubscriptionStatus.CANCELED, is_active: false });
        }
    }
}
