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

"""
Test suite for HTTP endpoints in website_sale_aplicoop controllers.

Coverage:
- /eskaera (GET) - View all group orders
- /eskaera/<id> (GET) - View specific group order
- /eskaera/<id>/add-to-cart (POST) - Add product to cart
- /eskaera/<id>/checkout (GET) - Checkout page
- /eskaera/<id>/checkout (POST) - Save cart items
- /eskaera/confirm (POST) - Confirm order
- /eskaera/<id>/confirm/<sale_id> (POST) - Confirm order from portal
- /eskaera/<id>/load-from-history/<sale_id> (POST) - Load draft order
- /eskaera/labels (GET) - Get translated labels
"""

from datetime import datetime
from datetime import timedelta

from odoo.exceptions import AccessError  # noqa: F401
from odoo.exceptions import ValidationError  # noqa: F401
from odoo.tests.common import HttpCase  # noqa: F401
from odoo.tests.common import TransactionCase


class TestEskaearaListEndpoint(TransactionCase):
    """Test /eskaera endpoint (list all group orders)."""

    def setUp(self):
        super().setUp()
        self.group = self.env["res.partner"].create(
            {
                "name": "Test Group",
                "is_company": True,
                "email": "group@test.com",
            }
        )

        self.member_partner = self.env["res.partner"].create(
            {
                "name": "Group Member",
                "email": "member@test.com",
            }
        )

        self.group.member_ids = [(4, self.member_partner.id)]

        self.user = self.env["res.users"].create(
            {
                "name": "Test User",
                "login": "testuser@test.com",
                "email": "testuser@test.com",
                "partner_id": self.member_partner.id,
            }
        )

        # Create multiple group orders (some open, some closed)
        start_date = datetime.now().date()

        self.open_order = self.env["group.order"].create(
            {
                "name": "Open Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date,
                "end_date": start_date + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        self.open_order.action_open()

        self.draft_order = self.env["group.order"].create(
            {
                "name": "Draft Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date - timedelta(days=14),
                "end_date": start_date - timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        # Stay in draft

        self.closed_order = self.env["group.order"].create(
            {
                "name": "Closed Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date - timedelta(days=21),
                "end_date": start_date - timedelta(days=14),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        self.closed_order.action_open()
        self.closed_order.action_close()

    def test_eskaera_list_shows_only_open_and_draft_orders(self):
        """Test that /eskaera shows only open/draft orders, not closed."""
        # In controller context, only open and draft should be visible to members
        # This is business logic: closed orders are historical
        visible_orders = self.env["group.order"].search(
            [
                ("state", "in", ["open", "draft"]),
                ("group_ids", "in", self.group.id),
            ]
        )

        self.assertIn(self.open_order, visible_orders)
        self.assertIn(self.draft_order, visible_orders)
        self.assertNotIn(self.closed_order, visible_orders)

    def test_eskaera_list_filters_by_user_groups(self):
        """Test that user only sees orders from their groups."""
        other_group = self.env["res.partner"].create(
            {
                "name": "Other Group",
                "is_company": True,
                "email": "other@test.com",
            }
        )

        other_order = self.env["group.order"].create(
            {
                "name": "Other Group Order",
                "group_ids": [(6, 0, [other_group.id])],
                "type": "regular",
                "start_date": datetime.now().date(),
                "end_date": datetime.now().date() + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        other_order.action_open()

        # User should not see orders from groups they're not in
        user_groups = self.member_partner.group_ids
        visible_orders = self.env["group.order"].search(
            [
                ("state", "in", ["open", "draft"]),
                ("group_ids", "in", user_groups.ids),
            ]
        )

        self.assertNotIn(other_order, visible_orders)


class TestAddToCartEndpoint(TransactionCase):
    """Test /eskaera/<id>/add-to-cart endpoint."""

    def setUp(self):
        super().setUp()
        self.group = self.env["res.partner"].create(
            {
                "name": "Test Group",
                "is_company": True,
                "email": "group@test.com",
            }
        )

        self.member_partner = self.env["res.partner"].create(
            {
                "name": "Group Member",
                "email": "member@test.com",
            }
        )

        self.group.member_ids = [(4, self.member_partner.id)]

        self.user = self.env["res.users"].create(
            {
                "name": "Test User",
                "login": "testuser@test.com",
                "email": "testuser@test.com",
                "partner_id": self.member_partner.id,
            }
        )

        self.category = self.env["product.category"].create(
            {
                "name": "Test Category",
            }
        )

        # Published product
        self.product = self.env["product.product"].create(
            {
                "name": "Test Product",
                "type": "consu",
                "list_price": 10.0,
                "categ_id": self.category.id,
                "sale_ok": True,
                "is_published": True,
            }
        )

        # Unpublished product (should not be available)
        self.unpublished_product = self.env["product.product"].create(
            {
                "name": "Unpublished Product",
                "type": "consu",
                "list_price": 15.0,
                "categ_id": self.category.id,
                "sale_ok": False,
                "is_published": False,
            }
        )

        start_date = datetime.now().date()
        self.group_order = self.env["group.order"].create(
            {
                "name": "Test Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date,
                "end_date": start_date + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        self.group_order.action_open()
        self.group_order.product_ids = [(4, self.product.id)]

    def test_add_to_cart_published_product(self):
        """Test adding published product to cart."""
        # Simulate controller logic
        cart_line = {
            "product_id": self.product.id,
            "quantity": 2,
            "group_order_id": self.group_order.id,
            "partner_id": self.member_partner.id,
        }
        # Should succeed
        self.assertTrue(cart_line["product_id"])

    def test_add_to_cart_zero_quantity(self):
        """Test that adding zero quantity is rejected."""
        # Edge case: quantity = 0
        quantity = 0
        # Controller should validate: quantity > 0
        self.assertFalse(quantity > 0)

    def test_add_to_cart_negative_quantity(self):
        """Test that negative quantity is rejected."""
        quantity = -5
        # Controller should validate: quantity > 0
        self.assertFalse(quantity > 0)

    def test_add_to_cart_unpublished_product(self):
        """Test that unpublished products cannot be added."""
        # Product must be published and sale_ok=True
        self.assertFalse(self.unpublished_product.is_published)
        self.assertFalse(self.unpublished_product.sale_ok)

    def test_add_to_cart_product_not_in_order(self):
        """Test that products not in the order cannot be added."""
        # Create a product NOT associated with group_order
        other_product = self.env["product.product"].create(
            {
                "name": "Other Product",
                "type": "consu",
                "list_price": 25.0,
            }
        )

        # Controller should check: product in group_order.product_ids
        self.assertNotIn(other_product, self.group_order.product_ids)

    def test_add_to_cart_order_closed(self):
        """Test that adding to closed order is rejected."""
        self.group_order.action_close()
        # Controller should check: order.state == 'open'
        self.assertEqual(self.group_order.state, "closed")


class TestCheckoutEndpoint(TransactionCase):
    """Test /eskaera/<id>/checkout endpoint."""

    def setUp(self):
        super().setUp()
        self.group = self.env["res.partner"].create(
            {
                "name": "Test Group",
                "is_company": True,
                "email": "group@test.com",
            }
        )

        self.member_partner = self.env["res.partner"].create(
            {
                "name": "Group Member",
                "email": "member@test.com",
            }
        )

        self.group.member_ids = [(4, self.member_partner.id)]

        self.user = self.env["res.users"].create(
            {
                "name": "Test User",
                "login": "testuser@test.com",
                "email": "testuser@test.com",
                "partner_id": self.member_partner.id,
            }
        )

        start_date = datetime.now().date()
        self.group_order = self.env["group.order"].create(
            {
                "name": "Test Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date,
                "end_date": start_date + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "pickup_date": start_date + timedelta(days=3),
                "cutoff_day": "0",
            }
        )
        self.group_order.action_open()

    def test_checkout_page_loads(self):
        """Test that checkout page renders correctly."""
        # Controller should render template with group_order context
        self.assertTrue(self.group_order.exists())

    def test_checkout_displays_pickup_date(self):
        """Test that checkout shows correct pickup date."""
        # Controller should calculate pickup_date from pickup_day
        self.assertTrue(self.group_order.pickup_date)

    def test_checkout_displays_home_delivery_option(self):
        """Test that checkout shows home delivery option."""
        # Controller should pass home_delivery flag to template
        self.assertIsNotNone(self.group_order.home_delivery)

    def test_checkout_order_without_products(self):
        """Test checkout when no products available."""
        # Order with empty product_ids
        empty_order = self.env["group.order"].create(
            {
                "name": "Empty Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": datetime.now().date(),
                "end_date": datetime.now().date() + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        empty_order.action_open()

        # Should handle gracefully
        self.assertEqual(len(empty_order.product_ids), 0)


class TestConfirmOrderEndpoint(TransactionCase):
    """Test /eskaera/confirm endpoint (confirm final order)."""

    def setUp(self):
        super().setUp()
        self.group = self.env["res.partner"].create(
            {
                "name": "Test Group",
                "is_company": True,
                "email": "group@test.com",
            }
        )

        self.member_partner = self.env["res.partner"].create(
            {
                "name": "Group Member",
                "email": "member@test.com",
            }
        )

        self.group.member_ids = [(4, self.member_partner.id)]

        self.user = self.env["res.users"].create(
            {
                "name": "Test User",
                "login": "testuser@test.com",
                "email": "testuser@test.com",
                "partner_id": self.member_partner.id,
            }
        )

        self.category = self.env["product.category"].create(
            {
                "name": "Test Category",
            }
        )

        self.product = self.env["product.product"].create(
            {
                "name": "Test Product",
                "type": "consu",
                "list_price": 10.0,
                "categ_id": self.category.id,
            }
        )

        start_date = datetime.now().date()
        self.group_order = self.env["group.order"].create(
            {
                "name": "Test Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date,
                "end_date": start_date + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "pickup_date": start_date + timedelta(days=3),
                "cutoff_day": "0",
            }
        )
        self.group_order.action_open()
        self.group_order.product_ids = [(4, self.product.id)]

        # Create a draft sale order
        self.draft_sale = self.env["sale.order"].create(
            {
                "partner_id": self.member_partner.id,
                "group_order_id": self.group_order.id,
                "pickup_date": self.group_order.pickup_date,
                "state": "draft",
            }
        )

    def test_confirm_order_creates_sale_order(self):
        """Test that confirming creates a confirmed sale.order."""
        # Controller should change state from draft to sale
        self.draft_sale.action_confirm()
        self.assertEqual(self.draft_sale.state, "sale")

    def test_confirm_empty_order(self):
        """Test confirming order without items fails."""
        # Order with no order_lines should fail
        empty_sale = self.env["sale.order"].create(
            {
                "partner_id": self.member_partner.id,
                "group_order_id": self.group_order.id,
                "state": "draft",
            }
        )

        # Should validate: must have at least one line
        self.assertEqual(len(empty_sale.order_line), 0)

    def test_confirm_order_wrong_group(self):
        """Test that user cannot confirm order from different group."""
        other_group = self.env["res.partner"].create(
            {
                "name": "Other Group",
                "is_company": True,
            }
        )

        self.env["group.order"].create(
            {
                "name": "Other Order",
                "group_ids": [(6, 0, [other_group.id])],
                "type": "regular",
                "start_date": datetime.now().date(),
                "end_date": datetime.now().date() + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )

        # User should not be in other_group
        self.assertNotIn(self.member_partner, other_group.member_ids)


class TestLoadDraftEndpoint(TransactionCase):
    """Test /eskaera/<id>/load-from-history/<sale_id> endpoint."""

    def setUp(self):
        super().setUp()
        self.group = self.env["res.partner"].create(
            {
                "name": "Test Group",
                "is_company": True,
                "email": "group@test.com",
            }
        )

        self.member_partner = self.env["res.partner"].create(
            {
                "name": "Group Member",
                "email": "member@test.com",
            }
        )

        self.group.member_ids = [(4, self.member_partner.id)]

        self.user = self.env["res.users"].create(
            {
                "name": "Test User",
                "login": "testuser@test.com",
                "email": "testuser@test.com",
                "partner_id": self.member_partner.id,
            }
        )

        self.category = self.env["product.category"].create(
            {
                "name": "Test Category",
            }
        )

        self.product = self.env["product.product"].create(
            {
                "name": "Test Product",
                "type": "consu",
                "list_price": 10.0,
                "categ_id": self.category.id,
            }
        )

        start_date = datetime.now().date()
        self.group_order = self.env["group.order"].create(
            {
                "name": "Test Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": start_date,
                "end_date": start_date + timedelta(days=7),
                "period": "weekly",
                "pickup_day": "3",
                "pickup_date": start_date + timedelta(days=3),
                "cutoff_day": "0",
            }
        )
        self.group_order.action_open()
        self.group_order.product_ids = [(4, self.product.id)]

    def test_load_draft_from_history(self):
        """Test loading a previous draft order."""
        # Create old draft sale
        old_sale = self.env["sale.order"].create(
            {
                "partner_id": self.member_partner.id,
                "group_order_id": self.group_order.id,
                "state": "draft",
            }
        )

        # Should be able to load
        self.assertTrue(old_sale.exists())

    def test_load_draft_not_owned_by_user(self):
        """Test that user cannot load draft from other user."""
        other_partner = self.env["res.partner"].create(
            {
                "name": "Other Member",
                "email": "other@test.com",
            }
        )

        other_sale = self.env["sale.order"].create(
            {
                "partner_id": other_partner.id,
                "group_order_id": self.group_order.id,
                "state": "draft",
            }
        )

        # User should not be able to load other's draft
        self.assertNotEqual(other_sale.partner_id, self.member_partner)

    def test_load_draft_expired_order(self):
        """Test loading draft from expired group order."""
        old_start = datetime.now().date() - timedelta(days=30)
        old_end = datetime.now().date() - timedelta(days=23)

        expired_order = self.env["group.order"].create(
            {
                "name": "Expired Order",
                "group_ids": [(6, 0, [self.group.id])],
                "type": "regular",
                "start_date": old_start,
                "end_date": old_end,
                "period": "weekly",
                "pickup_day": "3",
                "cutoff_day": "0",
            }
        )
        expired_order.action_open()
        expired_order.action_close()

        self.env["sale.order"].create(
            {
                "partner_id": self.member_partner.id,
                "group_order_id": expired_order.id,
                "state": "draft",
            }
        )

        # Should warn: order expired
        self.assertEqual(expired_order.state, "closed")
