from rest_framework import serializers

from .models import (
    BlogPost,
    BlogTag,
)


class BlogPostAdminListSerializer(serializers.ModelSerializer):

    category_name = serializers.CharField(
        source="category.name",
        read_only=True,
    )

    author_name = serializers.CharField(
        source="author.display_name",
        read_only=True,
    )

    class Meta:
        model = BlogPost

        fields = [
            "id",
            "title",
            "slug",
            "status",
            "author_name",
            "category_name",
            "views_count",
            "published_at",
            "created_at",
        ]


class BlogPostAdminDetailSerializer(serializers.ModelSerializer):

    tags = serializers.SerializerMethodField()

    meta_title = serializers.SerializerMethodField()

    meta_description = serializers.SerializerMethodField()

    keywords = serializers.SerializerMethodField()

    canonical_url = serializers.SerializerMethodField()

    og_title = serializers.SerializerMethodField()

    og_description = serializers.SerializerMethodField()

    og_image = serializers.SerializerMethodField()

    class Meta:
        model = BlogPost

        fields = [
            "id",

            "title",
            "excerpt",
            "content",
            "featured_image",

            "author",
            "category",

            "tags",

            "status",
            "is_featured",

            # SEO
            "meta_title",
            "meta_description",
            "keywords",
            "canonical_url",
            "og_title",
            "og_description",
            "og_image",
        ]

    def get_tags(self, obj):
        return [
            {
                "id": tag.id,
                "name": tag.name,
            }
            for tag in obj.tags.all()
        ]

    def _seo(self, obj):
        return getattr(obj, "seo", None)

    def get_meta_title(self, obj):
        seo = self._seo(obj)
        return seo.meta_title if seo else ""

    def get_meta_description(self, obj):
        seo = self._seo(obj)
        return seo.meta_description if seo else ""

    def get_keywords(self, obj):
        seo = self._seo(obj)
        return seo.keywords if seo else ""

    def get_canonical_url(self, obj):
        seo = self._seo(obj)
        return seo.canonical_url if seo else ""

    def get_og_title(self, obj):
        seo = self._seo(obj)
        return seo.og_title if seo else ""

    def get_og_description(self, obj):
        seo = self._seo(obj)
        return seo.og_description if seo else ""

    def get_og_image(self, obj):

        if not hasattr(obj, "seo") or not obj.seo.og_image:
            return None

        request = self.context.get("request")

        if request:
            return request.build_absolute_uri(obj.seo.og_image.url)

        return obj.seo.og_image.url


class BlogPostAdminWriteSerializer(serializers.ModelSerializer):

    tag_ids = serializers.PrimaryKeyRelatedField(
        queryset=BlogTag.objects.all(),
        many=True,
        write_only=True,
        required=False,
    )

    class Meta:
        model = BlogPost

        fields = [
            "id",

            "title",
            "excerpt",
            "content",
            "featured_image",

            "author",
            "category",

            "tag_ids",

            "status",
            "is_featured",
        ]

        read_only_fields = [
            "id",
            "author",
        ]

    def create(self, validated_data):

        tags = validated_data.pop("tag_ids", [])

        post = BlogPost.objects.create(**validated_data)

        post.tags.set(tags)

        return post

    def update(self, instance, validated_data):

        tags = validated_data.pop("tag_ids", None)

        for field, value in validated_data.items():
            setattr(instance, field, value)

        instance.save()

        if tags is not None:
            instance.tags.set(tags)

        return instance
    

