/** @odoo-module **/

import { registry } from "@web/core/registry";
import { Component, useState, onWillStart } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
import { rpc } from "@web/core/network/rpc";
import { _t } from "@web/core/l10n/translation";

/**
 * PayrollReportAction - Main OWL component for payroll reports
 * Provides QuickBooks-style filtering, viewing, and export functionality.
 */
export class PayrollReportAction extends Component {
    static template = "fusion_payroll.PayrollReportAction";
    static props = {
        action: { type: Object },
        actionId: { type: [Number, Boolean], optional: true },
    };

    setup() {
        this.orm = useService("orm");
        this.actionService = useService("action");
        this.notification = useService("notification");

        // Get report model from action context
        this.reportModel = this.props.action.context?.report_model || 'payroll.report.paycheque.history';

        this.state = useState({
            loading: true,
            reportName: '',
            columns: [],
            lines: [],
            options: {},
            dateFilterOptions: [],
            filterDateRange: true,
            filterEmployee: true,
            filterDepartment: false,
            selectedDateFilter: 'this_year',
            dateFrom: '',
            dateTo: '',
            showCustomDate: false,
            sortColumn: null,
            sortDirection: 'asc',
            expandedLines: {},
        });

        onWillStart(async () => {
            await this.loadReportData();
        });
    }

    async loadReportData(options = null) {
        this.state.loading = true;
        try {
            const result = await rpc("/payroll/report/get_report_data", {
                report_model: this.reportModel,
                options: options || this.state.options,
            });

            if (result.error) {
                console.error("Report error:", result.error, result.traceback);
                this.notification.add(_t("Error loading report: %s", result.error), { type: "danger" });
                this.state.loading = false;
                return;
            }

            this.state.reportName = result.report_name;
            this.state.columns = result.columns || [];
            this.state.lines = result.lines || [];
            this.state.options = result.options || {};
            this.state.dateFilterOptions = result.date_filter_options || [];
            this.state.filterDateRange = result.filter_date_range !== undefined ? result.filter_date_range : true;
            this.state.filterEmployee = result.filter_employee !== undefined ? result.filter_employee : true;
            this.state.filterDepartment = result.filter_department !== undefined ? result.filter_department : false;

            // Set date filter values
            if (result.options && result.options.date) {
                this.state.selectedDateFilter = result.options.date.filter;
                this.state.dateFrom = result.options.date.date_from;
                this.state.dateTo = result.options.date.date_to;
                this.state.showCustomDate = result.options.date.filter === 'custom';
            }
        } catch (error) {
            console.error("Error loading report:", error);
            this.notification.add(_t("Error loading report: %s", error.message || error), { type: "danger" });
        }
        this.state.loading = false;
    }

    async onDateFilterChange(ev) {
        const filter = ev.target.value;
        this.state.selectedDateFilter = filter;
        this.state.showCustomDate = filter === 'custom';

        if (filter !== 'custom') {
            await this.applyFilters();
        }
    }

    async onDateFromChange(ev) {
        this.state.dateFrom = ev.target.value;
    }

    async onDateToChange(ev) {
        this.state.dateTo = ev.target.value;
    }

    async applyFilters() {
        const options = {
            ...this.state.options,
            date: {
                filter: this.state.selectedDateFilter,
                date_from: this.state.dateFrom,
                date_to: this.state.dateTo,
            },
        };
        await this.loadReportData(options);
    }

    sortByColumn(column) {
        if (!column.sortable) return;

        if (this.state.sortColumn === column.field) {
            this.state.sortDirection = this.state.sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            this.state.sortColumn = column.field;
            this.state.sortDirection = 'asc';
        }

        // Sort lines
        const sortedLines = [...this.state.lines].sort((a, b) => {
            const aVal = a.values?.[column.field] ?? '';
            const bVal = b.values?.[column.field] ?? '';

            // Keep totals at top/bottom
            if (a.level < 0) return -1;
            if (b.level < 0) return 1;

            let comparison = 0;
            if (typeof aVal === 'number' && typeof bVal === 'number') {
                comparison = aVal - bVal;
            } else {
                comparison = String(aVal).localeCompare(String(bVal));
            }

            return this.state.sortDirection === 'asc' ? comparison : -comparison;
        });

        this.state.lines = sortedLines;
    }

    async toggleLine(lineId) {
        if (this.state.expandedLines[lineId]) {
            delete this.state.expandedLines[lineId];
        } else {
            this.state.expandedLines[lineId] = true;
            // Load detail lines if needed
            await this.loadDetailLines(lineId);
        }
    }

    async loadDetailLines(lineId) {
        try {
            const result = await rpc("/payroll/report/get_detail_lines", {
                report_model: this.reportModel,
                line_id: lineId,
                options: this.state.options,
            });

            if (result.error) {
                console.error("Detail lines error:", result.error);
                return;
            }

            if (result.detail_lines && result.detail_lines.length > 0) {
                // Insert detail lines after the parent line
                const lineIndex = this.state.lines.findIndex(l => l.id === lineId);
                if (lineIndex >= 0) {
                    const newLines = [...this.state.lines];
                    newLines.splice(lineIndex + 1, 0, ...result.detail_lines);
                    this.state.lines = newLines;
                }
            }
        } catch (error) {
            console.error("Error loading detail lines:", error);
        }
    }

    async exportXlsx() {
        const options = JSON.stringify(this.state.options);
        const url = `/payroll/report/export_xlsx?report_model=${this.reportModel}&options=${encodeURIComponent(options)}`;
        window.location.href = url;
    }

    async exportPdf() {
        const options = JSON.stringify(this.state.options);
        const url = `/payroll/report/export_pdf?report_model=${this.reportModel}&options=${encodeURIComponent(options)}`;
        window.open(url, '_blank');
    }

    async openRecord(line) {
        if (line.model && line.res_id) {
            await this.actionService.doAction({
                type: 'ir.actions.act_window',
                res_model: line.model,
                res_id: line.res_id,
                views: [[false, 'form']],
                target: 'current',
            });
        }
    }

    formatValue(value, columnType) {
        if (value === null || value === undefined || value === '') {
            return '';
        }

        switch (columnType) {
            case 'monetary':
                return new Intl.NumberFormat('en-CA', {
                    style: 'currency',
                    currency: 'CAD',
                }).format(value);
            case 'float':
                return new Intl.NumberFormat('en-CA', {
                    minimumFractionDigits: 2,
                    maximumFractionDigits: 2,
                }).format(value);
            case 'integer':
                return Math.round(value).toString();
            case 'date':
                if (value) {
                    return new Date(value).toLocaleDateString('en-CA');
                }
                return '';
            case 'percentage':
                return `${(value * 100).toFixed(2)}%`;
            default:
                return String(value);
        }
    }

    getLineClass(line) {
        const classes = [];
        if (line.class) {
            classes.push(line.class);
        }
        if (line.level < 0) {
            classes.push('o_payroll_report_total');
        }
        if (line.level > 0) {
            classes.push('o_payroll_report_detail');
        }
        return classes.join(' ');
    }

    goBack() {
        this.actionService.doAction({
            type: 'ir.actions.client',
            tag: 'fusion_payroll.report_hub',
        });
    }
}

// Register the component as a client action
registry.category("actions").add("fusion_payroll.payroll_report_action", PayrollReportAction);
