# -*- coding: utf-8 -*-
"""
Fusion Payroll Dashboard
========================
Modern dashboard with statistics, quick actions, and charts.
"""

from odoo import api, fields, models, _
from datetime import date
from dateutil.relativedelta import relativedelta


class PayrollDashboard(models.Model):
    """
    Dashboard model for Fusion Payroll.
    This is a singleton model that provides computed statistics.
    """
    _name = 'fusion.payroll.dashboard'
    _description = 'Fusion Payroll Dashboard'

    name = fields.Char(default='Fusion Payroll Dashboard')
    company_id = fields.Many2one(
        'res.company',
        default=lambda self: self.env.company,
    )
    
    # ==================== STATISTICS ====================
    
    # Employee Stats
    total_employees = fields.Integer(
        string='Total Employees',
        compute='_compute_employee_stats',
    )
    active_employees = fields.Integer(
        string='Active Employees',
        compute='_compute_employee_stats',
    )
    on_leave_employees = fields.Integer(
        string='On Leave',
        compute='_compute_employee_stats',
    )
    terminated_employees = fields.Integer(
        string='Terminated',
        compute='_compute_employee_stats',
    )
    
    # Payroll Stats
    payroll_this_month = fields.Monetary(
        string='Payroll This Month',
        currency_field='currency_id',
        compute='_compute_payroll_stats',
    )
    payroll_this_year = fields.Monetary(
        string='Payroll This Year',
        currency_field='currency_id',
        compute='_compute_payroll_stats',
    )
    payroll_last_month = fields.Monetary(
        string='Payroll Last Month',
        currency_field='currency_id',
        compute='_compute_payroll_stats',
    )
    payroll_count_this_month = fields.Integer(
        string='Payslips This Month',
        compute='_compute_payroll_stats',
    )
    avg_payroll_per_employee = fields.Monetary(
        string='Avg Pay Per Employee',
        currency_field='currency_id',
        compute='_compute_payroll_stats',
    )
    
    # Trend indicators
    payroll_trend = fields.Float(
        string='Payroll Trend (%)',
        compute='_compute_payroll_stats',
        help='Percentage change from last month',
    )
    
    currency_id = fields.Many2one(
        'res.currency',
        default=lambda self: self.env.company.currency_id,
    )
    
    # ==================== COMPUTED METHODS ====================
    
    @api.depends('company_id')
    def _compute_employee_stats(self):
        for dashboard in self:
            Employee = self.env['hr.employee']
            company_domain = [('company_id', '=', dashboard.company_id.id)]
            
            dashboard.total_employees = Employee.search_count(company_domain)
            
            # Check if employment_status field exists
            if 'employment_status' in Employee._fields:
                dashboard.active_employees = Employee.search_count(
                    company_domain + [('employment_status', '=', 'active')]
                )
                dashboard.on_leave_employees = Employee.search_count(
                    company_domain + [('employment_status', '=', 'on_leave')]
                )
                dashboard.terminated_employees = Employee.search_count(
                    company_domain + [('employment_status', '=', 'terminated')]
                )
            else:
                dashboard.active_employees = Employee.search_count(
                    company_domain + [('active', '=', True)]
                )
                dashboard.on_leave_employees = 0
                dashboard.terminated_employees = Employee.search_count(
                    company_domain + [('active', '=', False)]
                )
    
    @api.depends('company_id')
    def _compute_payroll_stats(self):
        today = date.today()
        month_start = today.replace(day=1)
        year_start = today.replace(month=1, day=1)
        last_month_start = month_start - relativedelta(months=1)
        last_month_end = month_start - relativedelta(days=1)
        
        for dashboard in self:
            Payslip = self.env['hr.payslip']
            company_domain = [
                ('company_id', '=', dashboard.company_id.id),
                ('state', 'in', ['done', 'paid']),
            ]
            
            # This month
            month_payslips = Payslip.search(
                company_domain + [
                    ('date_from', '>=', month_start),
                    ('date_to', '<=', today),
                ]
            )
            dashboard.payroll_this_month = sum(month_payslips.mapped('net_wage'))
            dashboard.payroll_count_this_month = len(month_payslips)
            
            # This year
            year_payslips = Payslip.search(
                company_domain + [
                    ('date_from', '>=', year_start),
                ]
            )
            dashboard.payroll_this_year = sum(year_payslips.mapped('net_wage'))
            
            # Last month (for trend)
            last_month_payslips = Payslip.search(
                company_domain + [
                    ('date_from', '>=', last_month_start),
                    ('date_to', '<=', last_month_end),
                ]
            )
            dashboard.payroll_last_month = sum(last_month_payslips.mapped('net_wage'))
            
            # Trend calculation
            if dashboard.payroll_last_month > 0:
                dashboard.payroll_trend = (
                    (dashboard.payroll_this_month - dashboard.payroll_last_month) 
                    / dashboard.payroll_last_month * 100
                )
            else:
                dashboard.payroll_trend = 0
            
            # Average per employee
            if dashboard.active_employees > 0 and dashboard.payroll_this_month > 0:
                dashboard.avg_payroll_per_employee = (
                    dashboard.payroll_this_month / dashboard.active_employees
                )
            else:
                dashboard.avg_payroll_per_employee = 0
    
    # ==================== ACTION METHODS ====================
    
    def action_run_payroll(self):
        """Open Run Payroll wizard."""
        action = self.env['run.payroll.wizard'].action_open_run_payroll()
        # Ensure edit is enabled (override dashboard context)
        if action.get('context'):
            ctx = action['context']
            if isinstance(ctx, str):
                try:
                    ctx = eval(ctx, {'uid': self.env.uid})
                except:
                    ctx = {}
            if not isinstance(ctx, dict):
                ctx = {}
        else:
            ctx = {}
        ctx.update({'create': True, 'edit': True, 'delete': True})
        action['context'] = ctx
        return action
    
    def _get_action_context(self, action):
        """Parse action context and add create/edit/delete permissions."""
        ctx = action.get('context', {})
        if isinstance(ctx, str):
            try:
                ctx = eval(ctx, {'uid': self.env.uid, 'active_id': self.id})
            except:
                ctx = {}
        if not isinstance(ctx, dict):
            ctx = {}
        ctx.update({'create': True, 'edit': True, 'delete': True})
        return ctx
    
    def action_view_employees(self):
        """Open All Employees view using existing action."""
        action = self.env['ir.actions.act_window']._for_xml_id('fusion_payroll.action_fusion_employees')
        action['context'] = self._get_action_context(action)
        return action
    
    def action_cra_remittance(self):
        """Open CRA Remittance view using existing action."""
        action = self.env['ir.actions.act_window']._for_xml_id('fusion_payroll.action_fusion_tax_remittances')
        action['context'] = self._get_action_context(action)
        return action
    
    def action_t4_slips(self):
        """Open T4 Slips view using existing action."""
        action = self.env['ir.actions.act_window']._for_xml_id('fusion_payroll.action_fusion_t4_slips')
        action['context'] = self._get_action_context(action)
        return action
    
    def action_roe(self):
        """Open Record of Employment view using existing action."""
        action = self.env['ir.actions.act_window']._for_xml_id('fusion_payroll.action_fusion_roe')
        action['context'] = self._get_action_context(action)
        return action
    
    def action_reports(self):
        """Open Reports hub using existing action."""
        try:
            action = self.env['ir.actions.act_window']._for_xml_id('fusion_payroll.action_fusion_report_hub_page')
            return action
        except ValueError:
            # Fallback if action doesn't exist
            return {
                'type': 'ir.actions.act_window',
                'name': _('Payroll Reports'),
                'res_model': 'ir.actions.report',
                'view_mode': 'kanban,list',
                'domain': [('model', 'like', 'hr.payslip')],
            }
    
    def action_settings(self):
        """Open Fusion Payroll Settings."""
        # Get or create settings record
        settings = self.env['payroll.config.settings'].get_settings()
        return {
            'type': 'ir.actions.act_window',
            'name': _('Fusion Payroll Settings'),
            'res_model': 'payroll.config.settings',
            'res_id': settings.id,
            'view_mode': 'form',
            'target': 'current',
            'context': {'form_view_initial_mode': 'edit'},
        }
    
    # ==================== SINGLETON PATTERN ====================
    
    @api.model
    def get_dashboard(self):
        """Get or create the dashboard singleton."""
        dashboard = self.search([
            ('company_id', '=', self.env.company.id)
        ], limit=1)
        
        if not dashboard:
            dashboard = self.create({
                'name': 'Fusion Payroll Dashboard',
                'company_id': self.env.company.id,
            })
        
        return dashboard
    
    @api.model
    def action_open_dashboard(self):
        """Open the dashboard."""
        dashboard = self.get_dashboard()
        return {
            'type': 'ir.actions.act_window',
            'name': _('Fusion Payroll'),
            'res_model': 'fusion.payroll.dashboard',
            'res_id': dashboard.id,
            'view_mode': 'form',
            'target': 'current',
            'flags': {'mode': 'readonly'},
        }


class PayrollDashboardStats(models.Model):
    """
    Monthly payroll statistics for graphing.
    This model stores aggregated monthly data for trend charts.
    """
    _name = 'fusion.payroll.stats'
    _description = 'Payroll Statistics'
    _order = 'year desc, month desc'
    
    name = fields.Char(compute='_compute_name', store=True)
    company_id = fields.Many2one('res.company', required=True)
    year = fields.Integer(required=True)
    month = fields.Integer(required=True)
    month_name = fields.Char(compute='_compute_name', store=True)
    
    total_payroll = fields.Monetary(currency_field='currency_id')
    total_gross = fields.Monetary(currency_field='currency_id')
    total_taxes = fields.Monetary(currency_field='currency_id')
    employee_count = fields.Integer()
    payslip_count = fields.Integer()
    
    currency_id = fields.Many2one(
        'res.currency',
        default=lambda self: self.env.company.currency_id,
    )
    
    @api.depends('year', 'month')
    def _compute_name(self):
        month_names = [
            '', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
        ]
        for stat in self:
            if stat.month and stat.year:
                stat.month_name = month_names[stat.month]
                stat.name = f"{month_names[stat.month]} {stat.year}"
            else:
                stat.month_name = ''
                stat.name = 'New'
    
    @api.model
    def refresh_stats(self):
        """Refresh statistics from payslip data."""
        today = date.today()
        company = self.env.company
        
        # Get data for last 12 months
        for i in range(12):
            target_date = today - relativedelta(months=i)
            year = target_date.year
            month = target_date.month
            
            month_start = target_date.replace(day=1)
            month_end = (month_start + relativedelta(months=1)) - relativedelta(days=1)
            
            # Find payslips for this month
            payslips = self.env['hr.payslip'].search([
                ('company_id', '=', company.id),
                ('state', 'in', ['done', 'paid']),
                ('date_from', '>=', month_start),
                ('date_to', '<=', month_end),
            ])
            
            # Find or create stat record
            stat = self.search([
                ('company_id', '=', company.id),
                ('year', '=', year),
                ('month', '=', month),
            ], limit=1)
            
            vals = {
                'company_id': company.id,
                'year': year,
                'month': month,
                'total_payroll': sum(payslips.mapped('net_wage')),
                'total_gross': sum(payslips.mapped('basic_wage')) if 'basic_wage' in payslips._fields else 0,
                'total_taxes': 0,  # Would need to sum tax lines
                'employee_count': len(set(payslips.mapped('employee_id.id'))),
                'payslip_count': len(payslips),
            }
            
            if stat:
                stat.write(vals)
            else:
                self.create(vals)
        
        return True
