import { ContactUsDao } from "../dao/contactus.dao";
import { sequelize } from "../models";
import Models from "../models";
import { EmailTemplateService } from "./emailTemplate.service";
import { Common } from "../../utils/common";
import { AppError } from "../../utils/errors";

export class ContactUsService {
    private accountId: number | null;
    private userId: number | null;
    private language: string;
    private scope: string[] | null;
    private config: userConfig | null;
    private contactUsDao: ContactUsDao;
    constructor(
        private options: {
            language: string;
            scope: string[] | null;
            accountId: number | null;
            userId: number | null;
            config: userConfig | null;
        } = {
                language: process.env.DEFAULT_LANGUAGE_CODE!,
                scope: null,
                config: null,
                userId: null,
                accountId: null,
            }
    ) {
        this.language = options.language;
        this.scope = options.scope ?? [];
        this.config = options.config ?? null;
        this.userId = options.userId ?? null;
        this.accountId = options.accountId ?? null;
        this.contactUsDao = new ContactUsDao({
            userId: this.userId,
            accountId: this.accountId,
            language: this.language,
            scope: this.scope,
            config: this.config
        });
    }

    // create a new content type
    createContact = async (data: ContactUsCreateServiceInput): Promise<ContactUsInterface> => {
        const transaction = await sequelize.transaction();
        try {
            const createContactInput: ContactUsCreateDaoInput = { name: data.name, email: data.email, subject: data.subject, message: data.message, attachments: data.attachmentIds ?? null };
            let conatctIdentifier: number = await this.contactUsDao.create(createContactInput, { transaction });
            const getContactByIdInput: ContactUsGetByIdDaoInput = { id: conatctIdentifier };
            let contact: ContactUsInterface = await this.contactUsDao.getConatctUsById(getContactByIdInput, { transaction });
            await transaction.commit();

            // Send notification email to admin
            const adminEmail = process.env.SUPERADMIN_EMAIL;
            if (adminEmail) {
                const emailTemplateService = new EmailTemplateService(this.options);
                try {
                    let templateExists = await Models.EmailTemplate.findOne({ where: { code: 'contact-us-admin-notification' } });
                    if (!templateExists) {
                        await emailTemplateService.createEmailTemplate({
                            title: 'Contact Us Admin Notification',
                            code: 'contact-us-admin-notification',
                            subject: 'New Contact Us Query: {{subject}}',
                            body: '<p>Hi Admin,</p><p>You have received a new contact us query from {{name}} ({{email}}).</p><p><strong>Subject:</strong> {{subject}}</p><p><strong>Message:</strong></p><p>{{message}}</p>' as any,
                            status: 1
                        } as any);
                    }
                    await emailTemplateService.sendEmailTemplate(
                        'contact-us-admin-notification',
                        [adminEmail],
                        {
                            name: data.name || 'User',
                            email: data.email || 'No email provided',
                            subject: data.subject || 'No subject',
                            message: data.message || 'No message'
                        }
                    );
                } catch (emailErr) {
                    console.error("Failed to send contact us notification email to admin:", emailErr);
                }
            }

            return contact;
        } catch (err) {
            await transaction.rollback();
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get category Type by id
    getById = async (data: ContactUsGetByIdServiceInput): Promise<ContactUsInterface> => {
        try {
            const getContactByIdInput: ContactUsGetByIdDaoInput = { id: data.id };
            let faq = await this.contactUsDao.getConatctUsById(getContactByIdInput);
            if (faq) {
                return faq;
            }
            throw new AppError(404, 'CONTACT_US_NOT_FOUND', { id: 'CONTACT_US_NOT_FOUND' });
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list category types
    list = async (data: ContactUsListServiceInput): Promise<ContactUsPaginatedList> => {
        try {
            const { listRequest } = data;
            const { page, perPage } = listRequest;
            const listContactUsInput: ContactUsListDaoInput = { listRequest };
            let faqs: ContactUsPaginatedData = await this.contactUsDao.list(listContactUsInput);
            if (faqs) {
                let totalPages = Common.getTotalPages(faqs.count, perPage);
                return {
                    data: faqs.rows,
                    page: page,
                    perPage: perPage,
                    totalRecords: faqs.count,
                    totalPages: totalPages
                } as unknown as ContactUsPaginatedList;
            }
            throw new AppError(400, 'FAQ_LIST_ERROR_OUT', {});
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }
}
