"""BE-002: writable cross-org FKs across asset_management serializers must be
rejected, not merely existence-checked. Mirrors the pattern already applied
to apps.hr / apps.finance / apps.accounting / apps.meetings / apps.events."""
from datetime import date

import pytest
from rest_framework.test import APIClient

from apps.asset_management.models import (
    Asset, AssetCategory, AssetLocation, AssetTicket, Vendor, License,
    LicenseSeatAssignment, Rental, StockItem, StockMovement, SellableItem,
)
from apps.companies.models import Organization, OrganizationMembership
from apps.core.models import User


def api(user):
    client = APIClient()
    client.force_authenticate(user)
    return client


@pytest.fixture
def org_a(db):
    return Organization.objects.create(name="Org A")


@pytest.fixture
def org_b(db):
    return Organization.objects.create(name="Org B")


@pytest.fixture
def director_a(org_a):
    user = User.objects.create_user(email="director-a@assets.test", password="p", organization_role="director")
    OrganizationMembership.objects.create(organization=org_a, user=user)
    return user


@pytest.mark.django_db
class TestAssetCrossTenantWrite:
    def test_create_rejects_cross_org_category(self, director_a, org_a, org_b):
        category_b = AssetCategory.objects.create(organization=org_b, name="Org B Category")
        client = api(director_a)
        resp = client.post("/api/assets/", {
            "name": "Laptop", "asset_tag": "LAP-001", "category": str(category_b.id),
        }, format="json")
        assert resp.status_code == 403
        assert not Asset.objects.filter(category=category_b).exists()

    def test_create_same_org_category_succeeds(self, director_a, org_a):
        category_a = AssetCategory.objects.create(organization=org_a, name="Org A Category")
        client = api(director_a)
        resp = client.post("/api/assets/", {
            "name": "Laptop", "asset_tag": "LAP-002", "category": str(category_a.id),
        }, format="json")
        assert resp.status_code == 201, resp.content


@pytest.mark.django_db
class TestAssetTicketCrossTenantWrite:
    def test_create_rejects_cross_org_asset(self, director_a, org_a, org_b):
        asset_b = Asset.objects.create(organization=org_b, name="Org B Asset", asset_tag="B-1")
        client = api(director_a)
        resp = client.post("/api/asset-tickets/", {
            "title": "Broken screen", "asset": str(asset_b.id),
        }, format="json")
        assert resp.status_code == 400
        assert resp.data["asset"][0].code == "does_not_exist"
        assert not AssetTicket.objects.filter(asset=asset_b).exists()


@pytest.mark.django_db
class TestLicenseCrossTenantWrite:
    def test_create_rejects_cross_org_vendor(self, director_a, org_a, org_b):
        vendor_b = Vendor.objects.create(organization=org_b, name="Org B Vendor")
        client = api(director_a)
        resp = client.post("/api/licenses/", {
            "name": "M365", "vendor": str(vendor_b.id), "seats": 5,
        }, format="json")
        assert resp.status_code == 403
        assert not License.objects.filter(vendor=vendor_b).exists()

    def test_create_same_org_vendor_succeeds(self, director_a, org_a):
        vendor_a = Vendor.objects.create(organization=org_a, name="Org A Vendor")
        client = api(director_a)
        resp = client.post("/api/licenses/", {
            "name": "M365", "vendor": str(vendor_a.id), "seats": 5,
        }, format="json")
        assert resp.status_code == 201, resp.content


@pytest.mark.django_db
class TestLicenseSeatAssignmentCrossTenantWrite:
    def test_create_rejects_cross_org_license(self, director_a, org_a, org_b):
        from apps.hr.signals import ensure_employee_stub
        from apps.hr.models import Employee

        license_b = License.objects.create(organization=org_b, name="Org B License", seats=5)
        ensure_employee_stub(director_a)
        employee_a = Employee.objects.get(user=director_a)
        client = api(director_a)
        resp = client.post("/api/license-seat-assignments/", {
            "license": str(license_b.id), "employee": str(employee_a.id),
            "assigned_date": date.today().isoformat(),
        }, format="json")
        assert resp.status_code == 403
        assert not LicenseSeatAssignment.objects.filter(license=license_b).exists()


@pytest.mark.django_db
class TestRentalCrossTenantWrite:
    def test_create_rejects_cross_org_location(self, director_a, org_a, org_b):
        location_b = AssetLocation.objects.create(organization=org_b, name="Org B Warehouse")
        client = api(director_a)
        resp = client.post("/api/rentals/", {
            "name": "Projector", "location": str(location_b.id),
        }, format="json")
        assert resp.status_code == 403
        assert not Rental.objects.filter(location=location_b).exists()


@pytest.mark.django_db
class TestStockItemCrossTenantWrite:
    def test_create_rejects_cross_org_vendor(self, director_a, org_a, org_b):
        vendor_b = Vendor.objects.create(organization=org_b, name="Org B Vendor")
        client = api(director_a)
        resp = client.post("/api/stock-items/", {
            "name": "Paper", "vendor": str(vendor_b.id),
        }, format="json")
        assert resp.status_code == 403
        assert not StockItem.objects.filter(vendor=vendor_b).exists()


@pytest.mark.django_db
class TestStockMovementCrossTenantWrite:
    def test_create_rejects_cross_org_item(self, director_a, org_a, org_b):
        item_b = StockItem.objects.create(organization=org_b, name="Org B Item")
        location_a = AssetLocation.objects.create(organization=org_a, name="Org A Loc")
        client = api(director_a)
        resp = client.post("/api/stock-movements/", {
            "item": str(item_b.id), "location": str(location_a.id),
            "movement_type": "in", "quantity": 10,
        }, format="json")
        assert resp.status_code == 403
        assert not StockMovement.objects.filter(item=item_b).exists()


@pytest.mark.django_db
class TestSellableItemCrossTenantWrite:
    def test_create_rejects_cross_org_stock_item(self, director_a, org_a, org_b):
        item_b = StockItem.objects.create(organization=org_b, name="Org B Book")
        client = api(director_a)
        resp = client.post("/api/sellable-items/", {
            "stock_item": str(item_b.id), "category": "book", "sale_price": "50000.00",
        }, format="json")
        assert resp.status_code == 403
        assert not SellableItem.objects.filter(stock_item=item_b).exists()
