from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin,
)
from django.db import models


class EmailUserManager(BaseUserManager):
    """Custom user manager using email as the unique identifier."""

    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError("Email is required")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        return self.create_user(email, password, **extra_fields)


class EmailUser(AbstractBaseUser, PermissionsMixin):
    """Minimal user model with email as USERNAME_FIELD.

    Matches the calling convention used in mizan's test suite:
        User.objects.create_user(email="...", password="...", is_staff=True)
    """

    email = models.EmailField(unique=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    objects = EmailUserManager()

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    class Meta:
        app_label = "tests"


# ─── Shape test models ──────────────────────────────────────────────────────

import uuid


class TimestampMixin(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class Publisher(TimestampMixin):
    name = models.CharField(max_length=200)
    country = models.CharField(max_length=100, default="")

    class Meta:
        app_label = "tests"


class Author(TimestampMixin):
    name = models.CharField(max_length=200)
    bio = models.TextField(default="")
    publisher = models.ForeignKey(
        Publisher, on_delete=models.CASCADE, related_name="authors"
    )
    mentor = models.ForeignKey(
        "self", on_delete=models.SET_NULL, null=True, blank=True, related_name="mentees"
    )

    class Meta:
        app_label = "tests"


class Tag(models.Model):
    slug = models.SlugField(primary_key=True, max_length=100)
    label = models.CharField(max_length=100)

    class Meta:
        app_label = "tests"


class Book(TimestampMixin):
    title = models.CharField(max_length=300)
    isbn = models.CharField(max_length=13, unique=True)
    page_count = models.IntegerField(default=0)
    is_published = models.BooleanField(default=False)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books")
    editor = models.ForeignKey(
        Author,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="edited_books",
    )
    tags = models.ManyToManyField(Tag, blank=True, related_name="books")

    class Meta:
        app_label = "tests"


class Chapter(TimestampMixin):
    book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name="chapters")
    number = models.IntegerField()
    title = models.CharField(max_length=300)
    word_count = models.IntegerField(default=0)

    class Meta:
        app_label = "tests"
        ordering = ["number"]
        unique_together = [("book", "number")]


class Section(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    chapter = models.ForeignKey(
        Chapter, on_delete=models.CASCADE, related_name="sections"
    )
    heading = models.CharField(max_length=300)
    body = models.TextField(default="")
    position = models.IntegerField(default=0)

    class Meta:
        app_label = "tests"
        ordering = ["position"]


class Category(models.Model):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey(
        "self", on_delete=models.CASCADE, null=True, blank=True, related_name="children"
    )

    class Meta:
        app_label = "tests"
