# -*- coding: utf-8 -*-
import logging
from datetime import datetime, timedelta, date

from odoo import models, fields, api
from odoo.addons.resource.models.utils import HOURS_PER_DAY
from odoo.tools.float_utils import float_round
from odoo.tools.translate import _

logger = logging.getLogger(__name__)

DEFAULT_DAYS = 7


class HolidayRequest(models.Model):
    _inherit = "hr.leave"

    def _get_duration(self, check_leave_type=True, resource_calendar=None):
        if self.leave_type_request_unit == "c_day":
            return self.employee_id.get_all_days_data(
                self.date_from, self.date_to, self.holiday_status_id.exclude_holidays
            )
        else:
            return super()._get_duration(check_leave_type, resource_calendar)

    working_hours_display = fields.Float(
        "Working hours",
        help="Working hours amount in selected period",
        compute="_compute_working_hours_display",
        copy=False,
        readonly=True,
    )

    @staticmethod
    def compute_work_weekends(date_from, date_to, collection):
        days = set()

        for event in collection:
            if (
                date_from
                and event.date_to < date_from.date()
                or date_to
                and event.date_from > date_to.date()
            ):
                continue

            start = max(event.date_from, date_from.date())
            until = min(event.date_to, date_to.date())

            if event.type_transfer_day == "is_workday":
                for i in range((until - start + timedelta(1)).days):
                    today = start + timedelta(i)
                    days.add(today)
            else:
                for i in range((until - start + timedelta(1)).days):
                    today = start + timedelta(i)
                    # weekends check
                    if today.weekday() != 5 and today.weekday() != 6:
                        days.add(today)
        return timedelta(len(days)).days

    @api.depends("number_of_days", "date_from", "date_to")
    def _compute_working_hours_display(self):
        for holiday in self:
            calendar = (
                holiday.employee_id.resource_calendar_id
                or self.env.user.company_id.resource_calendar_id
            )
            count_work_weekends = holiday.compute_work_weekends(
                holiday.date_from,
                holiday.date_to,
                self.env["holidays.calendar.leaves"].search(
                    [
                        ("type_transfer_day", "=", "is_workday"),
                    ]
                ),
            )
            count_non_working_days = holiday.compute_work_weekends(
                holiday.date_from,
                holiday.date_to,
                self.env["holidays.calendar.leaves"].search(
                    [
                        ("type_transfer_day", "=", "is_day_off"),
                    ]
                ),
            )
            count_holidays = holiday.compute_work_weekends(
                holiday.date_from,
                holiday.date_to,
                self.env["holidays.calendar.leaves"].search(
                    [
                        ("type_transfer_day", "=", "is_holiday"),
                    ]
                ),
            )

            if holiday.date_from and holiday.date_to:
                date_start = datetime(
                    year=holiday.date_from.year,
                    month=holiday.date_from.month,
                    day=holiday.date_from.day,
                    hour=0,
                    minute=0,
                    second=0,
                )
                date_end = datetime(
                    year=holiday.date_to.year,
                    month=holiday.date_to.month,
                    day=holiday.date_to.day,
                    hour=23,
                    minute=59,
                    second=59,
                )
                number_of_hours = calendar.get_work_hours_count(
                    date_start, date_end, compute_leaves=False
                )
                holiday.working_hours_display = number_of_hours + HOURS_PER_DAY * (
                    count_work_weekends - count_non_working_days - count_holidays
                )
            else:
                holiday.working_hours_display = 0

    @api.depends("number_of_hours_display", "number_of_days_display")
    def _compute_duration_display(self):
        for leave in self:
            amount = (
                float_round(leave.number_of_hours_display, precision_digits=2)
                if leave.leave_type_request_unit == "hour"
                else float_round(leave.number_of_days_display, precision_digits=2)
            )
            if leave.leave_type_request_unit == "c_day":
                units = _("calendar day(s)")
            elif leave.leave_type_request_unit == "hour":
                units = _("hour(s)")
            else:
                units = _("working day(s)")
            leave.duration_display = "%g %s" % (amount, units)

    @staticmethod
    def notify_before(leave):
        """Checks whether days_before_holidays is set, if it's not, use DEFAULT_DAYS"""
        return leave.holiday_status_id.days_before_holidays or DEFAULT_DAYS

    def _check_users_holidays(self):
        """
        Method calls every day and checks the planned holidays.
        If needed, an email notification to the responsible employee will be sent.
        """
        leaves = self.env["hr.leave"].search(
            [
                ("holiday_status_id.notify_before_start_holidays", "=", True),
                ("holiday_status_id.responsible_employee_to_notify_id", "!=", None),
                ("date_from", ">=", date.today()),
            ]
        )

        for leave in leaves:
            days_before_holidays = self.notify_before(leave)
            holidays_start_date = leave.date_from

            if (
                holidays_start_date - timedelta(days=days_before_holidays)
            ).date() == date.today():
                template_name = "hr_holidays_ru.holidays_notification_template"
                template = self.env.ref(template_name)
                template.send_mail(leave.id)

    @staticmethod
    def append_number_by_type(leave, res):
        if leave.leave_type_request_unit == "c_day":
            res.append(
                (
                    leave.id,
                    _("%s : %.2f Calendar day(s)")
                    % (
                        leave.name or leave.holiday_status_id.name,
                        leave.number_of_days,
                    ),
                )
            )
        elif leave.leave_type_request_unit == "hour":
            res.append(
                (
                    leave.id,
                    _("%s : %.2f hour(s)")
                    % (
                        leave.name or leave.holiday_status_id.name,
                        leave.number_of_hours_display,
                    ),
                )
            )
        else:
            res.append(
                (
                    leave.id,
                    _("%s : %.2f Working day(s)")
                    % (
                        leave.name or leave.holiday_status_id.name,
                        leave.number_of_days,
                    ),
                )
            )

    @staticmethod
    def append_number_by_type_without_short_name(leave, res):
        if leave.holiday_type == "company":
            target = leave.mode_company_id.name
        elif leave.holiday_type == "department":
            target = leave.department_id.name
        elif leave.holiday_type == "category":
            target = leave.category_id.name
        else:
            target = leave.employee_id.name

        if leave.leave_type_request_unit == "c_day":
            res.append(
                (
                    leave.id,
                    _("%s on %s : %.2f Calendar day(s)")
                    % (
                        target,
                        leave.holiday_status_id.name,
                        leave.number_of_days,
                    ),
                )
            )
        elif leave.leave_type_request_unit == "hour":
            res.append(
                (
                    leave.id,
                    _("%s on %s : %.2f hour(s)")
                    % (
                        target,
                        leave.holiday_status_id.name,
                        leave.number_of_hours_display,
                    ),
                )
            )
        else:
            res.append(
                (
                    leave.id,
                    _("%s on %s : %.2f Working day(s)")
                    % (
                        target,
                        leave.holiday_status_id.name,
                        leave.number_of_days,
                    ),
                )
            )

    def name_get(self):
        res = []
        for leave in self:
            if self.env.context.get("short_name"):
                self.append_number_by_type(leave, res)
            else:
                self.append_number_by_type_without_short_name(leave, res)
        return res