# Copyright 2023 Le Filament (https://le-filament.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from datetime import date

from dateutil.relativedelta import relativedelta

from odoo import api, fields, models


class HallContract(models.Model):
    _inherit = "hall.contract"

    # ------------------------------------------------------
    # Fields declaration
    # ------------------------------------------------------

    # ------------------------------------------------------
    # SQL Constrains
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Compute functions
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Action buttons
    # ------------------------------------------------------
    def show_overview(self):
        self.ensure_one()
        action = self.env["ir.actions.actions"]._for_xml_id(
            "festa_dashboard.hall_contract_overview_action"
        )
        action["context"] = {
            "active_id": self.id,
            "active_ids": self.ids,
            "active_test": False,
            "search_default_display_name": self.display_name,
        }
        return action

    @api.model
    def update_cashpad_values(self):
        self.search([("cashpad_id", "!=", False)]).get_sales()

    # ------------------------------------------------------
    # Common functions
    # ------------------------------------------------------
    def is_running(self, date_filter):
        """
        :param date date_filter: date de référence
        """
        self.ensure_one()
        if self.date_start <= date_filter and not self.date_end:
            return True
        elif self.date_start <= date_filter <= self.date_end:
            return True
        else:
            return False

    def get_overview(self):
        job_ids = (
            self.env["queue.job"]
            .sudo()
            .search(
                [
                    ("model_name", "=", "hall.contract"),
                    ("method_name", "=", "_import_sales"),
                    ("state", "in", ["pending", "enqueued", "started", "failed"]),
                ]
            )
        )
        return {
            "contract_ids": self,
            "hall_ids": self.mapped("hall_id"),
            "company_id": self.env.company,
            "sales": self.get_overview_sales(),
            "job_ids": job_ids,
        }

    def get_overview_sales(self):
        """
        Retourne les datas pour la vue QWEB
        """
        today = date.today()
        yesterday = date.today() - relativedelta(days=1)
        start_year = date(yesterday.year, 1, 1)
        start_month = date(yesterday.year, yesterday.month, 1)
        start_last_month = start_month - relativedelta(months=1)
        end_last_month = start_month - relativedelta(days=1)
        return {
            "yesterday": self._get_sale_amount(yesterday, yesterday),
            "last_year": self._get_sale_amount(
                yesterday.replace(year=yesterday.year - 1),
                yesterday.replace(year=yesterday.year - 1),
            ),
            "this_month": self._get_sale_amount(start_month, today),
            "last_month": self._get_sale_amount(start_last_month, end_last_month),
            "this_year": self._get_sale_amount(start_year, today),
            "target_month": self._get_target(today.year, today.month),
            "target_last_month": self._get_target(
                start_last_month.year, start_last_month.month
            ),
            "target_year": self._get_target(today.year),
            "revenue_detail": self._get_revenue_detail(),
            "day": yesterday,
            "month": start_month,
            "year": start_year,
        }

    def _get_sale_amount(self, start, end):
        """
        Retourne le montant HT des ventes en fonction de dates pour des contrats

        :param start date:
        :param end date:
        @returns float amount untaxed
        """
        sale_ids = self.sale_ids.search(
            [
                ("contract_id", "in", self.ids),
                ("day_date", ">=", start),
                ("day_date", "<=", end),
            ]
        )
        total_sales = sum(sale_ids.mapped("sales_excl_taxes"))
        total_receipts = sum(sale_ids.mapped("nb_receipts"))
        average_sales = total_sales / total_receipts if total_receipts > 0 else 0
        return {
            "total_sales": total_sales,
            "total_receipts": total_receipts,
            "average_sales": average_sales,
        }

    def _get_target(self, year, month=None):
        """
        :param int year:
        :param int month:
        """
        granularity = "month" if month else "year"
        month = month if month else 1
        start = date(year, month, 1)
        end = fields.Date.end_of(start, granularity)
        target_ids = self.target_ids.search(
            [
                ("contract_id", "in", self.ids),
                ("date_target", ">=", start),
                ("date_target", "<=", end),
            ]
        )
        return sum(target_ids.mapped("amount_untaxed_target"))

    def _get_revenue_detail(self):
        if len(self) != 1:
            return False

        today = fields.Date.today()
        start = today.replace(day=1) - relativedelta(months=12)
        end = today.replace(day=1)
        target_report_ids = self.env["hall.contract.target.report"].search(
            [
                ("contract_id", "=", self.id),
                ("day_date", ">=", start),
                ("day_date", "<=", end),
            ],
            order="day_date",
            limit=12,
        )
        return target_report_ids