# -*- coding: utf-8 -*-
from datetime import timedelta

from odoo import api, fields, models


class SoHelpdeskSla(models.Model):
    _name = 'so.helpdesk.sla'
    _description = 'Helpdesk SLA Policy'
    _order = 'team_id, sequence'

    name = fields.Char(required=True)
    active = fields.Boolean(default=True)
    sequence = fields.Integer(default=10)
    team_id = fields.Many2one(
        comodel_name='so.helpdesk.team',
        string='Team',
        required=True,
        ondelete='cascade',
        index=True,
    )
    stage_id = fields.Many2one(
        comodel_name='so.helpdesk.stage',
        string='Target Stage',
        required=True,
        domain="[('team_id', '=', team_id)]",
        help='Stage the ticket must reach within the SLA deadline.',
    )
    time_days = fields.Integer(string='Days', default=0)
    time_hours = fields.Float(string='Hours', default=4.0)
    priority = fields.Selection(
        selection=[
            ('0', 'Low'),
            ('1', 'Normal'),
            ('2', 'High'),
            ('3', 'Urgent'),
        ],
        string='Priority',
        help='Leave empty to apply to all priorities.',
    )
    ticket_type_id = fields.Many2one(
        comodel_name='so.helpdesk.ticket.type',
        string='Ticket Type',
        help='Leave empty to apply to all ticket types.',
    )
    exclude_stage_ids = fields.Many2many(
        comodel_name='so.helpdesk.stage',
        relation='so_helpdesk_sla_exclude_stage_rel',
        column1='sla_id',
        column2='stage_id',
        string='Excluded Stages',
        domain="[('team_id', '=', team_id)]",
        help='Time spent in these stages does not count toward the SLA.',
    )
    description = fields.Text()

    def _get_deadline_hours(self):
        self.ensure_one()
        return (self.time_days * 24) + self.time_hours


class SoHelpdeskSlaStatus(models.Model):
    _name = 'so.helpdesk.sla.status'
    _description = 'Helpdesk SLA Status'
    _order = 'deadline asc, id'

    ticket_id = fields.Many2one(
        comodel_name='so.helpdesk.ticket',
        string='Ticket',
        required=True,
        ondelete='cascade',
        index=True,
    )
    sla_id = fields.Many2one(
        comodel_name='so.helpdesk.sla',
        string='SLA Policy',
        required=True,
        ondelete='cascade',
    )
    stage_id = fields.Many2one(
        comodel_name='so.helpdesk.stage',
        related='sla_id.stage_id',
        store=True,
    )
    deadline = fields.Datetime(string='Deadline', index=True)
    reached_datetime = fields.Datetime(string='Reached On', readonly=True)
    status = fields.Selection(
        selection=[
            ('ongoing', 'In Progress'),
            ('reached', 'Reached'),
            ('failed', 'Failed'),
        ],
        string='Status',
        default='ongoing',
        required=True,
        index=True,
    )
    color = fields.Integer(compute='_compute_color')

    @api.depends('status', 'deadline')
    def _compute_color(self):
        now = fields.Datetime.now()
        for record in self:
            if record.status == 'reached':
                record.color = 10
            elif record.status == 'failed':
                record.color = 1
            elif record.deadline and record.deadline < now:
                record.color = 1
            else:
                record.color = 3

    @api.model
    def _generate_for_ticket(self, ticket):
        """Create SLA status lines for a ticket based on matching policies."""
        if not ticket.team_id:
            return
        domain = [('team_id', '=', ticket.team_id.id), ('active', '=', True)]
        if ticket.priority:
            domain += ['|', ('priority', '=', False), ('priority', '=', ticket.priority)]
        if ticket.ticket_type_id:
            domain += [
                '|',
                ('ticket_type_id', '=', False),
                ('ticket_type_id', '=', ticket.ticket_type_id.id),
            ]
        policies = self.env['so.helpdesk.sla'].search(domain)
        existing = ticket.sla_status_ids.mapped('sla_id')
        to_create = []
        for policy in policies - existing:
            deadline = fields.Datetime.now() + timedelta(hours=policy._get_deadline_hours())
            to_create.append({
                'ticket_id': ticket.id,
                'sla_id': policy.id,
                'deadline': deadline,
            })
        if to_create:
            self.create(to_create)

    def _mark_reached_if_applicable(self, ticket):
        """Mark SLA as reached when ticket hits the target stage."""
        for status in ticket.sla_status_ids.filtered(lambda s: s.status == 'ongoing'):
            if ticket.stage_id == status.sla_id.stage_id:
                status.write({
                    'status': 'reached',
                    'reached_datetime': fields.Datetime.now(),
                })

    @api.model
    def _cron_check_sla_failures(self):
        """Mark overdue ongoing SLAs as failed."""
        overdue = self.search([
            ('status', '=', 'ongoing'),
            ('deadline', '<', fields.Datetime.now()),
        ])
        overdue.write({'status': 'failed'})
