import { Injectable, HttpException, HttpStatus, OnModuleInit } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import axios from 'axios';
import { Users } from 'src/entities/users.entity';
import { responseMessages } from 'src/messages/response-messages';
import { In, Not, Repository } from 'typeorm';
import { EncryptionService } from '../encryption/encryption.service';
import { NotificationChannel, UserNotificationPreferences } from 'src/entities/user-notification-preferences.entity';
import { WhatsAppMessage, WhatsAppMessageDirection, WhatsAppRegistrationStatus } from 'src/entities/whatsapp-messages.entity';
import { Constants } from 'src/common/constants';
import { SocketGateway } from '../socket/socket.gateway';

@Injectable()
export class WhatsAppServices implements OnModuleInit {
    private readonly THANK_YOU_TEMPLATES = ['thank_you_en', 'thank_you_hk'];

    public WHATSAPP_ACCESS_TOKEN: string = "";
    public WHATSAPP_PHONE_NUMBER_ID: string = "";
    public WHATSAPP_API_VERSION: string = "v22.0";
    public WHATSAPP_BASE_URL: string = "";

    constructor(
        private encryptionService: EncryptionService,
        private socketGateway: SocketGateway,
        @InjectRepository(Users)
        private Users: Repository<Users>,
        @InjectRepository(UserNotificationPreferences)
        private UserNotificationPreferences: Repository<UserNotificationPreferences>,
        @InjectRepository(WhatsAppMessage)
        private WhatsAppMessage: Repository<WhatsAppMessage>,
    ) { }

    async onModuleInit() {
        // Initialize WhatsApp API configuration
        this.WHATSAPP_PHONE_NUMBER_ID = process.env.WHATSAPP_PHONE_NUMBER_ID || "";
        this.WHATSAPP_BASE_URL = `${process.env.WHATSAPP_BASE_URL}${this.WHATSAPP_PHONE_NUMBER_ID}/`;

        //if (process.env.WHATSAPP_ACCESS_TOKEN) {
        //this.WHATSAPP_ACCESS_TOKEN = await this.encryptionService.decrypt(process.env.WHATSAPP_ACCESS_TOKEN);
        //}
    }

    /**
     * Common POST axios method for WhatsApp Business API.
     *
     * @param {string} url - The URL to request.
     * @param {Object} headers - The headers to include in the request.
     * @param {Object} payload - The request payload.
     *
     * @returns {Object} The response data from the request.
     *
     * @throws {HttpException} If the request fails, an HTTP exception is thrown.
     */
    async postAxios(url: string, headers: any, payload: any) {
        try {
            const baseUrl = this.WHATSAPP_BASE_URL + url;
            headers['Authorization'] = `Bearer ${process.env.WHATSAPP_ACCESS_TOKEN}`;
            headers['Content-Type'] = 'application/json';
            const response = await axios.post(baseUrl, payload, {
                headers: headers,
            });
            return response.data;
        } catch (error) {
            console.log('WhatsApp API Error:', error.response?.data || error.message);
            throw new HttpException(
                error.response?.data?.error?.message || error.message || 'WhatsApp API request failed.',
                error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR
            );
        }
    }
    async formatForWhatsApp(message) {
        return message
            .replace(/<b>\s*/g, '*')   // remove space after <b>
            .replace(/\s*<\/b>/g, '*'); // remove space before </b>
    }
    /**
     * Verify if a user's phone number is a WhatsApp number.
     * Updates the is_whatsapp_verified status in the users table.
     * 
     * @param phoneNumber - The phone number to verify (optional, uses authUser's phone if not provided)
     * @param verificationCode - The verification code sent to WhatsApp (required for verification)
     * @param authUser - The authenticated user object
     * 
     * @throws HttpException - Throws a 400 error if the phone number is invalid.
     * @throws HttpException - Throws a 400 error if verification code is invalid.
     * 
     * @returns Success response with verification status.
     */
    async sendWhatsAppMessage(phoneNumber: string, message: string, metadata: any = null) {
        try {
            const whatsAppMessage = await this.formatForWhatsApp(message);
            const payload = {
                messaging_product: "whatsapp",
                to: phoneNumber,
                type: "template",
                template: {
                    name: "app_notifcations",
                    language: { code: "en" },
                    components: [
                        {
                            type: "body",
                            parameters: [
                                {
                                    type: "text",
                                    parameter_name: "user_name",
                                    text: metadata.user_name
                                },
                                {
                                    type: "text",
                                    parameter_name: "application_name",
                                    text: metadata.campaign_name
                                },
                                {
                                    type: "text",
                                    parameter_name: "message",
                                    text: whatsAppMessage
                                },
                            ]
                        },
                        {
                            type: "button",
                            sub_type: "url",
                            index: "0",
                            parameters: [
                                {
                                    type: "text",
                                    text: metadata.link
                                }
                            ]
                        }
                    ]
                }
            }
            const response = await this.postAxios('messages', {}, payload);
            await this.saveWhatsAppMessage({
                phone_number: phoneNumber,
                raw_payload: payload,
                message_content: message,
                message_type: 'app_notification',
                direction: WhatsAppMessageDirection.OUTBOUND,
            });
        } catch (error) {
            throw new HttpException(
                error.message || 'Failed to verify WhatsApp number.',
                error.status || HttpStatus.INTERNAL_SERVER_ERROR
            );
        }
    }

    async verifyWhatsAppNumber(phoneNumber: string, name: string) {
        const payload = {
            messaging_product: "whatsapp",
            to: phoneNumber,
            type: "template",
            template: {
                name: "verify_mobile_number",
                language: { code: "en" },
                components: [
                    {
                        type: "body",
                        parameters: [
                            {
                                type: "text",
                                parameter_name: "user_name",
                                text: name
                            }
                        ]
                    }
                ]
            }
        }
        this.saveWhatsAppMessage({
            phone_number: phoneNumber,
            raw_payload: payload,
            message_content: `Send Verification Code To ${name}'s WhatsApp Number`,
            message_type: 'verify_mobile_number',
            direction: WhatsAppMessageDirection.OUTBOUND,
        });
        const response = await this.postAxios('messages', {}, payload);
        console.log(response);
    }

    async managerAutoReplyTemplate(language?: string, role?: string) {
        switch (`${role}_${language}`) {
            case 'brand_en':
                return 'en_autoreply_copywriting_for_brand';

            case 'influencer_en':
                return 'en_autoreply_copywriting_for_influencer';

            case 'brand_hk':
                return 'hk_autoreply_copywriting_for_brand';

            case 'influencer_hk':
                return 'hk_autoreply_copywriting_for_influence';

            case 'influencer_kr':
                return 'en_autoreply_copywriting_for_influencer';

            case 'brand_kr':
                return 'en_autoreply_copywriting_for_brand';

            default:
                return 'en_autoreply_copywriting';
        }
    }

    async listMessages(queryParam: any) {
        const reqPage = queryParam.page ? queryParam.page : 0;
        const page = queryParam.page - 1;
        const pageSize = queryParam.per_page ? queryParam.per_page : Constants.whatsapp_message_list;
        const offset = page * pageSize;
        const nextPage = page + 1;
        const nextOffset = nextPage * pageSize;

        const sortByArr = {
            created_at: 'whatsapp_message.created_at',
            phone_number: 'whatsapp_message.phone_number',
            customer_name: 'whatsapp_message.customer_name',
            message_type: 'whatsapp_message.message_type',
            direction: 'whatsapp_message.direction',
            registration_status: 'whatsapp_message.registration_status',
        };

        let sort_by = queryParam.sort_by || 'created_at';
        const sort_type = queryParam.sort || 'DESC';
        sort_by = sortByArr[sort_by] || sortByArr.created_at;

        let query = this.WhatsAppMessage.createQueryBuilder('whatsapp_message')
            .leftJoin('whatsapp_message.user', 'user')
            .select([
                'whatsapp_message.id',
                'whatsapp_message.whatsapp_message_id',
                'whatsapp_message.phone_number',
                'whatsapp_message.registration_status',
                'whatsapp_message.message_type',
                'whatsapp_message.message_content',
                'whatsapp_message.customer_name',
                'whatsapp_message.direction',
                'whatsapp_message.is_auto_reply',
                'whatsapp_message.created_at',
                'user.id',
                'user.slug',
                'user.display_name',
                'user.first_name',
                'user.last_name',
                'user.email',
                'user.role',
                'user.whatsapp_phone_number',
                'user.is_whatsapp_verified',
                'user.image',
            ])
            .orderBy(sort_by, sort_type as 'ASC' | 'DESC');

        if (queryParam.search) {
            query = query.andWhere(
                `(whatsapp_message.phone_number ILIKE :search OR whatsapp_message.customer_name ILIKE :search OR whatsapp_message.message_content ILIKE :search OR user.display_name ILIKE :search OR user.email ILIKE :search)`,
                { search: `%${queryParam.search}%` },
            );
        }
        if (queryParam.message_type) {
            query = query.andWhere('whatsapp_message.message_type = :message_type', { message_type: queryParam.message_type });
        }
        if (queryParam.direction) {
            query = query.andWhere('whatsapp_message.direction = :direction', { direction: queryParam.direction });
        }
        if (queryParam.registration_status) {
            query = query.andWhere('whatsapp_message.registration_status = :registration_status', { registration_status: queryParam.registration_status });
        }

        if (queryParam.user_id) {
            query = query.andWhere('user.id = :user_id', { user_id: queryParam.user_id });
        }

        if (queryParam.phone_number) {
            query = query.andWhere('whatsapp_message.phone_number ILIKE :phone_number', { phone_number: `%${queryParam.phone_number}%` });
        }

        if (queryParam.is_auto_reply !== undefined && queryParam.is_auto_reply !== '') {
            const isAutoReply = queryParam.is_auto_reply === true || queryParam.is_auto_reply === 'true';
            query = query.andWhere('whatsapp_message.is_auto_reply = :is_auto_reply', { is_auto_reply: isAutoReply });
        }

        if (reqPage !== 0) {
            query = query.skip(offset).take(pageSize);
        }

        const [results, total] = await query.getManyAndCount();

        return {
            data: results,
            total,
            hasMoreResults: total > nextOffset ? 1 : 0,
        };
    }

    async checkAlreadySentAutoReplyMessage(phoneNumber: string, templateName: string) {
        const isThankYou = this.THANK_YOU_TEMPLATES.includes(templateName);
        const baseWhere = {
            phone_number: phoneNumber,
            message_type: 'auto_reply',
            direction: WhatsAppMessageDirection.OUTBOUND,
        };
        const where = isThankYou
            ? { ...baseWhere, message_content: In(this.THANK_YOU_TEMPLATES) }
            : { ...baseWhere, message_content: Not(In(this.THANK_YOU_TEMPLATES)) };

        const messageCount = await this.WhatsAppMessage.count({ where });
        return messageCount >= 1;
    }

    async sendAutoReplyMessage(phoneNumber: string, templateName?: string) {
        const user = await this.Users.findOne({ where: { whatsapp_phone_number: phoneNumber } });
        if (!user) {
            return;
        }
        const template = templateName ?? await this.managerAutoReplyTemplate(user?.language, user?.role);
        const alreadySent = await this.checkAlreadySentAutoReplyMessage(phoneNumber, template);
        if (alreadySent) {
            return;
        }
        const payload = {
            messaging_product: "whatsapp",
            to: phoneNumber,
            type: "template",
            template: {
                name: template,
                language: { code: user?.language == 'hk' ? 'zh_HK' : 'en' },
            }
        }
        await this.saveWhatsAppMessage({
            phone_number: phoneNumber,
            raw_payload: payload,
            message_content: template,
            message_type: 'auto_reply',
            direction: WhatsAppMessageDirection.OUTBOUND,
            is_auto_reply: true,
        });
        await this.postAxios('messages', {}, payload);
    }

    async saveWhatsAppMessage(request: any) {
        console.log('SAVE WHATSAPP MESSAGE');
        const user = await this.Users.findOne({ where: { whatsapp_phone_number: request.phone_number } });
        request.user = user ?? null;
        request.registration_status = user ? WhatsAppRegistrationStatus.REGISTERED : WhatsAppRegistrationStatus.NON_REGISTERED;
        request.customer_name = user?.display_name ?? null;
        this.WhatsAppMessage.save(request);
        return true;
    }

    async webhook(request: any) {
        const change = request.body?.entry?.[0]?.changes?.[0];
        const value = change?.value;
        const msg = value?.messages?.[0];
        const contact = value?.contacts?.[0];
        if (!msg) {
            console.log('NO MESSAGE');
            // Sometimes delivery/read status updates arrive without messages
            return;
        }

        let from = msg.from || contact?.wa_id; // customer wa_id (digits)
        const customerName = contact?.profile?.name;
        // Message types can be: text, button, interactive, image, etc.
        const type = msg.type;
        const user = await this.Users.findOne({ where: { whatsapp_phone_number: from }, order: { whatsapp_request_at: 'DESC' } });
        if (!user) {
            return;
        }
        await this.saveWhatsAppMessage({
            phone_number: from,
            raw_payload: msg,
            message_content: msg?.text?.body ?? msg?.button?.text ?? '',
            message_type: 'webhook',
            direction: WhatsAppMessageDirection.INBOUND,
        });

        if (type == 'button') {
            if (msg.button.text == 'Accept') {

                user.is_whatsapp_verified = true;
                await this.Users.save(user);


                await this.Users.update({ whatsapp_phone_number: from, id: Not(user.id) }, { is_whatsapp_verified: null, whatsapp_phone_number: null, whatsapp_request_at: null, phone_number: "", country_code: "" });

                if (user) {
                    const userPreferences = await this.UserNotificationPreferences.findOne({ where: { user: { id: user.id }, channel: NotificationChannel.WHATSAPP_NOTIFICATION } });
                    if (userPreferences) {
                        userPreferences.is_enabled = true;
                        await this.UserNotificationPreferences.save(userPreferences);
                    }
                }
                const thankYouTemplate = user.language == 'en' ? 'thank_you_en' : 'thank_you_hk';
                this.socketGateway.handleMessage({ whatsapp_verified: true }, user.id);
                this.sendAutoReplyMessage(from, thankYouTemplate);
            } else {
                this.Users.update({ whatsapp_phone_number: from }, { is_whatsapp_verified: false });
            }
        } else if (type == 'text') {
            this.sendAutoReplyMessage(from);
        }
        return true;
    }

}
