# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)

from datetime import datetime, timedelta
from odoo import models, fields, api


class HrEmployee(models.Model):
    _inherit = 'hr.employee'

    x_fclk_default_location_id = fields.Many2one(
        'fusion.clock.location',
        string='Default Clock Location',
        help="The default location shown on this employee's clock page.",
    )
    x_fclk_enable_clock = fields.Boolean(
        string='Enable Fusion Clock',
        default=True,
        help="If unchecked, this employee cannot use the Fusion Clock portal/systray.",
    )
    x_fclk_break_minutes = fields.Float(
        string='Custom Break (min)',
        default=0.0,
        help="Override default break duration for this employee. 0 = use shift or company default.",
    )

    # Shift scheduling
    x_fclk_shift_id = fields.Many2one(
        'fusion.clock.shift',
        string='Work Shift',
        help="Assigned shift schedule. Leave empty to use global defaults.",
    )

    # Pending reason enforcement
    x_fclk_pending_reason = fields.Boolean(
        string='Pending Reason Required',
        default=False,
        help="If set, employee must explain a missed clock-out before clocking in again.",
    )

    # Kiosk PIN
    x_fclk_kiosk_pin = fields.Char(
        string='Kiosk PIN',
        help="PIN code for kiosk clock-in/out identification.",
        groups="fusion_clock.group_fusion_clock_manager",
    )

    # On-time streak
    x_fclk_ontime_streak = fields.Integer(
        string='On-Time Streak',
        default=0,
        help="Consecutive workdays clocked in on time.",
    )

    # Absence tracking (computed)
    x_fclk_absences_this_month = fields.Integer(
        string='Absences This Month',
        compute='_compute_absence_counts',
    )
    x_fclk_absences_this_year = fields.Integer(
        string='Absences This Year',
        compute='_compute_absence_counts',
    )

    # Overtime tracking (computed)
    x_fclk_overtime_this_week = fields.Float(
        string='Overtime This Week (h)',
        compute='_compute_overtime',
    )
    x_fclk_overtime_this_month = fields.Float(
        string='Overtime This Month (h)',
        compute='_compute_overtime',
    )

    # Activity log relation
    x_fclk_activity_log_ids = fields.One2many(
        'fusion.clock.activity.log',
        'employee_id',
        string='Activity Logs',
    )

    # Leave request relation
    x_fclk_leave_request_ids = fields.One2many(
        'fusion.clock.leave.request',
        'employee_id',
        string='Leave Requests',
    )

    # Correction request relation
    x_fclk_correction_ids = fields.One2many(
        'fusion.clock.correction',
        'employee_id',
        string='Correction Requests',
    )

    # Reminder tracking
    x_fclk_last_reminder_date = fields.Date(
        string='Last Reminder Date',
        help="Tracks the last date a reminder was sent to avoid duplicates.",
    )

    def _get_fclk_break_minutes(self):
        """Return effective break minutes for this employee.
        Priority: employee override > shift > global setting.
        """
        self.ensure_one()
        if self.x_fclk_break_minutes > 0:
            return self.x_fclk_break_minutes
        if self.x_fclk_shift_id and self.x_fclk_shift_id.break_minutes > 0:
            return self.x_fclk_shift_id.break_minutes
        return float(
            self.env['ir.config_parameter'].sudo().get_param(
                'fusion_clock.default_break_minutes', '30'
            )
        )

    def _get_fclk_scheduled_times(self, date):
        """Return (scheduled_in_dt, scheduled_out_dt) for a given date.
        Uses employee shift if assigned, otherwise global settings.
        """
        self.ensure_one()
        if self.x_fclk_shift_id:
            in_hour = self.x_fclk_shift_id.start_time
            out_hour = self.x_fclk_shift_id.end_time
        else:
            ICP = self.env['ir.config_parameter'].sudo()
            in_hour = float(ICP.get_param('fusion_clock.default_clock_in_time', '9.0'))
            out_hour = float(ICP.get_param('fusion_clock.default_clock_out_time', '17.0'))

        in_h = int(in_hour)
        in_m = int((in_hour - in_h) * 60)
        out_h = int(out_hour)
        out_m = int((out_hour - out_h) * 60)

        scheduled_in = datetime.combine(date, datetime.min.time().replace(hour=in_h, minute=in_m))
        scheduled_out = datetime.combine(date, datetime.min.time().replace(hour=out_h, minute=out_m))
        return scheduled_in, scheduled_out

    def _get_fclk_scheduled_hours(self):
        """Return the expected work hours for this employee's shift."""
        self.ensure_one()
        if self.x_fclk_shift_id:
            return self.x_fclk_shift_id.scheduled_hours
        ICP = self.env['ir.config_parameter'].sudo()
        in_hour = float(ICP.get_param('fusion_clock.default_clock_in_time', '9.0'))
        out_hour = float(ICP.get_param('fusion_clock.default_clock_out_time', '17.0'))
        break_hrs = self._get_fclk_break_minutes() / 60.0
        return max((out_hour - in_hour) - break_hrs, 0.0)

    def _compute_absence_counts(self):
        ActivityLog = self.env['fusion.clock.activity.log'].sudo()
        today = fields.Date.today()
        month_start = today.replace(day=1)
        year_start = today.replace(month=1, day=1)

        for emp in self:
            emp.x_fclk_absences_this_month = ActivityLog.search_count([
                ('employee_id', '=', emp.id),
                ('log_type', '=', 'absent'),
                ('log_date', '>=', datetime.combine(month_start, datetime.min.time())),
            ])
            emp.x_fclk_absences_this_year = ActivityLog.search_count([
                ('employee_id', '=', emp.id),
                ('log_type', '=', 'absent'),
                ('log_date', '>=', datetime.combine(year_start, datetime.min.time())),
            ])

    def _compute_overtime(self):
        Attendance = self.env['hr.attendance'].sudo()
        today = fields.Date.today()
        week_start = today - timedelta(days=today.weekday())
        month_start = today.replace(day=1)

        for emp in self:
            week_atts = Attendance.search([
                ('employee_id', '=', emp.id),
                ('check_in', '>=', datetime.combine(week_start, datetime.min.time())),
                ('check_out', '!=', False),
            ])
            emp.x_fclk_overtime_this_week = sum(a.x_fclk_overtime_hours or 0 for a in week_atts)

            month_atts = Attendance.search([
                ('employee_id', '=', emp.id),
                ('check_in', '>=', datetime.combine(month_start, datetime.min.time())),
                ('check_out', '!=', False),
            ])
            emp.x_fclk_overtime_this_month = sum(a.x_fclk_overtime_hours or 0 for a in month_atts)
