/** @odoo-module **/
// Fusion Claims - Document Preview (PDF and XML)
// Copyright 2024-2025 Nexa Systems Inc.
// License OPL-1

import { registry } from "@web/core/registry";
import { _t } from "@web/core/l10n/translation";
import { Component, useState, onMounted } from "@odoo/owl";
import { Dialog } from "@web/core/dialog/dialog";
import { useService } from "@web/core/utils/hooks";

/**
 * PDF Document Preview Dialog Component
 * Uses Odoo's built-in PDF.js viewer for XFA/protected PDF support
 */
export class DocumentPreviewDialog extends Component {
    static template = "fusion_claims.DocumentPreviewDialog";
    static components = { Dialog };
    
    setup() {
        this.state = useState({
            isLoading: true,
            isMaximized: false
        });
    }

    getViewerUrl() {
        const pdfUrl = `/web/content/${this.props.attachmentId}`;
        const encodedUrl = encodeURIComponent(pdfUrl);
        return `/web/static/lib/pdfjs/web/viewer.html?file=${encodedUrl}#pagemode=none`;
    }

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

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

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

    getFrameStyle() {
        return this.state.isMaximized 
            ? 'height: calc(98vh - 100px); width: 100%;' 
            : 'height: calc(85vh - 100px); width: 100%;';
    }
}

/**
 * XML Viewer Dialog Component
 * Displays XML content with syntax highlighting
 */
export class XMLViewerDialog extends Component {
    static template = "fusion_claims.XMLViewerDialog";
    static components = { Dialog };
    
    setup() {
        this.state = useState({
            isLoading: true,
            isMaximized: false,
            xmlContent: '',
            formattedXml: '',
            error: null
        });
        this.notification = useService("notification");
        
        onMounted(async () => {
            await this.loadXmlContent();
        });
    }

    async loadXmlContent() {
        try {
            const response = await fetch(`/web/content/${this.props.attachmentId}`);
            if (!response.ok) {
                throw new Error('Failed to load XML file');
            }
            const xmlText = await response.text();
            this.state.xmlContent = xmlText;
            this.state.formattedXml = this.formatXml(xmlText);
            this.state.isLoading = false;
        } catch (error) {
            this.state.error = error.message;
            this.state.isLoading = false;
        }
    }

    formatXml(xml) {
        // Format XML with indentation and syntax highlighting
        let formatted = '';
        let indent = 0;
        const tab = '  ';
        
        // Split by tags
        xml = xml.replace(/>\s*</g, '><');
        const nodes = xml.split(/(<[^>]+>)/g).filter(n => n.trim());
        
        for (const node of nodes) {
            if (node.startsWith('</')) {
                // Closing tag - decrease indent
                indent = Math.max(0, indent - 1);
                formatted += tab.repeat(indent) + this.highlightXml(node) + '\n';
            } else if (node.startsWith('<?') || node.startsWith('<!')) {
                // Declaration or comment
                formatted += this.highlightXml(node) + '\n';
            } else if (node.startsWith('<') && node.endsWith('/>')) {
                // Self-closing tag
                formatted += tab.repeat(indent) + this.highlightXml(node) + '\n';
            } else if (node.startsWith('<')) {
                // Opening tag
                formatted += tab.repeat(indent) + this.highlightXml(node) + '\n';
                indent++;
            } else {
                // Text content
                const trimmed = node.trim();
                if (trimmed) {
                    formatted += tab.repeat(indent) + this.escapeHtml(trimmed) + '\n';
                }
            }
        }
        
        return formatted;
    }

    highlightXml(str) {
        // Escape HTML first
        str = this.escapeHtml(str);
        
        // Highlight tag names
        str = str.replace(/&lt;(\/?)([\w:-]+)/g, 
            '&lt;$1<span class="xml-tag">$2</span>');
        
        // Highlight attributes
        str = str.replace(/([\w:-]+)=(&quot;[^&]*&quot;)/g, 
            '<span class="xml-attr">$1</span>=<span class="xml-value">$2</span>');
        
        return str;
    }

    escapeHtml(str) {
        return str
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;');
    }

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

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

    async copyToClipboard() {
        try {
            await navigator.clipboard.writeText(this.state.xmlContent);
            this.notification.add(_t("XML copied to clipboard"), { type: 'success' });
        } catch (error) {
            this.notification.add(_t("Failed to copy to clipboard"), { type: 'warning' });
        }
    }

    downloadXml() {
        window.open(`/web/content/${this.props.attachmentId}?download=true`, '_blank');
    }
}

/**
 * Client action to preview a PDF document
 */
async function previewDocumentAction(env, action) {
    const attachmentId = action.params?.attachment_id;
    const title = action.params?.title || "Document Preview";
    
    if (!attachmentId) {
        env.services.notification.add(
            _t("No document has been uploaded yet."),
            { type: 'warning', title: _t("No Document") }
        );
        return;
    }
    
    env.services.dialog.add(DocumentPreviewDialog, {
        attachmentId: attachmentId,
        title: title
    });
}

/**
 * Client action to preview an XML document
 */
async function previewXmlAction(env, action) {
    const attachmentId = action.params?.attachment_id;
    const title = action.params?.title || "XML Viewer";
    
    if (!attachmentId) {
        env.services.notification.add(
            _t("No XML file has been uploaded yet."),
            { type: 'warning', title: _t("No Document") }
        );
        return;
    }
    
    env.services.dialog.add(XMLViewerDialog, {
        attachmentId: attachmentId,
        title: title
    });
}

// Register client actions
registry.category("actions").add("fusion_claims.preview_document", previewDocumentAction);
registry.category("actions").add("fusion_claims.preview_xml", previewXmlAction);

/**
 * Image Preview Dialog Component
 * Full-screen image preview with navigation
 */
export class ImagePreviewDialog extends Component {
    static template = "fusion_claims.ImagePreviewDialog";
    static components = { Dialog };
    
    setup() {
        this.state = useState({
            currentIndex: this.props.initialIndex || 0,
            isLoading: true
        });
    }

    get currentImage() {
        return this.props.images[this.state.currentIndex];
    }

    get imageUrl() {
        return `/web/image/${this.currentImage.id}`;
    }

    get hasMultiple() {
        return this.props.images.length > 1;
    }

    get currentPosition() {
        return `${this.state.currentIndex + 1} / ${this.props.images.length}`;
    }

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

    previousImage() {
        if (this.state.currentIndex > 0) {
            this.state.isLoading = true;
            this.state.currentIndex--;
        }
    }

    nextImage() {
        if (this.state.currentIndex < this.props.images.length - 1) {
            this.state.isLoading = true;
            this.state.currentIndex++;
        }
    }

    downloadImage() {
        window.open(`/web/content/${this.currentImage.id}?download=true`, '_blank');
    }
}

/**
 * Client action to preview images
 */
async function previewImageAction(env, action) {
    const images = action.params?.images || [];
    const initialIndex = action.params?.initial_index || 0;
    const title = action.params?.title || "Image Preview";
    
    if (!images.length) {
        env.services.notification.add(
            _t("No images available."),
            { type: 'warning', title: _t("No Images") }
        );
        return;
    }
    
    env.services.dialog.add(ImagePreviewDialog, {
        images: images,
        initialIndex: initialIndex,
        title: title
    });
}

registry.category("actions").add("fusion_claims.preview_image", previewImageAction);
