"""
inventory/tests/test_api.py
Integration tests for inventory REST API endpoints.
"""

from datetime import date
from decimal import Decimal

from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

from catalog_app.models import Author, Book
from inventory.models import Sale, StockLocation
from inventory.services.inventory_service import receive_stock

User = get_user_model()


def make_inv_manager(username="invmgr"):
    group, _ = Group.objects.get_or_create(name="inventory_managers")
    user = User.objects.create_user(username, password="pass", is_staff=True)
    user.groups.add(group)
    return user


def make_author():
    return Author.objects.create(
        name="API Test Author",
        default_my_keep_percent=Decimal("25.00"),
        default_author_pay_percent=Decimal("75.00"),
    )


def make_book(author):
    return Book.objects.create(
        title="API Test Book",
        author=author,
        price=Decimal("1500.00"),
        my_keep_percent=Decimal("25.00"),
        reorder_level=5,
        track_inventory=True,
        is_listed=True,
    )


def make_location(code="WH001"):
    return StockLocation.objects.create(
        name="Test Warehouse", code=code,
        location_type=StockLocation.TYPE_WAREHOUSE,
    )


class StockLocationAPITest(APITestCase):
    def setUp(self):
        self.user = make_inv_manager()
        self.client.force_authenticate(user=self.user)

    def test_list_locations(self):
        make_location("LOC001")
        url = "/api/inventory/locations/"
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertGreaterEqual(len(response.data["results"]), 1)

    def test_create_location(self):
        url = "/api/inventory/locations/"
        data = {"name": "New Store", "code": "ST001", "location_type": "bookstore", "is_active": True}
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data["code"], "ST001")

    def test_unauthenticated_denied(self):
        self.client.force_authenticate(user=None)
        url = "/api/inventory/locations/"
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)


class StockReceiveAPITest(APITestCase):
    def setUp(self):
        self.user = make_inv_manager()
        self.client.force_authenticate(user=self.user)
        self.author = make_author()
        self.book = make_book(self.author)
        self.location = make_location()

    def test_receive_stock(self):
        url = "/api/inventory/stock/receive/"
        data = {
            "book": self.book.pk,
            "location": self.location.pk,
            "quantity": 20,
            "reference": "PO-001",
        }
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_receive_negative_quantity_rejected(self):
        url = "/api/inventory/stock/receive/"
        data = {
            "book": self.book.pk,
            "location": self.location.pk,
            "quantity": -5,
        }
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)


class SaleAPITest(APITestCase):
    def setUp(self):
        self.user = make_inv_manager()
        self.client.force_authenticate(user=self.user)
        self.author = make_author()
        self.book = make_book(self.author)
        self.location = make_location("WH002")
        receive_stock(book=self.book, location=self.location, quantity=50, user=self.user)

    def test_create_sale(self):
        url = "/api/inventory/sales/"
        data = {
            "sale_channel": Sale.CHANNEL_DIRECT,
            "sale_date": str(date.today()),
            "items": [
                {
                    "book": self.book.pk,
                    "quantity": 2,
                    "unit_price": "1500.00",
                    "discount_percent": "0.00",
                    "stock_location": self.location.pk,
                }
            ],
        }
        response = self.client.post(url, data, format="json")
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertIn("invoice_number", response.data)

    def test_create_sale_no_items_rejected(self):
        url = "/api/inventory/sales/"
        data = {
            "sale_channel": Sale.CHANNEL_DIRECT,
            "sale_date": str(date.today()),
            "items": [],
        }
        response = self.client.post(url, data, format="json")
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_list_sales(self):
        url = "/api/inventory/sales/"
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)


class MarginPreviewAPITest(APITestCase):
    def setUp(self):
        self.user = make_inv_manager()
        self.client.force_authenticate(user=self.user)
        self.author = make_author()
        self.book = make_book(self.author)

    def test_margin_preview(self):
        url = "/api/inventory/sales/margin_preview/"
        data = {
            "book": self.book.pk,
            "quantity": 1,
            "unit_price": "1000.00",
            "discount_percent": "10.00",
        }
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn("net_amount", response.data)
        self.assertIn("my_profit_amount", response.data)
        self.assertIn("author_payout_amount", response.data)


class InventoryBalanceAPITest(APITestCase):
    def setUp(self):
        self.user = make_inv_manager()
        self.client.force_authenticate(user=self.user)
        self.author = make_author()
        self.book = make_book(self.author)
        self.location = make_location("WH003")
        receive_stock(book=self.book, location=self.location, quantity=15, user=self.user)

    def test_list_balances(self):
        url = "/api/inventory/balances/"
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertGreaterEqual(len(response.data["results"]), 1)

    def test_low_stock_filter(self):
        # book reorder_level=5, on_hand=15 → not low stock
        url = "/api/inventory/balances/?low_stock=true"
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        # none should be low stock since we have 15
        ids = [r["book"] for r in response.data["results"]]
        self.assertNotIn(self.book.pk, ids)
