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

import json
from requests.exceptions import HTTPError

import odoo
from odoo.tools import file_open, mute_logger
from odoo.addons.mail.tests.test_controller_common import TestControllerCommon


@odoo.tests.tagged("-at_install", "post_install")
class TestAttachmentControllerCommon(TestControllerCommon):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()

    def _execute_subtests(self, record, subtests):
        for data_user, allowed, *args in subtests:
            route_kw = args[0] if args else {}
            user = data_user if data_user._name == "res.users" else self.user_public
            guest = data_user if data_user._name == "mail.guest" else self.env["mail.guest"]
            self._authenticate_user(user=user, guest=guest)
            with self.subTest(record=record, user=user.name, guest=guest.name, route_kw=route_kw):
                if allowed:
                    attachment_id = self._upload_attachment(record.id, record._name, route_kw)
                    attachment = (
                        self.env["ir.attachment"].sudo().search([("id", "=", attachment_id)])
                    )
                    self.assertTrue(attachment)
                    self._delete_attachment(attachment, route_kw)
                    self.assertFalse(attachment.exists())
                else:
                    with self.assertRaises(
                        HTTPError, msg="upload attachment should raise NotFound"
                    ):
                        self._upload_attachment(record.id, record._name, route_kw)

    def _upload_attachment(self, thread_id, thread_model, route_kw):
        with mute_logger("odoo.http"), file_open("addons/web/__init__.py") as file:
            res = self.url_open(
                url="/mail/attachment/upload",
                data={
                    "csrf_token": odoo.http.Request.csrf_token(self),
                    "is_pending": True,
                    "thread_id": thread_id,
                    "thread_model": thread_model,
                    **route_kw,
                },
                files={"ufile": file},
            )
            res.raise_for_status()
            return json.loads(res.content.decode("utf-8"))["data"]["ir.attachment"][0]["id"]

    def _delete_attachment(self, attachment, route_kw):
        self.make_jsonrpc_request(
            route="/mail/attachment/delete",
            params={
                "attachment_id": attachment["id"],
                "access_token": attachment["access_token"],
                **route_kw,
            },
        )


@odoo.tests.tagged("-at_install", "post_install")
class TestAttachmentController(TestAttachmentControllerCommon):
    def test_attachment_partner(self):
        """Test access to upload an attachment on a non channel thread"""
        record = self.user_demo.partner_id
        self._execute_subtests(
            record,
            (
                (self.guest, False),
                (self.user_admin, True),
                (self.user_demo, True),
                (self.user_employee, False),
                (self.user_portal, False),
                (self.user_public, False),
            ),
        )
