import pytest
from django.contrib.auth import get_user_model

from apps.chatbot.models import ChatSession
from apps.chatbot.tools import list_projects, list_tasks
from apps.core.models import Permission, Role, UserRole
from apps.companies.models import Organization
from apps.projects.models import Project, ProjectTeamMember
from apps.tasks.models import Task

User = get_user_model()


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


@pytest.fixture
def staff_user(db, organization):
    u = User.objects.create_user(email="staff@example.com", password="pass123")
    organization.members.add(u)
    return u


@pytest.fixture
def manager_user(db, organization):
    user = User.objects.create_user(email="manager@example.com", password="pass123")
    organization.members.add(user)
    perm, _ = Permission.objects.get_or_create(domain="project", action="delete", defaults={"label": "Project: Delete"})
    task_perm, _ = Permission.objects.get_or_create(domain="tasks", action="delete", defaults={"label": "Tasks: Delete"})
    role = Role.objects.create(name="Manager", slug="manager-test")
    role.permissions.add(perm, task_perm)
    UserRole.objects.create(user=user, role=role, organization=organization)
    return user


@pytest.fixture
def own_project(db, staff_user, organization):
    project = Project.objects.create(organization=organization, name="Own Project")
    ProjectTeamMember.objects.create(project=project, user=staff_user, role="member")
    return project


@pytest.fixture
def other_project(db, organization):
    return Project.objects.create(organization=organization, name="Other Project")


@pytest.mark.django_db
class TestChatSessionModel:
    def test_session_str_defaults_to_id(self, staff_user):
        session = ChatSession.objects.create(user=staff_user)
        assert str(session.id) in str(session)

    def test_session_scoped_to_owner(self, staff_user, manager_user):
        ChatSession.objects.create(user=staff_user, title="staff session")
        ChatSession.objects.create(user=manager_user, title="manager session")
        assert ChatSession.objects.filter(user=staff_user).count() == 1


@pytest.mark.django_db
class TestListProjectsScoping:
    def test_staff_sees_only_own_projects(self, staff_user, own_project, other_project):
        result = list_projects(staff_user)
        names = {p["name"] for p in result}
        assert names == {"Own Project"}

    def test_manager_sees_all_projects(self, manager_user, own_project, other_project):
        result = list_projects(manager_user)
        names = {p["name"] for p in result}
        assert names == {"Own Project", "Other Project"}


@pytest.mark.django_db
class TestListTasksScoping:
    def test_staff_sees_only_own_tasks(self, staff_user, own_project, other_project, organization):
        Task.objects.create(organization=organization, title="Mine", project=own_project, created_by=staff_user, assignee=staff_user)
        other_owner = User.objects.create_user(email="other@example.com", password="pass123")
        Task.objects.create(organization=organization, title="Not mine", project=other_project, created_by=other_owner, assignee=other_owner)

        result = list_tasks(staff_user)
        titles = {t["title"] for t in result}
        assert titles == {"Mine"}

    def test_manager_sees_all_tasks(self, manager_user, staff_user, own_project, other_project, organization):
        Task.objects.create(organization=organization, title="Mine", project=own_project, created_by=staff_user, assignee=staff_user)
        Task.objects.create(organization=organization, title="Not mine", project=other_project, created_by=staff_user)

        result = list_tasks(manager_user)
        titles = {t["title"] for t in result}
        assert titles == {"Mine", "Not mine"}

    def test_archived_tasks_excluded_by_default(self, staff_user, own_project, organization):
        Task.objects.create(organization=organization, title="Active", project=own_project, created_by=staff_user, assignee=staff_user, status="todo")
        Task.objects.create(organization=organization, title="Archived", project=own_project, created_by=staff_user, assignee=staff_user, status="archived")

        result = list_tasks(staff_user)
        titles = {t["title"] for t in result}
        assert titles == {"Active"}
