# © 2019 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from datetime import datetime, time

from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError


class ScopHrTimesheet(models.Model):
    _inherit = "account.analytic.line"

    def _default_ur(self):
        return self.env["res.company"]._ur_default_get()

    # Inherited fields
    name = fields.Char(required=False)
    partner_id = fields.Many2one(required=True)

    # New fields
    cgscop_timesheet_code_id = fields.Many2one(
        related="project_id.cgscop_timesheet_code_id",
        string="Code Activité National",
        store=True,
    )
    ur_financial_system_id = fields.Many2one(
        comodel_name="ur.financial.system", string="Dispositif Financier"
    )
    ur_regional_convention_id = fields.Many2one(
        comodel_name="ur.regional.convention", string="Convention Régionale"
    )
    ur_id = fields.Many2one(
        "union.regionale",
        string="Union Régionale",
        index=True,
        ondelete="restrict",
        default=_default_ur,
    )
    sheet_id = fields.Many2one(
        comodel_name="cgscop.timesheet.sheet",
        string="Feuille de temps",
        readonly=True,
        copy=False,
    )
    state = fields.Selection(
        [
            ("to_report", "A rapporter"),
            ("draft", "Brouillon"),
            ("submit", "Soumis"),
            ("valid", "Validé"),
        ],
        compute="_compute_state",
        string="Statut",
        copy=False,
        index=True,
        readonly=True,
        store=True,
    )
    ur_financial_system_nb = fields.Integer(
        string="Nb Dispositifs Financiers", compute="_compute_ur_system_nb"
    )
    ur_regional_convention_nb = fields.Integer(
        string="Nb conventions régionales", compute="_compute_ur_system_nb"
    )
    is_present = fields.Boolean("Présentiel")
    location = fields.Selection(
        [
            ("R", "Rendez-vous"),
            ("D", "Déplacement"),
            ("B", "Bureau"),
        ],
        string="Lieu",
    )
    justificatifs = fields.Char(string="Justificatifs", required=False)
    is_overtime = fields.Boolean(
        string="Heures supplémentaires",
        default=False,
    )
    is_overtime_allowed = fields.Boolean(
        string="Heures supplémentaires autorisées",
        compute="_compute_overtime_allowed",
    )
    travel_time = fields.Float(
        string="Temps déplacement",
    )
    is_travel_time_allowed = fields.Boolean(
        string="Temps de déplacement autorisé",
        compute="_compute_travel_time_allowed",
    )
    calendar_l1 = fields.Char(
        string="Ligne 1 calendrier",
        compute="_compute_calendar_l1",
    )
    calendar_l2 = fields.Char(
        string="Ligne 2 calendrier",
        compute="_compute_calendar_l2",
    )

    # ------------------------------------------------------
    # Compute Functions
    # ------------------------------------------------------
    @api.depends("ur_id")
    def _compute_overtime_allowed(self):
        for rec in self:
            rec.is_overtime_allowed = self.env.company.overtime_working

    @api.depends("ur_id")
    def _compute_travel_time_allowed(self):
        for rec in self:
            rec.is_travel_time_allowed = self.env.company.use_travel_time

    @api.depends("ur_id")
    def _compute_ur_system_nb(self):
        for timesheet in self:
            # Calcul nombre de dispositifs financiers
            financial_system = timesheet.env["ur.financial.system"].search(
                [("ur_id", "=", timesheet.ur_id.id)]
            )
            timesheet.ur_financial_system_nb = len(financial_system)
            # Calcul nombre de conventions
            regional_convention = timesheet.env["ur.regional.convention"].search(
                [("ur_id", "=", timesheet.ur_id.id)]
            )
            timesheet.ur_regional_convention_nb = len(regional_convention)

    @api.depends("sheet_id", "sheet_id.state")
    def _compute_state(self):
        for timesheet in self:
            if not timesheet.sheet_id:
                timesheet.state = "to_report"
            else:
                timesheet.state = timesheet.sheet_id.state

    @api.depends("project_id", "partner_id")
    def _compute_calendar_l1(self):
        for ts in self:
            ts.calendar_l1 = ""
            if ts.project_id:
                ts.calendar_l1 += ts.project_id.name + ", "
            if ts.partner_id:
                ts.calendar_l1 += ts.partner_id.name

    @api.depends("unit_amount")
    def _compute_calendar_l2(self):
        for ts in self:
            ts.calendar_l2 = "Durée : " + str(ts.unit_amount) + " heure(s)"

    # ------------------------------------------------------
    # Override le _rec_name
    # ------------------------------------------------------
    @api.depends("project_id", "partner_id")
    def name_get(self):
        result = []
        for ts in self:
            name = ts.calendar_l1
            result.append((ts.id, name))
        return result

    # ------------------------------------------------------
    # OnChange Functions
    # ------------------------------------------------------
    @api.onchange("project_id")
    def onchange_project_id(self):
        self.partner_id = self.project_id.partner_id

    @api.onchange("partner_id")
    def onchange_partner_id(self):
        # affiche le Dispositif Financier par défaut sur la LdT
        # si il n'y a pas de date limite du dispositif
        # ou si la date de la Ldt est inférieure à la date limite du dispositif
        if (
            not self.partner_id.ur_financial_system_date
            or self.date <= self.partner_id.ur_financial_system_date
        ):
            self.ur_financial_system_id = self.partner_id.ur_financial_system_id

        # affiche la Convention par défaut sur la LdT
        # si il n'y a pas de date limite de la convention
        # ou si la date de la LdT est inférieure à la date limite de la convention
        if (
            not self.partner_id.ur_regional_convention_date
            or self.date <= self.partner_id.ur_regional_convention_date
        ):
            self.ur_regional_convention_id = self.partner_id.ur_regional_convention_id

    # ------------------------------------------------------
    # Contrains
    # ------------------------------------------------------
    @api.constrains("unit_amount", "date")
    def _check_hours(self):
        for record in self:
            if record.project_id:
                lines = self.search(
                    [
                        ("date", "=", record.date),
                        ("employee_id", "=", record.employee_id.id),
                    ]
                )
                total = sum(lines.mapped("unit_amount"))
                if (
                    not self.env.company.day_working
                    and total > self.env.company.day_duration
                ):
                    raise ValidationError(
                        _(
                            "Vous ne pouvez imputer plus de %sh sur la même journée.\n"
                            "Journée du %s"
                        )
                        % (
                            self.env.company.day_duration,
                            record.date.strftime("%d/%m/%Y"),
                        )
                    )

    @api.constrains("date")
    def _check_weekday(self):

        if self.env.company.weekend_working:
            return

        for line in self:
            dt = datetime.combine(line.date, time(12, 00))
            holiday = self.env["resource.calendar.leaves"].search(
                [
                    "|",
                    ("company_id", "=", False),
                    ("company_id", "=", self.env.company.id),
                    ("date_from", "<=", dt),
                    ("date_to", ">=", dt),
                    ("resource_id", "=", False),
                ]
            )
            if not line.holiday_id and (line.date.weekday() in (5, 6) or holiday):
                raise ValidationError(
                    _(
                        "Vous ne pouvez imputer du temps sur un weekend "
                        "ou un jour férié."
                    )
                )

    # ------------------------------------------------------
    # Override ORM
    # ------------------------------------------------------
    def unlink(self):
        for timesheet in self:
            if timesheet.state in ["submit", "valid"]:
                raise UserError(
                    _(
                        "Vous ne pouvez pas supprimer une "
                        "ligne de temps soumise ou validée"
                    )
                )
        super(ScopHrTimesheet, self).unlink()

    # ------------------------------------------------------
    # Actions
    # ------------------------------------------------------
    def action_submit_timesheet_lines(self):
        """
        Crée une feuille de temps avec les lignes sélectionnées
        """
        if any(time.state != "to_report" or time.sheet_id for time in self):
            raise UserError(_("Vous ne pouvez pas insérer 2 fois la même ligne !"))
        if len(self.mapped("employee_id")) != 1:
            raise UserError(
                _(
                    "Il ne peut y avoir plusieurs employés dans une "
                    "même feuille de temps."
                )
            )

        return {
            "name": "New Expense Report",
            "type": "ir.actions.act_window",
            "view_mode": "form",
            "res_model": "cgscop.timesheet.sheet",
            "target": "current",
            "context": {
                "default_timesheet_line_ids": self.ids,
                "default_employee_id": self[0].employee_id.id,
                "default_name": self[0].name if len(self) == 1 else "",
            },
        }

    # ------------------------------------------------------
    # Modification du context pour cacher les colonnes
    # ------------------------------------------------------
    @api.model
    def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
        custom_context = self.env.context.copy()

        current_ur_id = self.env.context['current_ur_id']
        nbfs = self.env["ur.financial.system"].search([("ur_id", "=", current_ur_id)])
        if len(nbfs) == 0:
            custom_context['hide_financial_system'] = True
        nbrc = self.env["ur.regional.convention"].search([("ur_id", "=", current_ur_id)])
        if len(nbrc) == 0:
            custom_context['hide_regional_convention'] = True

        overtime_allowed = self.env.company.overtime_working
        if not overtime_allowed:
            custom_context['hide_overtime'] = True
        travel_time_allowed = self.env.company.use_travel_time
        if not travel_time_allowed:
            custom_context['hide_travel_time'] = True

        res = super(ScopHrTimesheet, self.with_context(custom_context)).fields_view_get(
            view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)

        return res