import { validatePermissionsByCompany, validateSessionUser } from "../../helpers/check";
import { PostsAdapterMongoose } from "./Posts.Adapter.Mongoose";
import {
    CreatePostParams,
    DeletePostParams,
    DeletePostsByCompanyParams,
    GetPostParams,
    IPost,
    IPostsManager,
    PaginatePostsParams,
    PaginatePostsResults,
    SavePostParams,
    UpdatePostParams,
} from "./Posts.Interface";
import sanitizeHtml from "sanitize-html";

export class PostsManager implements IPostsManager {
    posts: PostsAdapterMongoose;

    constructor() {
        this.posts = new PostsAdapterMongoose();
    }

    public async deletePostsByCompany(data: DeletePostsByCompanyParams): Promise<void> {
        if (!data.companyId) {
            return;
        }
        await this.posts.postList.deleteMany({
            companyId: data.companyId,
        });
    }

    //sdasd
    public async createPost(data: CreatePostParams): Promise<IPost> {
        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

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

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

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

        return post;
    }

    public async updatePost(data: UpdatePostParams): Promise<IPost> {
        await validateSessionUser({
            sessionUser: data.sessionUser,
        });

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

        const checkPost = await this.posts.findOne({
            companyId: data.companyId,
            id: data.postId,
        });

        if (!checkPost) {
            throw new Error("El post que intenta actualizar no existe");
        }

        const updatedPost = await this.posts.update(data);

        if (!updatedPost) {
            throw new Error("Error al actualizar el post");
        }

        return updatedPost;
    }

    public async savePost(data: SavePostParams): Promise<IPost> {
        const sanitizedContent = sanitizeHtml(data.content, {
            allowedTags: [
                "p",
                "strong",
                "u",
                "s",
                "ol",
                "ul",
                "li",
                "span",
                "h1",
                "h2",
                "h3",
                "h4",
                "h5",
                "h6",
                "a",
                "img",
                "br",
                "div",
                "iframe",
            ],
            allowedAttributes: {
                a: ["href", "title", "rel", "target", "style"],
                img: ["src", "alt", "title", "width", "height", "style"],
                span: ["style", "class", "contenteditable"],
                li: ["data-list"],
                iframe: ["frameborder", "allowfullscreen", "src"],
                "*": ["style", "class"], // habilita style/class en todos los tags
            },
            allowedIframeHostnames: ["www.youtube.com"],
            allowedSchemes: ["http", "https", "mailto"],
            allowedStyles: {
                "*": {
                    color: [/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/i, /^#[0-9a-f]{3,6}$/i],
                    "background-color": [
                        /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/i,
                        /^#[0-9a-f]{3,6}$/i,
                    ],
                    "text-align": [/^left$/, /^right$/, /^center$/, /^justify$/],
                },
            },
        });

        if (data.postId) {
            return this.updatePost({
                postId: data.postId,
                companyId: data.companyId,
                content: sanitizedContent,
                fixed: data.fixed,
                fixedOrder: data.fixedOrder,
                sessionUser: data.sessionUser,
            });
        } else {
            return this.createPost({
                companyId: data.companyId,
                content: sanitizedContent,
                sessionUser: data.sessionUser,
            });
        }
    }

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

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

        if (!post) {
            throw new Error("El post que intenta eliminar no existe");
        }

        const validation = await validatePermissionsByCompany({
            companyId: String(post.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 el post");
        }

        await this.posts.delete(data);
    }

    public async paginate(data: PaginatePostsParams): Promise<PaginatePostsResults> {
        return this.posts.paginate(data);
    }

    public async getPost(data: GetPostParams): Promise<IPost> {
        const post = await this.posts.findOne({ id: data.id });

        if (!post) {
            throw new Error("El post que intenta obtener no existe");
        }

        return post;
    }
}

export default new PostsManager();
