/** @odoo-module **/

import { Component, useState, onWillStart, useRef, onMounted } from "@odoo/owl";
import { markup } from "@odoo/owl";
import { rpc } from "@web/core/network/rpc";
import { _t } from "@web/core/l10n/translation";
import { isHtmlEmpty } from "@web/core/utils/html";
import { useService } from "@web/core/utils/hooks";
import { session } from "@web/session";

/**
 * Template picker popover (Section 2.3 / 2.4 / 2.5 / 2.6 / 6.3 / 14).
 *
 * Split-panel popover: a searchable, favorite-filterable, category-grouped
 * list on the left and a live, placeholder-resolved preview on the right.
 * All security is enforced server-side by the JSON-RPC controllers.
 */
export class TemplatePickerPopover extends Component {
    static template = "do_mail_quick_templates.TemplatePickerPopover";
    static props = {
        composer: { type: Object },
        owner: { type: Object, optional: true },
        resModel: { type: [String, Boolean], optional: true },
        resId: { type: [Number, Boolean], optional: true },
        close: { type: Function },
        "*": true,
    };

    setup() {
        this.notification = useService("notification");
        this.searchRef = useRef("search");
        this.state = useState({
            categories: [],
            selectedTemplate: null,
            previewContent: null,
            previewAttachments: [],
            searchText: "",
            favoritesOnly: false,
            loading: true,
            previewLoading: false,
            error: null,
            confirmReplace: false,
        });
        // Client-side preview cache keyed by template id, valid for this
        // popover session only (Section 2.6 / 15.4).
        this._previewCache = {};
        this._searchDebounce = null;

        onWillStart(async () => {
            await this._fetchTemplates();
        });
        onMounted(() => {
            if (this.searchRef.el) {
                this.searchRef.el.focus();
            }
        });
    }

    // ------------------------------------------------------------------
    // Data
    // ------------------------------------------------------------------
    async _fetchTemplates() {
        this.state.loading = true;
        this.state.error = null;
        try {
            const result = await rpc("/do_mail_quick_templates/get", {
                res_model: this.props.resModel || false,
                res_id: this.props.resId || false,
            });
            this.state.categories = result.categories || [];
        } catch {
            this.state.error = _t("Could not load templates. Please try again.");
            this.notification.add(this.state.error, { type: "danger" });
        } finally {
            this.state.loading = false;
        }
    }

    async refresh() {
        this._previewCache = {};
        this.state.selectedTemplate = null;
        this.state.previewContent = null;
        await this._fetchTemplates();
    }

    // ------------------------------------------------------------------
    // Derived data (client-side filtering, Section 13.4)
    // ------------------------------------------------------------------
    get filteredCategories() {
        const search = this.state.searchText.trim().toLowerCase();
        const favOnly = this.state.favoritesOnly;
        const result = [];
        for (const cat of this.state.categories) {
            const templates = cat.templates.filter((t) => {
                if (favOnly && !t.is_favorite) {
                    return false;
                }
                if (!search) {
                    return true;
                }
                return (
                    t.name.toLowerCase().includes(search) ||
                    (t.preview_text || "").toLowerCase().includes(search)
                );
            });
            if (templates.length) {
                result.push({ ...cat, templates });
            }
        }
        return result;
    }

    get isEmpty() {
        return !this.state.loading && this.filteredCategories.length === 0;
    }

    get hasManagerRights() {
        return Boolean(session.do_mail_quick_templates_is_manager);
    }

    // ------------------------------------------------------------------
    // Events
    // ------------------------------------------------------------------
    onSearchInput(ev) {
        const value = ev.target.value;
        clearTimeout(this._searchDebounce);
        this._searchDebounce = setTimeout(() => {
            this.state.searchText = value;
        }, 150);
    }

    toggleFavoritesOnly() {
        this.state.favoritesOnly = !this.state.favoritesOnly;
    }

    async onTemplateClick(template) {
        this.state.selectedTemplate = template;
        this.state.confirmReplace = false;
        await this._loadPreview(template);
    }

    async _loadPreview(template) {
        if (this._previewCache[template.id]) {
            const cached = this._previewCache[template.id];
            this.state.previewContent = cached.html;
            this.state.previewAttachments = cached.attachments;
            return;
        }
        this.state.previewLoading = true;
        this.state.previewContent = null;
        try {
            const result = await rpc("/do_mail_quick_templates/preview", {
                template_id: template.id,
                res_model: this.props.resModel || false,
                res_id: this.props.resId || false,
            });
            if (result.error) {
                this.state.previewContent = markup("");
                this.notification.add(result.error, { type: "warning" });
            } else {
                this.state.previewContent = markup(result.resolved_html || "");
                this.state.previewAttachments = result.attachment_names || [];
                this._previewCache[template.id] = {
                    html: this.state.previewContent,
                    attachments: this.state.previewAttachments,
                };
            }
        } catch {
            this.notification.add(
                _t("Could not load the template preview."),
                { type: "warning" }
            );
        } finally {
            this.state.previewLoading = false;
        }
    }

    onInsertClick() {
        if (!this.state.selectedTemplate) {
            return;
        }
        // Section 2.4: warn before replacing existing draft content.
        if (!isHtmlEmpty(this.props.composer.composerHtml)) {
            this.state.confirmReplace = true;
            return;
        }
        this._doInsert();
    }

    confirmReplaceYes() {
        this.state.confirmReplace = false;
        this._doInsert();
    }

    confirmReplaceNo() {
        this.state.confirmReplace = false;
    }

    async _doInsert() {
        const template = this.state.selectedTemplate;
        if (!template) {
            return;
        }
        // Ensure we have the resolved body (use cache if present).
        let html = this._previewCache[template.id]?.html;
        if (html === undefined) {
            await this._loadPreview(template);
            html = this.state.previewContent;
        }
        // Replace the composer body. Assigning composerHtml triggers the
        // composer's reactive effect that updates the live editor
        // (addons/mail/static/src/core/common/composer.js).
        this.props.composer.composerHtml = markup(html ? html.toString() : "");

        // Auto-attach the template's default attachments (Section 2.8).
        await this._attachDefaults(template);

        // Fire-and-forget usage logging (Section 2.7 / 8.2).
        rpc("/do_mail_quick_templates/log_use", {
            template_id: template.id,
            res_model: this.props.resModel || false,
            res_id: this.props.resId || false,
        }).catch(() => {});

        this.props.close();
    }

    async _attachDefaults(template) {
        if (!template.attachment_count) {
            return;
        }
        try {
            const result = await rpc("/do_mail_quick_templates/copy_attachments", {
                template_id: template.id,
                res_model: this.props.resModel || false,
                res_id: this.props.resId || false,
            });
            const store = this.props.composer.store;
            for (const att of result.attachments || []) {
                const record = store["ir.attachment"].insert({
                    id: att.id,
                    name: att.name,
                    mimetype: att.mimetype,
                });
                this.props.composer.attachments.add(record);
            }
        } catch {
            // Best-effort: never block the insertion if attaching fails.
        }
    }

    async toggleFavorite(template, ev) {
        ev.stopPropagation();
        const previous = template.is_favorite;
        template.is_favorite = !previous; // optimistic update
        try {
            const result = await rpc("/do_mail_quick_templates/toggle_favorite", {
                template_id: template.id,
            });
            template.is_favorite = result.is_favorite;
        } catch {
            // Section 2.5: revert on error.
            template.is_favorite = previous;
        }
    }

    onKeydown(ev) {
        if (ev.key === "Escape") {
            this.props.close();
        } else if (ev.key === "Enter" && this.state.selectedTemplate) {
            this.onInsertClick();
        }
    }
}
