import re

from rest_framework import serializers

from apps.annotations.models import Bookmark, Note

_HEX_COLOR_RE = re.compile(r"^#[0-9A-Fa-f]{6}$")


def validate_highlight_color(value: str) -> str:
    stripped = (value or "").strip()
    if not _HEX_COLOR_RE.match(stripped):
        raise serializers.ValidationError("highlight_color must be a hex color like #fde047.")
    return stripped.lower()


class BookmarkSerializer(serializers.ModelSerializer):
    ebook_title = serializers.CharField(source="ebook.title", read_only=True)

    class Meta:
        model = Bookmark
        fields = [
            "id",
            "ebook",
            "ebook_title",
            "epub_cfi",
            "chapter_index",
            "chapter_title",
            "page",
            "location_text",
            "content",
            "highlight_color",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at", "ebook_title", "page"]


class BookmarkCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bookmark
        fields = [
            "ebook",
            "epub_cfi",
            "chapter_index",
            "chapter_title",
            "location_text",
            "content",
            "highlight_color",
        ]

    def validate_highlight_color(self, value: str) -> str:
        return validate_highlight_color(value)

    def validate_epub_cfi(self, value: str) -> str:
        stripped = (value or "").strip()
        if not stripped:
            raise serializers.ValidationError("epub_cfi is required.")
        return stripped

    def validate_chapter_index(self, value: int) -> int:
        if value < 0:
            raise serializers.ValidationError("chapter_index must be non-negative.")
        return value

    def validate(self, attrs):
        user = self.context["request"].user
        ebook = attrs["ebook"]
        epub_cfi = attrs["epub_cfi"]
        if Bookmark.objects.filter(user=user, ebook=ebook, epub_cfi=epub_cfi).exists():
            raise serializers.ValidationError(
                {"epub_cfi": "A marker already exists for this passage."}
            )
        return attrs

    def create(self, validated_data):
        validated_data["user"] = self.context["request"].user
        validated_data["page"] = validated_data.get("chapter_index", 0) + 1
        validated_data["content"] = (validated_data.get("content") or "").strip()
        return super().create(validated_data)


class NoteSerializer(serializers.ModelSerializer):
    book_title = serializers.CharField(source="book.title", read_only=True)

    class Meta:
        model = Note
        fields = [
            "id",
            "book",
            "book_title",
            "page",
            "location_text",
            "content",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at", "book_title"]

    def validate_page(self, value: int) -> int:
        if value < 1:
            raise serializers.ValidationError("Page must be a positive integer.")
        return value


class NoteCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = ["book", "page", "location_text", "content"]

    def validate_page(self, value: int) -> int:
        if value < 1:
            raise serializers.ValidationError("Page must be a positive integer.")
        return value

    def validate_content(self, value: str) -> str:
        stripped = value.strip()
        if not stripped:
            raise serializers.ValidationError("Note content cannot be empty.")
        return stripped

    def create(self, validated_data):
        validated_data["user"] = self.context["request"].user
        return super().create(validated_data)
