# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import fields, models, api
from odoo.addons.mail.tools.discuss import Store
from odoo.fields import Command


class ResUsers(models.Model):
    """ Update of res.users class
        - add a preference about username for livechat purpose
    """
    _inherit = 'res.users'

    livechat_channel_ids = fields.Many2many(
        "im_livechat.channel", "im_livechat_channel_im_user", "user_id", "channel_id", copy=False
    )
    livechat_username = fields.Char(
        string="Livechat Username",
        groups="im_livechat.im_livechat_group_user,base.group_erp_manager",
        compute="_compute_livechat_username",
        inverse="_inverse_livechat_username",
        store=False,
    )
    livechat_lang_ids = fields.Many2many(
        "res.lang",
        string="Livechat Languages",
        groups="im_livechat.im_livechat_group_user,base.group_erp_manager",
        compute="_compute_livechat_lang_ids",
        inverse="_inverse_livechat_lang_ids",
        store=False,
    )
    livechat_expertise_ids = fields.Many2many(
        "im_livechat.expertise",
        string="Live Chat Expertise",
        groups="im_livechat.im_livechat_group_user,base.group_erp_manager",
        compute="_compute_livechat_expertise_ids",
        inverse="_inverse_livechat_expertise_ids",
        store=False,
        help="When forwarding live chat conversations, the chatbot will prioritize users with matching expertise.",
    )
    livechat_ongoing_session_count = fields.Integer(
        "Number of Ongoing sessions",
        compute="_compute_livechat_ongoing_session_count",
        groups="im_livechat.im_livechat_group_user",
    )
    livechat_is_in_call = fields.Boolean(
        help="Whether the user is in a call, only available if the user is in a live chat agent",
        compute="_compute_livechat_is_in_call",
        groups="im_livechat.im_livechat_group_user",
    )
    has_access_livechat = fields.Boolean(compute='_compute_has_access_livechat', string='Has access to Livechat', store=False, readonly=True)

    @property
    def SELF_READABLE_FIELDS(self):
        return super().SELF_READABLE_FIELDS + [
            "has_access_livechat",
            "livechat_expertise_ids",
            "livechat_lang_ids",
            "livechat_username",
        ]

    @property
    def SELF_WRITEABLE_FIELDS(self):
        return super().SELF_WRITEABLE_FIELDS + [
            "livechat_expertise_ids",
            "livechat_lang_ids",
            "livechat_username",
        ]

    @api.depends("livechat_channel_ids", "is_in_call")
    def _compute_livechat_is_in_call(self):
        for user in self:
            # sudo - res.users: checking if user is in call is allowed if the user is member of a live chat channel.
            user.livechat_is_in_call = user.sudo().is_in_call if user.livechat_channel_ids else None

    @api.depends_context("im_livechat_channel_id")
    @api.depends("livechat_channel_ids.channel_ids.livechat_end_dt", "partner_id")
    def _compute_livechat_ongoing_session_count(self):
        domain = [
            ("channel_id.livechat_end_dt", "=", False),
            ("member_id", "!=", False),
            ("partner_id", "in", self.partner_id.ids),
            ("channel_id.last_interest_dt", ">=", "-15M"),
        ]
        if channel_id := self.env.context.get('im_livechat_channel_id'):
            domain.append(("session_livechat_channel_id", "=", channel_id))
        count_by_partner = dict(
            self.env["im_livechat.channel.member.history"]._read_group(
                domain, ["partner_id"], ["__count"],
            ),
        )
        for user in self:
            user.livechat_ongoing_session_count = count_by_partner.get(user.partner_id, 0)

    @api.depends('res_users_settings_id.livechat_username')
    def _compute_livechat_username(self):
        for user in self:
            # sudo: livechat user can see the livechat username of any other user
            user.livechat_username = user.sudo().res_users_settings_id.livechat_username

    def _inverse_livechat_username(self):
        for user in self:
            settings = self.env['res.users.settings']._find_or_create_for_user(user)
            settings.livechat_username = user.livechat_username

    @api.depends('res_users_settings_id.livechat_lang_ids')
    def _compute_livechat_lang_ids(self):
        for user in self:
            # sudo: livechat user can see the livechat languages of any other user
            user.livechat_lang_ids = user.sudo().res_users_settings_id.livechat_lang_ids

    def _inverse_livechat_lang_ids(self):
        for user in self:
            settings = self.env['res.users.settings']._find_or_create_for_user(user)
            settings.livechat_lang_ids = user.livechat_lang_ids

    @api.depends("res_users_settings_id.livechat_expertise_ids")
    def _compute_livechat_expertise_ids(self):
        for user in self:
            # sudo: livechat user can see the livechat expertise of any other user
            user.livechat_expertise_ids = user.sudo().res_users_settings_id.livechat_expertise_ids

    def _inverse_livechat_expertise_ids(self):
        for user in self:
            settings = self.env["res.users.settings"]._find_or_create_for_user(user)
            settings.livechat_expertise_ids = user.livechat_expertise_ids

    @api.depends("group_ids")
    def _compute_has_access_livechat(self):
        for user in self.sudo():
            user.has_access_livechat = user.has_group('im_livechat.im_livechat_group_user')

    def write(self, vals):
        if vals.get("group_ids"):
            operator_group = self.env.ref("im_livechat.im_livechat_group_user")
            if operator_group in self.all_group_ids:
                result = super().write(vals)
                lost_operators = self.filtered_domain([("all_group_ids", "not in", operator_group.id)])
                # sudo - im_livechat.channel: user manager can remove user from livechat channels
                self.env["im_livechat.channel"].sudo() \
                    .search([("user_ids", "in", lost_operators.ids)]) \
                    .write({"user_ids": [Command.unlink(operator.id) for operator in lost_operators]})
                return result
        return super().write(vals)

    def _init_store_data(self, store: Store):
        super()._init_store_data(store)
        store.add_global_values(has_access_livechat=self.env.user.has_access_livechat)
        if not self.env.user._is_public():
            store.add(
                self.env.user,
                Store.Attr(
                    "is_livechat_manager",
                    lambda u: u.has_group("im_livechat.im_livechat_group_manager"),
                ),
            )
