# Copyright 2026 Criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields
from odoo.tests import HttpCase, tagged

from odoo.addons.membership.tests.common import TestMembershipCommon


@tagged("post_install", "-at_install")
class TestWebsiteMembershipAssociate(HttpCase, TestMembershipCommon):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.website = cls.env.ref("website.default_website")
        cls.country_us = cls.env.ref("base.us")
        cls.country_be = cls.env.ref("base.be")

        cls.membership_1.write({"website_published": True})
        cls.partner_1.write(
            {
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_us.id,
            }
        )
        invoice = cls.partner_1.create_membership_invoice(cls.membership_1, 75.0)
        invoice.action_post()
        cls.env["account.payment.register"].with_context(
            active_model="account.move", active_ids=invoice.ids
        ).create(
            {
                "amount": 86.25,
                "payment_method_line_id": cls.inbound_payment_method_line.id,
            }
        )._create_payments()
        cls.partner_1._compute_membership_state()

        cls.associate = cls.env["res.partner"].create(
            {
                "name": "Associate Paid",
                "associate_member": cls.partner_1.id,
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_be.id,
                "website_description": "Sustainable farming",
            }
        )

        cls.partner_2.write(
            {
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_us.id,
            }
        )
        cls.associate_free = cls.env["res.partner"].create(
            {
                "name": "Associate Free",
                "associate_member": cls.partner_2.id,
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_us.id,
            }
        )

    def test_host_membership_state_is_paid(self):
        self.assertEqual(self.partner_1.membership_state, "paid")

    def test_members_page_lists_host_and_associate(self):
        response = self.url_open("/members")
        self.assertEqual(response.status_code, 200)
        self.assertIn(self.partner_1.name, response.text)
        self.assertIn(self.associate.name, response.text)

    def test_membership_filter_includes_associate(self):
        response = self.url_open("/members/association/%d" % self.membership_1.id)
        self.assertEqual(response.status_code, 200)
        self.assertIn(self.partner_1.name, response.text)
        self.assertIn(self.associate.name, response.text)

    def test_free_membership_filter_includes_associate(self):
        response = self.url_open("/members/association/free")
        self.assertEqual(response.status_code, 200)
        self.assertIn(self.partner_2.name, response.text)
        self.assertIn(self.associate_free.name, response.text)

    def test_country_filter_counts_associate(self):
        response = self.url_open("/members/country/%d" % self.country_be.id)
        self.assertEqual(response.status_code, 200)
        self.assertIn(self.associate.name, response.text)
        self.assertNotIn(self.partner_1.name, response.text)
        self.assertNotIn(self.partner_2.name, response.text)
        self.assertNotIn(self.associate_free.name, response.text)

    def test_search_finds_associate(self):
        response = self.url_open("/members?search=Sustainable+farming")
        self.assertEqual(response.status_code, 200)
        self.assertIn(self.associate.name, response.text)
        self.assertNotIn(self.partner_1.name, response.text)

    def test_published_companies_map_includes_associate(self):
        host_line = self.partner_1.member_lines[0]
        companies = host_line._get_published_companies(limit=2000)
        self.assertIn(self.partner_1.id, companies)
        self.assertIn(self.associate.id, companies)


@tagged("post_install", "-at_install")
class TestWebsiteMembershipAssociatePagination(HttpCase, TestMembershipCommon):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.website = cls.env.ref("website.default_website")
        cls.country_es = cls.env.ref("base.es")
        cls.membership_1.write({"website_published": True})

        host_vals = [
            {
                "name": "Host Page %d" % i,
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_es.id,
            }
            for i in range(20)
        ]
        cls.paginated_hosts = cls.env["res.partner"].create(host_vals)
        invoices = cls.paginated_hosts.create_membership_invoice(
            cls.membership_1, 75.0
        )
        invoices.action_post()
        cls.env["account.payment.register"].with_context(
            active_model="account.move", active_ids=invoices.ids
        ).create(
            {
                "amount": sum(invoices.mapped("amount_total")),
                "payment_method_line_id": cls.inbound_payment_method_line.id,
            }
        )._create_payments()
        cls.paginated_hosts._compute_membership_state()

        associate_vals = [
            {
                "name": "Associate Page %d" % i,
                "associate_member": cls.paginated_hosts[i].id,
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_es.id,
            }
            for i in range(20)
        ]
        cls.paginated_associates = cls.env["res.partner"].create(associate_vals)

    def test_pagination_hosts_plus_associates(self):
        response = self.url_open("/members/association/%d" % self.membership_1.id)
        self.assertEqual(response.status_code, 200)
        # Page 1 contains all 20 hosts plus their 20 associates.
        self.assertIn("Host Page 0", response.text)
        self.assertIn("Host Page 19", response.text)
        self.assertIn("Associate Page 0", response.text)
        self.assertIn("Associate Page 19", response.text)
        # No pagination placeholder from a second page is expected.
        self.assertNotIn("Host Page 20", response.text)
        self.assertNotIn("Associate Page 20", response.text)


@tagged("post_install", "-at_install")
class TestMembershipLineAssociate(TestMembershipCommon):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.country_us = cls.env.ref("base.us")
        cls.country_be = cls.env.ref("base.be")

        cls.membership_1.write({"website_published": True})
        cls.partner_1.write(
            {
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_us.id,
                "website_description": "Host description",
            }
        )
        invoice = cls.partner_1.create_membership_invoice(cls.membership_1, 75.0)
        invoice.action_post()
        cls.env["account.payment.register"].with_context(
            active_model="account.move", active_ids=invoice.ids
        ).create(
            {
                "amount": invoice.amount_total,
                "payment_method_line_id": cls.inbound_payment_method_line.id,
            }
        )._create_payments()
        cls.partner_1._compute_membership_state()

        cls.associate = cls.env["res.partner"].create(
            {
                "name": "Associate Paid",
                "associate_member": cls.partner_1.id,
                "website_published": True,
                "is_company": True,
                "country_id": cls.country_be.id,
                "website_description": "Sustainable farming",
            }
        )

    def _base_domain(self):
        today = fields.Date.today()
        return [
            ("partner.website_published", "=", True),
            ("state", "=", "paid"),
            ("date_to", ">=", today),
            ("date_from", "<=", today),
            ("membership_id", "in", self.membership_1.ids),
        ]

    def test_search_excludes_host_when_only_associate_matches_without_context(self):
        domain = self._base_domain()
        domain += [
            "|",
            ("partner.name", "ilike", "Sustainable farming"),
            ("partner.website_description", "ilike", "Sustainable farming"),
        ]
        lines = self.env["membership.membership_line"].search(domain)
        self.assertNotIn(self.partner_1.id, lines.partner.ids)

    def test_search_includes_host_when_associate_name_matches(self):
        domain = self._base_domain()
        domain += [
            "|",
            ("partner.name", "ilike", "Sustainable farming"),
            ("partner.website_description", "ilike", "Sustainable farming"),
        ]
        lines = (
            self.env["membership.membership_line"]
            .with_context(include_associate_members=True)
            .search(domain)
        )
        self.assertIn(self.partner_1.id, lines.partner.ids)

    def test_search_includes_host_when_associate_country_matches(self):
        domain = self._base_domain()
        domain.append(("partner.country_id", "=", self.country_be.id))
        lines = (
            self.env["membership.membership_line"]
            .with_context(include_associate_members=True)
            .search(domain)
        )
        self.assertIn(self.partner_1.id, lines.partner.ids)

    def test_get_associate_partners_filters_by_country(self):
        MembershipLine = self.env["membership.membership_line"]
        match = MembershipLine._get_associate_partners(
            (self.partner_1.id,), country_id=self.country_be.id
        )
        self.assertEqual(match, self.associate)
        no_match = MembershipLine._get_associate_partners(
            (self.partner_1.id,), country_id=self.country_us.id
        )
        self.assertFalse(no_match)

    def test_get_associate_partners_filters_by_search(self):
        MembershipLine = self.env["membership.membership_line"]
        match = MembershipLine._get_associate_partners(
            (self.partner_1.id,), post_name="Sustainable"
        )
        self.assertEqual(match, self.associate)
        no_match = MembershipLine._get_associate_partners(
            (self.partner_1.id,), post_name="Nonexistent"
        )
        self.assertFalse(no_match)

    def test_published_companies_includes_associate(self):
        host_line = self.partner_1.member_lines[0]
        companies = host_line._get_published_companies(limit=2000)
        self.assertIn(self.partner_1.id, companies)
        self.assertIn(self.associate.id, companies)
