from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.test import APIRequestFactory

from account.audit import audit_event
from account.models import UserAuditLog
from shop_management.models.data.organization import Warehouse
from shop_management.models.data.shop import Shop
from shop_management.models.data.stock_adjustment import StockAdjustment
from shop_management.models.data.utils import Currency, ExchangeRate


class StructuredAuditLogTests(TestCase):
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user(username="auditor", password="secret", is_staff=True)
        self.shop = Shop.objects.create(name="Kabul", owner=self.user)
        self.warehouse = Warehouse.objects.create(shop=self.shop, code="MAIN", name="Main")

    def test_posted_adjustment_records_structured_before_and_after_state(self):
        adjustment = StockAdjustment.objects.create(
            warehouse=self.warehouse, reason="Count correction", created_by=self.user
        )
        adjustment.status = StockAdjustment.Status.POSTED
        adjustment.posted_by = self.user
        adjustment.save()
        event = UserAuditLog.objects.filter(
            model_name="shop_management.StockAdjustment", action="ADJUSTMENT"
        ).latest("timestamp")
        self.assertEqual(event.object_id, str(adjustment.pk))
        self.assertEqual(event.branch_id, self.shop.pk)
        self.assertEqual(event.before_data["status"], "DRAFT")
        self.assertEqual(event.after_data["status"], "POSTED")

    def test_exchange_rate_create_and_update_are_distinct_events(self):
        afn = Currency.objects.create(shop=self.shop, title="AFN")
        usd = Currency.objects.create(shop=self.shop, title="USD")
        rate = ExchangeRate.objects.create(
            shop=self.shop, from_currency=usd, to_currency=afn,
            rate="70", rate_date="2026-09-05",
        )
        rate.rate = "71"
        rate.save()
        events = UserAuditLog.objects.filter(
            model_name="shop_management.ExchangeRate", action="EXCHANGE_RATE_CHANGE"
        )
        self.assertEqual(events.count(), 2)
        self.assertEqual(events.latest("timestamp").before_data["rate"], "70.000000")

    def test_login_event_captures_ip_without_sensitive_credentials(self):
        request = APIRequestFactory().post("/login/", REMOTE_ADDR="192.0.2.10")
        audit_event(
            "LOGIN", actor=self.user, target_user=self.user, request=request,
            reference=self.user.username, branch_id=self.shop.pk,
            after={"selected_branch": str(self.shop.pk)},
        )
        event = UserAuditLog.objects.get(action="LOGIN")
        self.assertEqual(event.ip_address, "192.0.2.10")
        self.assertNotIn("password", event.after_data)

    def test_permission_change_is_audited(self):
        self.user.system_role = "ACCOUNTANT"
        self.user.action_permissions = ["accounting.create_manual_journal"]
        self.user.save()
        event = UserAuditLog.objects.filter(action="PERMISSION_CHANGE").latest("timestamp")
        self.assertEqual(event.user_id, self.user.pk)
        self.assertIn("system_role", event.after_data)
