from ninja import Router, File
from ninja.files import UploadedFile
from ninja.pagination import paginate
from django.db import transaction
from django.core.files.base import ContentFile
from django.http import Http404
from django.utils import timezone
from django.shortcuts import get_object_or_404
from typing import List

from .models import Submission, PuzzleResponse, SubmissionFile, SteamCollectionItem
from .schemas import (
    SubmissionIn,
    SubmissionOut,
    PuzzleResponseOut,
    ValidationIn,
    SteamCollectionItemOut,
)

router = Router()


@router.get("/puzzles", response=List[SteamCollectionItemOut])
def list_puzzles(request):
    """Get list of available puzzles"""
    return SteamCollectionItem.objects.select_related("collection").filter(
        collection__is_active=True
    )


@router.get("/submissions", response=List[SubmissionOut])
@paginate
def list_submissions(request):
    """Get paginated list of submissions"""
    return Submission.objects.prefetch_related(
        "responses__files", "responses__puzzle"
    ).filter(user=request.user)


@router.get("/submissions/{submission_id}", response=SubmissionOut)
def get_submission(request, submission_id: str):
    """Get detailed submission by ID"""
    return get_object_or_404(
        Submission.objects.prefetch_related(
            "responses__files", "responses__puzzle"
        ).filter(user=request.user),
        id=submission_id,
    )


@router.post("/submissions", response=SubmissionOut)
def create_submission(
    request, data: SubmissionIn, files: List[UploadedFile] = File(...)
):
    """Create a new submission with multiple puzzle responses"""

    # Validate that we have files
    if not files:
        return 400, {"detail": "At least one file is required"}

    # Group files by puzzle (based on filename or order)
    # For now, we'll assume files are provided in the same order as responses
    if len(files) < len(data.responses):
        return 400, {"detail": "Not enough files for all responses"}

    print(data, files)

    try:
        with transaction.atomic():
            # Create the submission
            submission = Submission.objects.create(
                user=request.user if request.user.is_authenticated else None,
                notes=data.notes,
            )

            file_index = 0
            for response_data in data.responses:
                # Get the puzzle
                try:
                    puzzle = SteamCollectionItem.objects.get(id=response_data.puzzle_id)
                except SteamCollectionItem.DoesNotExist:
                    return 400, {
                        "detail": f"Puzzle with id {response_data.puzzle_id} not found"
                    }

                # Create the puzzle response
                response = PuzzleResponse.objects.create(
                    submission=submission,
                    puzzle=puzzle,
                    puzzle_name=response_data.puzzle_name,
                    cost=response_data.cost,
                    cycles=response_data.cycles,
                    area=response_data.area,
                    needs_manual_validation=response_data.needs_manual_validation,
                    ocr_confidence_score=response_data.ocr_confidence_score,
                )

                # Process files for this response
                # For simplicity, we'll take one file per response
                # In a real implementation, you'd need better file-to-response mapping
                if file_index < len(files):
                    uploaded_file = files[file_index]

                    # Validate file type
                    if not uploaded_file.content_type.startswith(("image/", "video/")):
                        return 400, {
                            "detail": f"Invalid file type: {uploaded_file.content_type}"
                        }

                    # Validate file size (256MB limit)
                    if uploaded_file.size > 256 * 1024 * 1024:
                        return 400, {"detail": "File too large (max 256MB)"}

                    # Create submission file
                    submission_file = SubmissionFile.objects.create(
                        response=response,
                        original_filename=uploaded_file.name,
                        file_size=uploaded_file.size,
                        content_type=uploaded_file.content_type,
                    )

                    # Save the file
                    submission_file.file.save(
                        uploaded_file.name, ContentFile(uploaded_file.read()), save=True
                    )

                    file_index += 1

                # Check if OCR validation is needed
                if not all(
                    [response_data.cost, response_data.cycles, response_data.area]
                ):
                    response.mark_for_validation("Incomplete OCR data")

            # Reload with relations for response
            submission = Submission.objects.prefetch_related(
                "responses__files", "responses__puzzle"
            ).get(id=submission.id)

            return submission

    except Exception as e:
        print(e)
        return 500, {"detail": f"Error creating submission: {str(e)}"}


@router.put("/responses/{response_id}/validate", response=PuzzleResponseOut)
def validate_response(request, response_id: int, data: ValidationIn):
    """Manually validate a puzzle response"""

    if not request.user.is_authenticated or not request.user.is_staff:
        return 403, {"detail": "Admin access required"}

    try:
        response = PuzzleResponse.objects.select_related("puzzle").get(id=response_id)

        # Update validated values
        if data.validated_cost is not None:
            response.validated_cost = data.validated_cost
        if data.validated_cycles is not None:
            response.validated_cycles = data.validated_cycles
        if data.validated_area is not None:
            response.validated_area = data.validated_area

        # Mark as no longer needing validation if we have all values
        if all([response.final_cost, response.final_cycles, response.final_area]):
            response.needs_manual_validation = False

        response.save()

        return response

    except PuzzleResponse.DoesNotExist:
        raise Http404("Response not found")


@router.get("/responses/needs-validation", response=List[PuzzleResponseOut])
def list_responses_needing_validation(request):
    """Get all responses that need manual validation"""

    if not request.user.is_authenticated or not request.user.is_staff:
        return 403, {"detail": "Admin access required"}

    return (
        PuzzleResponse.objects.filter(needs_manual_validation=True)
        .select_related("puzzle", "submission")
        .prefetch_related("files")
    )


@router.post("/submissions/{submission_id}/validate", response=SubmissionOut)
def validate_submission(request, submission_id: str):
    """Mark entire submission as validated"""

    if not request.user.is_authenticated or not request.user.is_staff:
        return 403, {"detail": "Admin access required"}

    try:
        submission = Submission.objects.get(id=submission_id)

        submission.is_validated = True
        submission.validated_by = request.user
        submission.validated_at = timezone.now()
        submission.save()

        # Also mark all responses as not needing validation
        submission.responses.update(needs_manual_validation=False)

        # Reload with relations
        submission = Submission.objects.prefetch_related(
            "responses__files", "responses__puzzle"
        ).get(id=submission.id)

        return submission

    except Submission.DoesNotExist:
        raise Http404("Submission not found")


@router.delete("/submissions/{submission_id}")
def delete_submission(request, submission_id: str):
    """Delete a submission (admin only)"""

    if not request.user.is_authenticated or not request.user.is_staff:
        return 403, {"detail": "Admin access required"}

    try:
        submission = Submission.objects.get(id=submission_id)
        submission.delete()
        return {"detail": "Submission deleted successfully"}

    except Submission.DoesNotExist:
        raise Http404("Submission not found")


@router.get("/stats")
def get_stats(request):
    """Get submission statistics"""

    total_submissions = Submission.objects.count()
    total_responses = PuzzleResponse.objects.count()
    needs_validation = PuzzleResponse.objects.filter(
        needs_manual_validation=True
    ).count()
    validated_submissions = Submission.objects.filter(is_validated=True).count()

    return {
        "total_submissions": total_submissions,
        "total_responses": total_responses,
        "needs_validation": needs_validation,
        "validated_submissions": validated_submissions,
        "validation_rate": validated_submissions / total_submissions
        if total_submissions > 0
        else 0,
    }
