from types import SimpleNamespace
from unittest.mock import MagicMock, patch

from django.test import RequestFactory, SimpleTestCase

from ledgers.ledgers_helper import get_transactional_charts
from ledgers.serializers import OrganisationSubAccountSerializer
from ledgers.views import OrganisationSubAccountView, SystemTransactionalChartsView


class OrganisationSubAccountSerializerTests(SimpleTestCase):
    @patch('ledgers.serializers.OrganisationSubAccount.objects.filter')
    def test_get_child_accounts_excludes_deleted_children(self, filter_mock):
        queryset = MagicMock()
        queryset.order_by.return_value = []
        filter_mock.return_value = queryset

        serializer = OrganisationSubAccountSerializer()
        result = serializer.get_child_accounts(SimpleNamespace(id=123))

        filter_mock.assert_called_once_with(parent_id=123, deleted=False)
        self.assertEqual(result, [])


class OrganisationSubAccountViewTests(SimpleTestCase):
    @patch('ledgers.views.get_current_user', return_value=77)
    @patch('ledgers.views.OrganisationSubAccount.objects.filter')
    def test_get_queryset_excludes_deleted_accounts(self, filter_mock, get_current_user_mock):
        queryset = MagicMock()
        queryset.order_by.return_value = []
        filter_mock.return_value = queryset

        request = RequestFactory().get('/api/organisationsubaccounts/?line=assets')
        view = OrganisationSubAccountView()
        view.request = request

        result = view.get_queryset()

        filter_mock.assert_called_once_with(
            account_line='assets',
            account_organisation=77,
            parent_id__isnull=True,
            deleted=False,
        )
        self.assertEqual(result, [])


class TransactionalChartsTests(SimpleTestCase):
    @patch('ledgers.ledgers_helper.OrganisationSubAccount.objects.filter')
    def test_get_transactional_charts_excludes_deleted_accounts(self, filter_mock):
        queryset = MagicMock()
        queryset.order_by.return_value = []
        filter_mock.return_value = queryset

        result = get_transactional_charts(77)

        filter_mock.assert_called_once_with(
            account_organisation_id=77,
            parent_id_id__gte=1,
            child_accounts__isnull=True,
            deleted=False,
        )
        self.assertEqual(result, [])

    @patch('ledgers.views.OrganisationSubAccountSerializer')
    @patch('ledgers.views.get_transactional_charts')
    @patch('ledgers.views.get_current_user', side_effect=[77, 11])
    def test_aggregated_transactional_charts_skip_deleted_parents(
        self,
        get_current_user_mock,
        get_transactional_charts_mock,
        serializer_mock,
    ):
        active_parent = SimpleNamespace(id=1, deleted=False)
        deleted_parent = SimpleNamespace(id=2, deleted=True)
        active_chart = SimpleNamespace(id=101, parent_id=active_parent)
        deleted_parent_child = SimpleNamespace(id=102, parent_id=deleted_parent)

        get_transactional_charts_mock.return_value = [active_chart, deleted_parent_child]

        serializer_instance = MagicMock()
        serializer_instance.data = []
        serializer_mock.return_value = serializer_instance

        request = RequestFactory().get('/api/transactional-charts/?filter=agregated')
        view = SystemTransactionalChartsView()
        response = view.get(request)

        passed_charts = serializer_mock.call_args.args[0]
        self.assertEqual(passed_charts, [active_parent, active_chart, deleted_parent_child])
        self.assertEqual(response.status_code, 200)
