from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.db import IntegrityError, transaction
from django.test import TestCase
from django.utils import timezone

from apps.accounts.models import Invite, Organization, Role

User = get_user_model()

class AccountsModelTests(TestCase):
    def setUp(self):
        self.owner = User.objects.create_user(
            email_address='owner@example.com',
            password='pass1234',
            first_name='Owner',
            last_name='User',
            date_of_birth='1990-01-01',
            is_manager=True,
        )
        self.member = User.objects.create_user(
            email_address='member@example.com',
            password='pass1234',
            first_name='Member',
            last_name='User',
            date_of_birth='1992-02-02',
        )

    def test_user_fields_and_defaults(self):
        self.assertEqual(self.owner.email_address, 'owner@example.com')
        self.assertEqual(self.owner.first_name, 'Owner')
        self.assertEqual(self.owner.last_name, 'User')
        self.assertEqual(str(self.owner.date_of_birth), '1990-01-01')

        self.assertTrue(self.owner.is_active)
        self.assertFalse(self.owner.is_staff)
        self.assertTrue(self.owner.is_manager)

        self.assertIsNotNone(self.owner.id)
        self.assertIsNotNone(self.owner.uuid)
        self.assertIsNotNone(self.owner.created_at)
        self.assertIsNotNone(self.owner.updated_at)

        self.assertEqual(self.owner.full_name, 'Owner User')
        self.assertEqual(str(self.owner), 'Owner User')

    def test_organization_fields_and_relations(self):
        org = Organization.objects.create(
            name='Acme',
            description='Primary org',
            owner=self.owner,
        )
        org.members.add(self.owner, self.member)

        self.assertEqual(org.name, 'Acme')
        self.assertEqual(org.description, 'Primary org')
        self.assertEqual(org.owner, self.owner)
        self.assertEqual(org.members.count(), 2)

        self.assertIsNotNone(org.id)
        self.assertIsNotNone(org.uuid)
        self.assertIsNotNone(org.created_at)
        self.assertIsNotNone(org.updated_at)

        self.assertEqual(str(org), 'Acme')

    def test_invite_fields_defaults_and_validity(self):
        org = Organization.objects.create(name='Org B', owner=self.owner)
        invite = Invite.objects.create(organization=org, created_by=self.owner)

        self.assertIsNotNone(invite.uuid)
        self.assertEqual(invite.organization, org)
        self.assertEqual(invite.created_by, self.owner)
        self.assertEqual(invite.uses, 0)
        self.assertEqual(invite.max_uses, 1)
        self.assertTrue(invite.is_active)
        self.assertGreater(invite.expires_at, timezone.now())
        self.assertTrue(invite.is_valid())

        invite.uses = 1
        invite.save(update_fields=['uses'])
        self.assertFalse(invite.is_valid())

    def test_role_fields_relations_and_string(self):
        org = Organization.objects.create(name='Org C', owner=self.owner)
        role = Role.objects.create(name='Engineer', description='Builds things', organization=org)
        role.members.add(self.member)

        self.assertEqual(role.name, 'Engineer')
        self.assertEqual(role.description, 'Builds things')
        self.assertEqual(role.organization, org)
        self.assertEqual(role.members.count(), 1)

        self.assertIsNotNone(role.id)
        self.assertIsNotNone(role.uuid)
        self.assertIsNotNone(role.created_at)
        self.assertIsNotNone(role.updated_at)

        self.assertEqual(str(role), 'Engineer (Org C)')

    def test_owner_is_added_to_members_on_create(self):
        org = Organization.objects.create(name='Org Owner Membership', owner=self.owner)
        self.assertTrue(org.members.filter(id=self.owner.id).exists())

    def test_owner_cannot_be_removed_from_members(self):
        org = Organization.objects.create(name='Org Owner Locked', owner=self.owner)
        org.members.add(self.owner)

        with self.assertRaises(ValidationError):
            org.members.remove(self.owner)

    def test_owner_remains_member_after_clear(self):
        org = Organization.objects.create(name='Org Clear Members', owner=self.owner)
        org.members.add(self.owner, self.member)
        org.members.clear()

        self.assertTrue(org.members.filter(id=self.owner.id).exists())
        self.assertFalse(org.members.filter(id=self.member.id).exists())

    def test_role_name_unique_per_organization(self):
        org = Organization.objects.create(name='Org Role Scoped', owner=self.owner)
        other_org = Organization.objects.create(name='Org Role Scoped 2', owner=self.member)
        Role.objects.create(name='Analyst', organization=org)
        Role.objects.create(name='Analyst', organization=other_org)

        with self.assertRaises(IntegrityError):
            with transaction.atomic():
                Role.objects.create(name='Analyst', organization=org)
