# Copyright 2018 Graeme Gellatly
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from dateutil.relativedelta import relativedelta

from odoo import api, fields, models
from odoo.osv import expression


class StatementCommon(models.AbstractModel):
    _name = "statement.common.wizard"
    _description = "Statement Reports Common Wizard"

    name = fields.Char()
    company_id = fields.Many2one(
        comodel_name="res.company",
        default=lambda self: self.env.company,
        string="Company",
        required=True,
    )
    date_end = fields.Date(required=True, default=fields.Date.context_today)
    show_aging_buckets = fields.Boolean(default=True)
    show_only_overdue = fields.Boolean(
        help="Show only lines due before the selected date",
    )
    number_partner_ids = fields.Integer(
        default=lambda self: len(self._context["active_ids"])
    )
    filter_partners_non_due = fields.Boolean(
        string="Don't show partners with no due entries", default=True
    )
    filter_negative_balances = fields.Boolean("Exclude Negative Balances", default=True)

    aging_type = fields.Selection(
        [("days", "Age by Days"), ("months", "Age by Months")],
        string="Aging Method",
        default="days",
        required=True,
    )

    account_type = fields.Selection(
        [("asset_receivable", "Receivable"), ("liability_payable", "Payable")],
        default="asset_receivable",
    )
    excluded_accounts_selector = fields.Char(
        string="Accounts to exclude",
        help="Select account codes to be excluded "
        "with a comma-separated list of expressions like 70%.",
    )

    @api.model
    def _get_excluded_accounts_domain(self, selector):
        """Convert an account codes selector to a domain to search accounts.

        The selector is a comma-separated list of expressions like 70%.
        The algorithm is the same as
        AccountingExpressionProcessor._account_codes_to_domain
        of `mis_builder` module.
        """
        if not selector:
            selector = ""
        domains = []
        for account_code in selector.split(","):
            account_code = account_code.strip()
            if "%" in account_code:
                domains.append(
                    [
                        ("code", "=like", account_code),
                    ]
                )
            else:
                domains.append(
                    [
                        ("code", "=", account_code),
                    ]
                )
        return expression.OR(domains)

    def _get_excluded_accounts(self):
        self.ensure_one()
        domain = self._get_excluded_accounts_domain(self.excluded_accounts_selector)
        return self.env["account.account"].search(domain)

    @api.onchange("aging_type")
    def onchange_aging_type(self):
        if self.aging_type == "months":
            self.date_end = fields.Date.context_today(self).replace(
                day=1
            ) - relativedelta(days=1)
        else:
            self.date_end = fields.Date.context_today(self)

    def _prepare_statement(self):
        self.ensure_one()
        return {
            "date_end": self.date_end,
            "company_id": self.company_id.id,
            "partner_ids": self._context["active_ids"],
            "show_aging_buckets": self.show_aging_buckets,
            "show_only_overdue": self.show_only_overdue,
            "filter_non_due_partners": self.filter_partners_non_due,
            "account_type": self.account_type,
            "aging_type": self.aging_type,
            "filter_negative_balances": self.filter_negative_balances,
            "excluded_accounts_ids": self._get_excluded_accounts().ids,
        }

    def button_export_html(self):
        self.ensure_one()
        report_type = "qweb-html"
        return self._export(report_type)

    def button_export_pdf(self):
        self.ensure_one()
        report_type = "qweb-pdf"
        return self._export(report_type)

    def button_export_xlsx(self):
        self.ensure_one()
        report_type = "xlsx"
        return self._export(report_type)
