import { Injectable, HttpException, HttpStatus, Res } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, Not, In } from 'typeorm';
import { classToPlain } from 'class-transformer';
import { responseMessages } from '../../messages/response-messages';
import { emailMessages } from '../../messages/email-messages';
import { BrandRegisterRepository } from './brand-register.repository';
import * as bcrypt from 'bcryptjs';
import { HttpService } from '@nestjs/axios';
import { Constants } from '../../common/constants';
import { JwtService } from '@nestjs/jwt';
const moment = require('moment-timezone');
import { SendMailService } from '../../common/config/send-mail.service';

// Entities Files
import { UserRoles, Users } from "../../entities/users.entity";
import { BrandIndustries } from '../../entities/brand-industries.entity';

// DTO Files
import { FirstStepDto } from './dtos/first-step.dto';
import { SecondStepDto } from './dtos/second-step.dto';
import { ThirdStepDto } from './dtos/third-step.dto';
import { Settings } from 'src/entities/settings.entity';
import { BrandUpdateDto } from './dtos/brand-update.dto';
import { BrandSlugParamDto } from './dtos/brand-slug-param.dto';
import { UsersServices } from 'src/common/services/users/users.service';
import { PaymentService } from '../payment/payment.service';
import { CommonService } from '../common/common.services';
import { WhatsAppServices } from 'src/common/services/whatsapp/whatsapp.service';
import { notificationSettings } from 'src/messages/notification-settings';

@Injectable()
export class BrandRegisterService {

    constructor(
        private brandRegisterRepository: BrandRegisterRepository,
        private sendMailService: SendMailService,
        private usersServices: UsersServices,
        private paymentService: PaymentService,
        private commonService: CommonService,
        private whatsappServices: WhatsAppServices,
        @InjectRepository(Users)
        private Users: Repository<Users>,

        @InjectRepository(BrandIndustries)
        private BrandIndustries: Repository<BrandIndustries>,

        @InjectRepository(Settings)
        private Settings: Repository<Settings>,

    ) { }

    async firstStep(request: FirstStepDto, authUser: any) {
        const lang = authUser.language || 'en';
        const languageCode = request.language_code || 'en';
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] });
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND);
        }

        if (existsUser.pending_steps != 0) {
            throw new HttpException(responseMessages[lang].user.invalid_registration_page, HttpStatus.NOT_FOUND);
        }

        existsUser['business_type'] = request.business_type;
        existsUser['pending_steps'] = 1;
        await this.Users.save(existsUser);
        // UPDATE COMET CHAT USER EMAIL NOTIFICATION
        this.commonService.cometChatEmailNotification(existsUser.id);
        return await this.usersServices.getUserDetails(authUser, authUser);
    }

    async secondStep(request: SecondStepDto, authUser: any) {
        const lang = authUser.language || 'en';
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] });
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND);
        }

        if (existsUser.pending_steps != 1) {
            throw new HttpException(responseMessages[lang].user.invalid_registration_page, HttpStatus.NOT_FOUND);
        }

        existsUser['working_people'] = request.working_people;
        existsUser['pending_steps'] = 2;
        await this.Users.save(existsUser);

        return await this.usersServices.getUserDetails(authUser, authUser);
    }

    async thirdStep(request: ThirdStepDto, authUser: any) {
        const lang = authUser.language || 'en';
        const existsUser = await this.Users.findOne({ where: [{ id: authUser.id }] });
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND);
        }

        if (existsUser.pending_steps != 2) {
            throw new HttpException(responseMessages[lang].user.invalid_registration_page, HttpStatus.NOT_FOUND);
        }

        const settings = await this.Settings.find({ where: { type: In(['industry_min', 'industry_max']) } })
        const industryLimits = {
            industry_min: Number(settings.find(setting => setting.type === 'industry_min')?.value),
            industry_max: Number(settings.find(setting => setting.type === 'industry_max')?.value),
        };

        // if (request.industries.length >= industryLimits.industry_min && request.industries.length <= industryLimits.industry_max) {

        // }


        await this.brandRegisterRepository.createBrandIndustries(request, existsUser);

        existsUser['pending_steps'] = 3;
        const welcomeMailNotificationSetting = notificationSettings.welcome_email;
        if (welcomeMailNotificationSetting.email) {
            const name = `${existsUser.first_name} ${existsUser.last_name}`;
            const mailSubject = emailMessages.en.welcome_mail.subject;
            const mailObj = {
                hello_user_name: emailMessages.en.hello_user_name.replace(':user_name', name),
                main_title: emailMessages.en.welcome_mail.title,
                descriptions: emailMessages.en.welcome_mail.description,
                copyright: emailMessages.en.copyright,
                all_rights_reserved: emailMessages.en.all_rights_reserved,
            }

            this.sendMailService.sendMailObjectWithTemplates(existsUser.email, mailSubject, 'welcome_mail', mailObj);
        }
        const plan = await this.paymentService.getFreePlan();
        if (plan) {
            const body = { plan_id: plan.id, card_id: "", interval: "month" };
            await this.paymentService.subscription(body, existsUser);
            existsUser['is_subscribed'] = true;
        }
        await this.Users.save(existsUser);
        return await this.usersServices.getUserDetails(authUser, authUser);
    }

    /**
     * Updates the brand data based on the provided request data.
     * @param params - An instance of BrandSlugParamDto containing the brand slug to be updated.
     * @param request - An instance of BrandUpdateDto containing the brand information to be updated.
     * @param response - The response object for sending the HTTP response.
     * @param req - The request object, containing the authenticated user information.
     * @throws HttpException - Throws a 404 error if the user does not exist.
     * @returns 201 status if the update is successful.
     * In case of an error, logs the error and responds with the respective error status and message.
    */
    async brandUpdate(params: BrandSlugParamDto, request: BrandUpdateDto, authUser: any) {
        const lang = authUser.language || 'en';
        const req_business_type = request.business_type ? request.business_type : null;
        const req_working_people = request.working_people ? request.working_people : null;
        const req_industries = request.industries ? request.industries : null;

        const existsUser = await this.Users.findOne({ where: [{ slug: params.brand_slug, role: UserRoles.BRAND }] });
        if (!existsUser) {
            throw new HttpException(responseMessages[lang].user.user_not_exists, HttpStatus.NOT_FOUND);
        }
        if (request.phone_number) {
            const phoneNumberExists = await this.Users.createQueryBuilder('user')
                .where('user.phone_number = :phone_number', { phone_number: request.phone_number })
                .andWhere('user.is_whatsapp_verified = true')
                .andWhere('user.id != :id', { id: existsUser.id })
                .getOne();
            if (phoneNumberExists) {
                throw new HttpException(responseMessages[lang].user.phone_number_already_exists, HttpStatus.NOT_FOUND);
            }
        }
        if (existsUser.phone_number !== request.phone_number) {
            existsUser['is_whatsapp_verified'] = null;
            existsUser['whatsapp_request_at'] = new Date();
            let phoneNumber = request.phone_number
            if (phoneNumber.startsWith('0')) {
                phoneNumber = phoneNumber.substring(1);
            }
            phoneNumber = `${request.country_code}${phoneNumber}`.replace('+', '');
            this.whatsappServices.verifyWhatsAppNumber(phoneNumber, existsUser.first_name);
        }
        existsUser['first_name'] = request.first_name;
        existsUser['last_name'] = request.last_name;
        existsUser['country_code'] = request.country_code;
        existsUser['phone_number'] = request.phone_number;
        existsUser['company_name'] = request.company_name;
        existsUser['business_type'] = req_business_type;
        existsUser['working_people'] = req_working_people;
        existsUser['country'] = request.country;
        existsUser['gender'] = request.gender;
        existsUser['currency'] = request.currency;
        existsUser['is_offline_payment_allowed'] = request.is_offline_payment_allowed;
        existsUser['offline_payment_allowed'] = request.offline_payment_allowed;
        existsUser['about_me'] = request.about_me;
        existsUser['whatsapp_phone_number'] = `${request.country_code}${request.phone_number}`.replace('+', '');


        if (req_industries && request.industries.length > 0) {
            const settings = await this.Settings.find({ where: { type: In(['industry_min', 'industry_max']) } })
            const industryLimits = {
                industry_min: Number(settings.find(setting => setting.type === 'industry_min')?.value),
                industry_max: Number(settings.find(setting => setting.type === 'industry_max')?.value),
            };

            // if (request.industries.length >= industryLimits.industry_min && request.industries.length <= industryLimits.industry_max) {

            // }

            await this.brandRegisterRepository.createBrandIndustries(request, existsUser);
        }

        await this.Users.save(existsUser);
        const data = { first_name: existsUser.first_name, last_name: existsUser.last_name };
        return { data };
    }
    async backStep(authUser: any) {
        authUser["pending_steps"] = authUser["pending_steps"] - 1
        await this.Users.save(authUser)
        return await this.usersServices.getUserDetails(authUser, authUser);
    }

}
