"""BE-002: writable cross-org FKs on Invoice and BankStatementImport must be
rejected, not merely existence-checked. Mirrors the same audit and fix shape
already applied to apps.hr.serializers.AttendanceSerializer — here using this
file's own established pattern (assert_same_organization inside validate(),
raising PermissionDenied/403, not a disguised 400) since accounting/finance
already had working examples of that pattern elsewhere (JournalEntrySerializer,
SaleSerializer) before this fix."""
import pytest
from django.core.files.uploadedfile import SimpleUploadedFile
from rest_framework.test import APIClient

from apps.companies.models import Company, Organization, OrganizationMembership
from apps.core.models import User
from apps.finance.models import BankAccount, Invoice


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@tenant.test", password="p", organization_role="director")
    OrganizationMembership.objects.create(organization=org_a, user=user)
    return user


@pytest.mark.django_db
class TestInvoiceCrossTenantWrite:
    def test_create_rejects_cross_org_donor(self, director_a, org_a, org_b):
        donor_b = Company.objects.create(organization=org_b, name="Org B Donor")
        client = api(director_a)
        resp = client.post("/api/finance-invoices/", {
            "donor": str(donor_b.id), "due_date": "2026-08-31",
        }, format="json")
        assert resp.status_code == 403
        assert not Invoice.objects.filter(donor=donor_b).exists()

    def test_create_same_org_donor_succeeds(self, director_a, org_a):
        donor_a = Company.objects.create(organization=org_a, name="Org A Donor")
        client = api(director_a)
        resp = client.post("/api/finance-invoices/", {
            "donor": str(donor_a.id), "due_date": "2026-08-31",
        }, format="json")
        assert resp.status_code == 201, resp.content
        assert Invoice.objects.filter(donor=donor_a).exists()

    def test_update_rejects_reassignment_to_cross_org_donor(self, director_a, org_a, org_b):
        donor_a = Company.objects.create(organization=org_a, name="Org A Donor")
        donor_b = Company.objects.create(organization=org_b, name="Org B Donor")
        invoice = Invoice.objects.create(organization=org_a, donor=donor_a, created_by=director_a, due_date="2026-08-31")
        client = api(director_a)
        resp = client.patch(f"/api/finance-invoices/{invoice.id}/", {"donor": str(donor_b.id)}, format="json")
        assert resp.status_code == 403
        invoice.refresh_from_db()
        assert str(invoice.donor_id).replace("-", "") == str(donor_a.id).replace("-", "")


@pytest.mark.django_db
class TestBankStatementImportCrossTenantWrite:
    def test_create_rejects_cross_org_bank_account(self, director_a, org_a, org_b):
        account_b = BankAccount.objects.create(organization=org_b, bank_name="Org B Bank", account_number="999", currency="IDR")
        client = api(director_a)
        resp = client.post("/api/bank-statement-imports/", {
            "bank_account": str(account_b.id),
            "import_method": "csv",
            "statement_file": SimpleUploadedFile("statement.csv", b"date,amount\n"),
        }, format="multipart")
        assert resp.status_code == 403

    def test_create_same_org_bank_account_succeeds(self, director_a, org_a):
        account_a = BankAccount.objects.create(organization=org_a, bank_name="Org A Bank", account_number="111", currency="IDR")
        client = api(director_a)
        resp = client.post("/api/bank-statement-imports/", {
            "bank_account": str(account_a.id),
            "import_method": "csv",
            "statement_file": SimpleUploadedFile("statement.csv", b"date,amount\n"),
        }, format="multipart")
        assert resp.status_code == 201, resp.content
