from rest_framework import serializers

# Cross-app import (photos → tools). String FK in the model avoids DB circular
# import; here we need the class directly for the serializer queryset.
from apps.tools.models import ShotGroup

from .models import GroupPhoto, GroupPhotoAnalysis, Photo, PointOfImpact


class PhotoMetaSerializer(serializers.ModelSerializer):
    """Photo metadata only — the binary `data` field is never exposed in JSON."""

    class Meta:
        model = Photo
        fields = ['id', 'content_type', 'size', 'width', 'height',
                  'uploaded_by', 'uploaded_at', 'description']
        read_only_fields = ['id', 'size', 'width', 'height', 'uploaded_by', 'uploaded_at']


class GroupPhotoAnalysisSerializer(serializers.ModelSerializer):
    class Meta:
        model = GroupPhotoAnalysis
        fields = [
            'group_size_mm', 'group_size_moa',
            'elevation_offset_mm', 'elevation_offset_moa',
            'windage_offset_mm', 'windage_offset_moa',
            'mean_radius_mm', 'mean_radius_moa',
            'notes',
        ]

    def validate(self, attrs):
        instance = GroupPhotoAnalysis(**attrs)
        instance.clean()
        return attrs


class PointOfImpactSerializer(serializers.ModelSerializer):
    # Write: accept Shot PK; Read: compact inline summary
    shot_detail = serializers.SerializerMethodField()

    class Meta:
        model = PointOfImpact
        fields = [
            'id', 'order',
            'shot', 'shot_detail',
            'x_px', 'y_px',
            'x_mm', 'y_mm', 'radius_mm',
            'notes',
        ]

    def get_shot_detail(self, obj):
        if not obj.shot_id:
            return None
        return {
            'id':           obj.shot.pk,
            'shot_number':  obj.shot.shot_number,
            'velocity_fps': str(obj.shot.velocity_fps),
        }


class GroupPhotoSerializer(serializers.ModelSerializer):
    photo = PhotoMetaSerializer(read_only=True)
    photo_id = serializers.PrimaryKeyRelatedField(
        source='photo',
        queryset=Photo.objects.all(),
        write_only=True,
    )
    # shot_group is optional — photos can exist independently of any group
    shot_group = serializers.PrimaryKeyRelatedField(
        queryset=ShotGroup.objects.all(),
        required=False, allow_null=True,
    )
    shot_group_detail = serializers.SerializerMethodField()
    analysis = GroupPhotoAnalysisSerializer(read_only=True)
    points_of_impact = PointOfImpactSerializer(many=True, read_only=True)

    class Meta:
        model = GroupPhoto
        fields = [
            'id', 'photo_id', 'photo',
            'shot_group', 'shot_group_detail', 'caption', 'order',
            'is_public', 'analysis', 'points_of_impact',
        ]

    def get_shot_group_detail(self, obj):
        if not obj.shot_group_id:
            return None
        sg = obj.shot_group
        return {
            'id':         sg.pk,
            'label':      sg.label,
            'distance_m': str(sg.distance_m) if sg.distance_m else None,
        }
