/** @odoo-module **/

import { registry } from "@web/core/registry";
import { _t } from "@web/core/l10n/translation";
import { session } from "@web/session";
import { rpc } from "@web/core/network/rpc";
import { user } from "@web/core/user";
import { Component, useState, onMounted, onWillUnmount } from "@odoo/owl";
import { Dialog } from "@web/core/dialog/dialog";


/**
 * Fire-and-forget audit log for PDF preview/print/download actions.
 */
async function logPreviewAction(reportName, actionType, recordIds, modelName) {
    try {
        await rpc("/fusion_pdf_preview/log_action", {
            report_name: reportName,
            action_type: actionType,
            record_ids: recordIds || '',
            model_name: modelName || '',
        });
    } catch (err) {
        console.warn("Failed to log PDF preview action:", err);
    }
}


export class PDFViewerDialog extends Component {
    setup() {
        this.state = useState({
            isLoading: true,
            viewerUrl: this.getViewerUrl(),
            isMaximized: false
        });

        this._onKeyDown = this._onKeyDown.bind(this);

        onMounted(() => {
            document.addEventListener('keydown', this._onKeyDown);
        });

        onWillUnmount(() => {
            document.removeEventListener('keydown', this._onKeyDown);
        });
    }

    getViewerUrl() {
        const baseUrl = '/fusion_pdf_preview/static/lib/pdfjs/web/viewer.html';
        return `${baseUrl}?file=${this.props.url}`;
    }

    onIframeLoad() {
        this.state.isLoading = false;
    }

    toggle() {
        this.state.isMaximized = !this.state.isMaximized;
    }

    getDialogSize() {
        if (this.state.isMaximized) {
            return 'fullscreen';
        }
        return 'xl';
    }

    getFrameStyle() {
        if (this.state.isMaximized) {
            return 'height: calc(98vh - 141px) !important;';
        }
        return 'height: calc(90vh - 100px) !important;';
    }

    downloadPDF() {
        const link = document.createElement('a');
        link.href = this.props.url;
        link.download = this.props.title ? `${this.props.title}.pdf` : 'document.pdf';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);

        if (this.props.reportName) {
            logPreviewAction(this.props.reportName, 'download',
                this.props.recordIds, this.props.modelName);
        }
    }

    openInNewTab() {
        window.open(this.props.url, '_blank');
    }

    printPDF() {
        try {
            const iframe = this.el?.querySelector('iframe');
            if (iframe && iframe.contentWindow) {
                iframe.contentWindow.print();
            }
        } catch (err) {
            window.open(this.props.url, '_blank');
        }

        if (this.props.reportName) {
            logPreviewAction(this.props.reportName, 'print',
                this.props.recordIds, this.props.modelName);
        }
    }

    _onKeyDown(ev) {
        const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
        const ctrlOrCmd = isMac ? ev.metaKey : ev.ctrlKey;

        // F key (no modifiers) - toggle fullscreen
        if ((ev.key === 'f' || ev.key === 'F') && !ctrlOrCmd && !ev.altKey && !ev.shiftKey) {
            const activeEl = document.activeElement;
            if (activeEl && (activeEl.tagName === 'INPUT' || activeEl.tagName === 'TEXTAREA' || activeEl.isContentEditable)) {
                return;
            }
            ev.preventDefault();
            this.toggle();
        }

        // Ctrl+P / Cmd+P - print
        if (ctrlOrCmd && (ev.key === 'p' || ev.key === 'P')) {
            ev.preventDefault();
            this.printPDF();
        }

        // Ctrl+D / Cmd+D - download
        if (ctrlOrCmd && (ev.key === 'd' || ev.key === 'D')) {
            ev.preventDefault();
            this.downloadPDF();
        }
    }
}

PDFViewerDialog.template = 'fusion_pdf_preview.PDFViewerDialog';
PDFViewerDialog.components = { Dialog };

registry.category("dialog").add("PDFViewerDialog", PDFViewerDialog);


export function openPDFViewer(env, url, title = "PDF Document", meta = {}) {
    const dialog = env.services.dialog;
    return dialog.add(PDFViewerDialog, {
        url: url,
        title: title,
        reportName: meta.reportName || '',
        recordIds: meta.recordIds || '',
        modelName: meta.modelName || '',
    });
}


/**
 * Helper function to handle automatic printing
 * @param {string} url - URL of the PDF to print
 * @param {Object} env - Environment object for notifications
 */
function handleAutomaticPrinting(url, env) {
    const printFrame = document.createElement('iframe');
    printFrame.style.display = 'none';
    printFrame.src = url;

    printFrame.onload = function() {
        try {
            printFrame.contentWindow.print();
        } catch (err) {
            env.services.notification.add(
                _t("Failed to print automatically. Please check your browser settings."),
                {
                    type: 'warning',
                    sticky: true,
                    title: _t("Printing Error"),
                }
            );
            document.body.removeChild(printFrame);
        }
    };

    const cleanup = () => {
        if (printFrame.parentNode) {
            document.body.removeChild(printFrame);
        }
        window.removeEventListener('focus', cleanup);
    };

    window.addEventListener('focus', cleanup);

    document.body.appendChild(printFrame);
}


/**
 * Generates the report url given a report action.
 *
 * @private
 * @param {ReportAction} action
 * @param {Object} env
 * @param {string} filename
 * @returns {string}
 */
function _getReportUrl(action, env, filename) {
    let url = `/report/pdf/${action.report_name}`;
    const actionContext = action.context || {};
    filename = filename || action.name;
    if (filename !== undefined) {
        filename = filename.replace(/[/?%#&=]/g, "_") + ".pdf";
    }
    if (action.data && JSON.stringify(action.data) !== "{}") {
        const options = encodeURIComponent(JSON.stringify(action.data));
        const context = encodeURIComponent(JSON.stringify(actionContext));
        url += `?filename=${filename}&options=${options}&context=${context}&`;
    } else {
        if (actionContext.active_ids) {
            url += `/${actionContext.active_ids.join(",")}?filename=${filename}&context=${encodeURIComponent(JSON.stringify(user.context))}&`;
        }
    }

    return url;
}

async function FusionPdfPreview(action, options, env) {
    const link = '<br><br><a href="http://wkhtmltopdf.org/" target="_blank">wkhtmltopdf.org</a>';
    const WKHTMLTOPDF_MESSAGES = {
        broken:
            _t(
                "Your installation of Wkhtmltopdf seems to be broken. The report will be shown " +
                    "in html."
            ) + link,
        install:
            _t(
                "Unable to find Wkhtmltopdf on this system. The report will be shown in " + "html."
            ) + link,
        upgrade:
            _t(
                "You should upgrade your version of Wkhtmltopdf to at least 0.12.0 in order to " +
                    "get a correct display of headers and footers as well as support for " +
                    "table-breaking between pages."
            ) + link,
        workers: _t(
            "You need to start Odoo with at least two workers to print a pdf version of " +
                "the reports."
        ),
    };

    if (action.report_type === "qweb-pdf" && env.services.menu.getCurrentApp() !== undefined) {
        const userWantsPreview = session.preview_print;
        const userWantsAutoPrint = session.automatic_printing;

        const result = await rpc("/fusion_pdf_preview/get_report_name", {
            report_name: action.report_name,
            data: JSON.stringify(action.context)
        });
        const state = result["wkhtmltopdf_state"];
        const previewMode = result["fusion_preview_mode"] || "default";

        if (state in WKHTMLTOPDF_MESSAGES) {
            env.services.notification.add(WKHTMLTOPDF_MESSAGES[state], {
                sticky: true,
                title: _t("Report"),
            });
        }

        if (state === "upgrade" || state === "ok") {
            // Determine effective behavior based on report-level override
            let shouldPreview = userWantsPreview;
            let shouldAutoPrint = userWantsAutoPrint;

            if (previewMode === 'preview') {
                shouldPreview = true;
                shouldAutoPrint = false;
            } else if (previewMode === 'download') {
                return false;
            } else if (previewMode === 'auto_print') {
                shouldPreview = false;
                shouldAutoPrint = true;
            }

            if (!shouldPreview && !shouldAutoPrint) {
                return false;
            }

            const url = _getReportUrl(action, env, result["file_name"]);
            const actionContext = action.context || {};
            const meta = {
                reportName: action.report_name,
                recordIds: (actionContext.active_ids || []).join(','),
                modelName: actionContext.active_model || '',
            };

            if (shouldPreview) {
                openPDFViewer(env, url, action.name, meta);
                logPreviewAction(meta.reportName, 'preview', meta.recordIds, meta.modelName);
            }

            if (shouldAutoPrint) {
                handleAutomaticPrinting(url, env);
                logPreviewAction(meta.reportName, 'print', meta.recordIds, meta.modelName);
            }
            return true;
        }
    }
}

registry
    .category("ir.actions.report handlers")
    .add("fusion_pdf_preview", FusionPdfPreview);
