import { isNull } from "../../helpers/IsNull";
import { validatePermissionsByCompany, validateSessionUser } from "../../helpers/check";
import { TextObjectFilterResult } from "../TextObjectFilter.model";
import { TemplatesAdapterMongoose } from "./Templates.Adapter.Mongoose";
import {
    CreateTemplateParams,
    DeleteTemplateParams,
    DeleteTemplatesByCompanyParams,
    FindTemplatesParams,
    GetDefaultTemplateParams,
    ITemplate,
    ITemplatesManager,
    PaginateTemplatesParams,
    PaginateTemplatesResults,
    SaveTemplateParams,
    TemplateTypes,
    UpdateTemplateParams,
} from "./Templates.Interface";

export class TemplatesManager implements ITemplatesManager {
    templates: TemplatesAdapterMongoose;

    constructor() {
        this.templates = new TemplatesAdapterMongoose();
    }

    public async deleteTemplatesByCompany(data: DeleteTemplatesByCompanyParams): Promise<void> {
        if (!data.companyId) {
            return;
        }
        await this.templates.templatesList.deleteMany({
            companyId: data.companyId,
        });
    }

    public async createTemplate(data: CreateTemplateParams): Promise<ITemplate> {
        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

        await validatePermissionsByCompany({
            companyId: data.companyId,
            sessionUser: data.sessionUser,
        });

        const checkTemplate = await this.templates.findOne({
            companyId: data.companyId,
            code: data.code,
        });

        if (checkTemplate) {
            throw new Error("Ya existe una plantilla con el mismo código");
        }

        // La lógica de negocio se implementará aquí
        const template = this.templates.create(data);

        if (!template) {
            throw new Error("Error al crear la plantilla");
        }

        return template;
    }

    public async updateTemplate(data: UpdateTemplateParams): Promise<ITemplate> {
        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

        await validatePermissionsByCompany({
            companyId: data.companyId,
            sessionUser: data.sessionUser,
        });

        const checkTemplate = await this.templates.findOne({
            companyId: data.companyId,
            id: data.templateId,
        });

        if (!checkTemplate) {
            throw new Error("La plantilla que intenta actualizar no existe");
        }

        const updatedTemplate = await this.templates.update(data);

        if (!updatedTemplate) {
            throw new Error("Error al actualizar la plantilla");
        }

        return updatedTemplate;
    }

    public async saveTemplate(data: SaveTemplateParams): Promise<ITemplate> {
        if (data.templateId) {
            return this.updateTemplate({
                templateId: data.templateId,
                companyId: data.companyId,
                name: data.name,
                code: data.code,
                type: data.type,
                template: data.template,
                sessionUser: data.sessionUser,
            });
        } else {
            return this.createTemplate({
                companyId: data.companyId,
                name: data.name,
                code: data.code,
                type: data.type,
                template: data.template,
                sessionUser: data.sessionUser,
            });
        }
    }

    public async deleteTemplate(data: DeleteTemplateParams): Promise<void> {
        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

        const template = await this.templates.findOne({ id: data.id, companyId: data.companyId });

        if (!template) {
            throw new Error("La plantilla que intenta eliminar no existe");
        }

        const validation = await validatePermissionsByCompany({
            companyId: String(template.companyId),
            sessionUser: data.sessionUser,
        });

        //Desvincular de la organizacion.
        const companyCheck = validation.company;

        if (!companyCheck) {
            throw new Error(
                "No se puede determinar la organización a la que pertenece la plantilla"
            );
        }

        if (String(companyCheck.templateEmailAltaId) === String(data.id)) {
            companyCheck.templateEmailAltaId = undefined;
        }
        if (String(companyCheck.templateEmailNotifId) === String(data.id)) {
            companyCheck.templateEmailNotifId = undefined;
        }
        if (String(companyCheck.templateWapAltaId) === String(data.id)) {
            companyCheck.templateWapAltaId = undefined;
        }

        if (String(companyCheck.templateWapNotifId) === String(data.id)) {
            companyCheck.templateWapNotifId = undefined;
        }

        await this.templates.delete(data);
    }

    public async paginate(data: PaginateTemplatesParams): Promise<PaginateTemplatesResults> {
        return this.templates.paginate(data);
    }

    public async getTemplate(data: FindTemplatesParams): Promise<ITemplate> {
        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

        await validatePermissionsByCompany({
            companyId: data.companyId,
            sessionUser: data.sessionUser,
        });

        const checkTemplate = await this.templates.findOne({
            companyId: data.companyId,
            id: data.id,
        });

        if (!checkTemplate) {
            throw new Error("La plantilla que intenta obtener no existe");
        }

        return checkTemplate;
    }

    public async textObjectFilter(data: FindTemplatesParams): Promise<TextObjectFilterResult[]> {
        const templates = await this.templates.find(data);
        const formattedResult: TextObjectFilterResult[] = [];

        for (const item of templates) {
            formattedResult.push({
                id: isNull<string>(item.id, ""),
                name: item.name,
                image: "",
            });
        }

        return formattedResult;
    }

    public async getDefaultTemplate(data: GetDefaultTemplateParams): Promise<string> {
        let defaultTemplate = "";

        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

        await validatePermissionsByCompany({
            companyId: data.companyId,
            sessionUser: data.sessionUser,
        });

        switch (data.type) {
            case TemplateTypes.WAP_REMINDER:
                defaultTemplate = `${process.env.WAP_REMINDER}`;
                break;
            case TemplateTypes.WAP_NEW_APPOINTMENT:
                defaultTemplate = `${process.env.WAP_ALTA}`;
                break;
            case TemplateTypes.EMAIL_REMINDER:
                defaultTemplate = `${process.env.WAP_REMINDER}`;
                break;
            case TemplateTypes.EMAIL_NEW_APPOINTMENT:
                defaultTemplate = `${process.env.WAP_ALTA}`;
                break;
        }
        return defaultTemplate;
    }
}

export default new TemplatesManager();
