# (c) cavaliba.com - test_datatask_views

from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from app_data.tasks import create_datatask, finish_task
from tests import helper


class TaskNavbarPartialTest(TestCase):
    def setUp(self):
        cache.clear()

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_returns_200(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        response = self.client.get(reverse("app_data:task_navbar_partial"))
        self.assertEqual(response.status_code, 200)

    def test_no_auth_returns_empty(self):
        response = self.client.get(reverse("app_data:task_navbar_partial"))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, b"")

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_shows_running_task(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        dt = create_datatask("my long task", owner_id="unittest")
        dt.state = "RUNNING"
        dt.save()
        response = self.client.get(reverse("app_data:task_navbar_partial"))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b"my long task", response.content)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_no_tasks_returns_idle_state(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        response = self.client.get(reverse("app_data:task_navbar_partial"))
        self.assertEqual(response.status_code, 200)
        # No active tasks — idle state rendered, no running indicator
        self.assertIn(b"datatask-label-idle", response.content)
        self.assertNotIn(b"datatask-label-running", response.content)


class TaskListViewTest(TestCase):
    def setUp(self):
        cache.clear()

    def test_requires_auth(self):
        response = self.client.get(reverse("app_data:task_list"))
        # Unauthenticated → redirect to login
        self.assertNotEqual(response.status_code, 200)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_empty_list(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        response = self.client.get(reverse("app_data:task_list"))
        self.assertEqual(response.status_code, 200)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_shows_own_tasks(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        create_datatask("task A", owner_id="unittest")
        response = self.client.get(reverse("app_data:task_list"))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b"task A", response.content)


class TaskAdminListViewTest(TestCase):
    def setUp(self):
        cache.clear()

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_admin_access(self):
        helper.add_admin_user(login="unittest")
        response = self.client.get(reverse("app_data:task_list"))
        self.assertEqual(response.status_code, 200)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_non_admin_sees_own_list_but_not_others_tasks(self):
        """No permission gates the list since p_task_view was dropped - a
        logged-in user reaches it, scoped to their own tasks."""

        helper.add_user_with_perm(login="unittest", perms=["p_data_access"])
        create_datatask("task of someone else", owner_id="someuser")
        response = self.client.get(reverse("app_data:task_list"))
        self.assertEqual(response.status_code, 200)
        self.assertNotIn(b"task of someone else", response.content)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_shows_all_tasks(self):
        helper.add_admin_user(login="unittest")
        create_datatask("task B", owner_id="someuser")
        response = self.client.get(reverse("app_data:task_list"))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b"task B", response.content)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_state_filter(self):
        helper.add_admin_user(login="unittest")
        dt = create_datatask("done task", owner_id="u1")
        finish_task(dt.handle, state="DONE")
        create_datatask("queued task", owner_id="u1")
        response = self.client.get(reverse("app_data:task_list") + "?state=DONE")
        self.assertEqual(response.status_code, 200)
        self.assertIn(b"done task", response.content)
        self.assertNotIn(b"queued task", response.content)


class TaskDetailViewTest(TestCase):
    """Detail needs no permission for one's own task (p_task_view was dropped),
    and ownership alone keeps someone else's task out without p_task_all."""

    def setUp(self):
        cache.clear()

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_own_task_without_any_permission(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        dt = create_datatask("my task", owner_id="unittest")
        response = self.client.get(reverse("app_data:task_detail", kwargs={"handle": dt.handle}))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b"my task", response.content)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_other_users_task_is_refused(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        dt = create_datatask("not my task", owner_id="someuser")
        response = self.client.get(reverse("app_data:task_detail", kwargs={"handle": dt.handle}))
        self.assertEqual(response.status_code, 302)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_other_users_task_with_task_all(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all"])
        dt = create_datatask("not my task", owner_id="someuser")
        response = self.client.get(reverse("app_data:task_detail", kwargs={"handle": dt.handle}))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b"not my task", response.content)

    def test_requires_auth(self):
        dt = create_datatask("my task", owner_id="unittest")
        response = self.client.get(reverse("app_data:task_detail", kwargs={"handle": dt.handle}))
        self.assertNotEqual(response.status_code, 200)


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class TaskStopViewTest(TestCase):
    """Stopping follows the browsing rule since 5.4.0: your own task needs no
    permission, somebody else's needs p_task_manage (and p_task_all to be
    visible at all)."""

    def setUp(self):
        cache.clear()

    def _stop(self, handle, method="post"):
        url = reverse("app_data:task_stop", kwargs={"handle": handle})
        return getattr(self.client, method)(url)

    def test_stop_queued_task(self):
        helper.add_admin_user(login="unittest")
        dt = create_datatask("t", owner_id="u1")

        response = self._stop(dt.handle)

        self.assertEqual(response.status_code, 302)
        dt.refresh_from_db()
        self.assertEqual(dt.state, "ABORTED")

    def test_get_does_not_stop(self):
        helper.add_admin_user(login="unittest")
        dt = create_datatask("t", owner_id="u1")

        self._stop(dt.handle, method="get")

        dt.refresh_from_db()
        self.assertEqual(dt.state, "QUEUED")

    def test_own_task_stops_without_any_permission(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        dt = create_datatask("t", owner_id="unittest")

        self._stop(dt.handle)

        dt.refresh_from_db()
        self.assertEqual(dt.state, "ABORTED")

    def test_someone_elses_task_is_not_found_without_p_task_all(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_manage"])
        dt = create_datatask("t", owner_id="someone_else")

        response = self._stop(dt.handle)

        self.assertEqual(response.status_code, 404)
        dt.refresh_from_db()
        self.assertEqual(dt.state, "QUEUED")

    def test_someone_elses_task_needs_p_task_manage(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all"])
        dt = create_datatask("t", owner_id="someone_else")

        response = self._stop(dt.handle)

        self.assertEqual(response.status_code, 302)
        dt.refresh_from_db()
        self.assertEqual(dt.state, "QUEUED")

    def test_someone_elses_task_stops_with_both(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all", "p_task_manage"])
        dt = create_datatask("t", owner_id="someone_else")

        self._stop(dt.handle)

        dt.refresh_from_db()
        self.assertEqual(dt.state, "ABORTED")

    def test_unknown_handle_is_not_found(self):
        helper.add_user_with_perm(login="unittest", perms=[])

        response = self._stop("8e2b2a1e-0000-4000-8000-000000000000")

        self.assertEqual(response.status_code, 404)
