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

import logging

import werkzeug

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

_logger = logging.getLogger(__name__)


class ResPartner(models.Model):
    _inherit = "res.partner"

    # ------------------------------------------------------
    # Fields declaration
    # ------------------------------------------------------
    is_portal = fields.Boolean("Est un utilisateur portail")
    # ------------------------------------------------------
    # SQL Constraints
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Default methods
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Computed fields / Search Fields
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Onchange / Constraints
    # ------------------------------------------------------

    # ------------------------------------------------------
    # CRUD methods (ORM overrides)
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Actions
    # ------------------------------------------------------
    def acces_portal_app(self):
        for partner in self:
            if not partner.email:
                raise UserError(
                    _(
                        "Vous devez renseigner une adresse e-mail "
                        "sur le contact pour la création d'un utilisateur."
                    )
                )
            group_portal = self.env.ref("base.group_portal")
            # Vérifier si le contact a un utilisateur lié
            user = (
                self.env["res.users"]
                .sudo()
                .with_context(active_test=False)
                .search([("login", "=ilike", partner.email)])
            )

            if not partner.is_portal:
                # ajouter un groupe de portail à l'utilisateur
                # relatif des contacts sélectionnés
                user_portal = None
                # create a user if necessary, and make sure it is in the portal group
                if not user:
                    if partner.company_id:
                        company_id = partner.company_id.id
                    else:
                        company_id = self.env.company.id
                    user_portal = partner.sudo().with_company(company_id)._create_user()
                else:
                    user_portal = user
                partner.is_portal = True
                user_portal.write({"active": True, "groups_id": [(4, group_portal.id)]})
                # prepare for the signup process
                partner.signup_prepare()
                partner.with_context(active_test=True)._send_email(user_portal)
            else:
                # remove the user (if it exists) from the portal group
                if user and group_portal in user.groups_id:
                    partner.is_portal = False
                    # if user belongs to portal only, deactivate it
                    if len(user.groups_id) <= 1:
                        user.write(
                            {"groups_id": [(3, group_portal.id)], "active": False}
                        )
                    else:
                        user.write({"groups_id": [(3, group_portal.id)]})

    def _create_user(self):
        """Création d'un nouveal utilisateur pour un contact
        :returns enregistrement res.users
        """
        return (
            self.env["res.users"]
            .with_context(no_reset_password=True)
            ._create_user_from_template(
                {
                    "email": self.email,
                    "login": self.email,
                    "partner_id": self.id,
                    "company_id": self.env.company.id,
                    "company_ids": [(6, 0, self.env.company.ids)],
                }
            )
        )

    def _send_email(self, user_portal):
        """ envoi d'un mail au nouvel utilisateur portail """
        if not self.env.user.email:
            raise UserError(
                _(
                    "Vous devez avoir une adresse e-mail dans vos "
                    "Préférences utilisateur pour envoyer des e-mails."
                )
            )

        # determine subject and body in the portal user's language
        template = self.env.ref("acc_portal.acc_mail_template_data_portal_welcome")
        lang = user_portal.lang
        company_id = self.env.company
        portal_url = self.with_context(
            signup_force_type_in_url="", lang=lang
        )._get_signup_url_app()[self.id]
        self.signup_prepare()

        if template:
            template.with_context(
                dbname=self._cr.dbname,
                portal_url=portal_url,
                company_id=company_id,
                user_signup_url=user_portal.signup_url,
                lang=lang,
            ).send_mail(self.id, force_send=True)
        else:
            _logger.warning(
                "Aucun modèle d'e-mail trouvé pour l'envoi "
                "d'e-mails à l'utilisateur du portail"
            )

        return True

    def _get_signup_url_app(
        self,
        url=None,
        action=None,
        view_type=None,
        menu_id=None,
        res_id=None,
        model=None,
    ):

        res = dict.fromkeys(self.ids, False)
        for partner in self:
            base_url = self.env.company.url_app

            # when required, make sure the partner has a valid signup token
            if self.env.context.get("signup_valid") and not partner.user_ids:
                partner.sudo().signup_prepare()

            route = "signup"
            # the parameters to encode for the query
            query = dict(db=self.env.cr.dbname)
            signup_type = self.env.context.get(
                "signup_force_type_in_url", partner.sudo().signup_type or ""
            )
            if signup_type:
                route = "reset_password" if signup_type == "reset" else signup_type

            if partner.sudo().signup_token and signup_type:
                query["token"] = partner.sudo().signup_token
            elif partner.user_ids:
                query["login"] = partner.user_ids[0].login
            else:
                continue  # no signup token, no user, thus no signup url!

            signup_url = "/%s?%s" % (route, werkzeug.urls.url_encode(query))
            if not self.env.context.get("relative_url"):
                signup_url = werkzeug.urls.url_join(base_url, signup_url)
            res[partner.id] = signup_url

        return res

    # ------------------------------------------------------
    # Business methods
    # ------------------------------------------------------