"""
Versioning API endpoints for ThrillWiki.

Provides REST API for:
- Version history for entities
- Specific version details
- Comparing versions
- Diff with current state
- Version restoration (optional)
"""

from typing import List
from uuid import UUID
from django.shortcuts import get_object_or_404
from django.http import Http404
from ninja import Router

from apps.entities.models import Park, Ride, Company, RideModel
from apps.versioning.models import EntityVersion
from apps.versioning.services import VersionService
from api.v1.schemas import (
    EntityVersionSchema,
    VersionHistoryResponseSchema,
    VersionDiffSchema,
    VersionComparisonSchema,
    ErrorSchema,
    MessageSchema
)

router = Router(tags=['Versioning'])


# Park Versions

@router.get(
    '/parks/{park_id}/versions',
    response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
    summary="Get park version history"
)
def get_park_versions(request, park_id: UUID, limit: int = 50):
    """
    Get version history for a park.
    
    Returns up to `limit` versions in reverse chronological order (newest first).
    """
    park = get_object_or_404(Park, id=park_id)
    versions = VersionService.get_version_history(park, limit=limit)
    
    return {
        'entity_id': str(park.id),
        'entity_type': 'park',
        'entity_name': park.name,
        'total_versions': VersionService.get_version_count(park),
        'versions': [
            EntityVersionSchema.from_orm(v) for v in versions
        ]
    }


@router.get(
    '/parks/{park_id}/versions/{version_number}',
    response={200: EntityVersionSchema, 404: ErrorSchema},
    summary="Get specific park version"
)
def get_park_version(request, park_id: UUID, version_number: int):
    """Get a specific version of a park by version number."""
    park = get_object_or_404(Park, id=park_id)
    version = VersionService.get_version_by_number(park, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    return EntityVersionSchema.from_orm(version)


@router.get(
    '/parks/{park_id}/versions/{version_number}/diff',
    response={200: VersionDiffSchema, 404: ErrorSchema},
    summary="Compare park version with current"
)
def get_park_version_diff(request, park_id: UUID, version_number: int):
    """
    Compare a specific version with the current park state.
    
    Returns the differences between the version and current values.
    """
    park = get_object_or_404(Park, id=park_id)
    version = VersionService.get_version_by_number(park, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    diff = VersionService.get_diff_with_current(version)
    
    return {
        'entity_id': str(park.id),
        'entity_type': 'park',
        'entity_name': park.name,
        'version_number': version.version_number,
        'version_date': version.created,
        'differences': diff['differences'],
        'changed_field_count': diff['changed_field_count']
    }


# Ride Versions

@router.get(
    '/rides/{ride_id}/versions',
    response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
    summary="Get ride version history"
)
def get_ride_versions(request, ride_id: UUID, limit: int = 50):
    """Get version history for a ride."""
    ride = get_object_or_404(Ride, id=ride_id)
    versions = VersionService.get_version_history(ride, limit=limit)
    
    return {
        'entity_id': str(ride.id),
        'entity_type': 'ride',
        'entity_name': ride.name,
        'total_versions': VersionService.get_version_count(ride),
        'versions': [
            EntityVersionSchema.from_orm(v) for v in versions
        ]
    }


@router.get(
    '/rides/{ride_id}/versions/{version_number}',
    response={200: EntityVersionSchema, 404: ErrorSchema},
    summary="Get specific ride version"
)
def get_ride_version(request, ride_id: UUID, version_number: int):
    """Get a specific version of a ride by version number."""
    ride = get_object_or_404(Ride, id=ride_id)
    version = VersionService.get_version_by_number(ride, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    return EntityVersionSchema.from_orm(version)


@router.get(
    '/rides/{ride_id}/versions/{version_number}/diff',
    response={200: VersionDiffSchema, 404: ErrorSchema},
    summary="Compare ride version with current"
)
def get_ride_version_diff(request, ride_id: UUID, version_number: int):
    """Compare a specific version with the current ride state."""
    ride = get_object_or_404(Ride, id=ride_id)
    version = VersionService.get_version_by_number(ride, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    diff = VersionService.get_diff_with_current(version)
    
    return {
        'entity_id': str(ride.id),
        'entity_type': 'ride',
        'entity_name': ride.name,
        'version_number': version.version_number,
        'version_date': version.created,
        'differences': diff['differences'],
        'changed_field_count': diff['changed_field_count']
    }


# Company Versions

@router.get(
    '/companies/{company_id}/versions',
    response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
    summary="Get company version history"
)
def get_company_versions(request, company_id: UUID, limit: int = 50):
    """Get version history for a company."""
    company = get_object_or_404(Company, id=company_id)
    versions = VersionService.get_version_history(company, limit=limit)
    
    return {
        'entity_id': str(company.id),
        'entity_type': 'company',
        'entity_name': company.name,
        'total_versions': VersionService.get_version_count(company),
        'versions': [
            EntityVersionSchema.from_orm(v) for v in versions
        ]
    }


@router.get(
    '/companies/{company_id}/versions/{version_number}',
    response={200: EntityVersionSchema, 404: ErrorSchema},
    summary="Get specific company version"
)
def get_company_version(request, company_id: UUID, version_number: int):
    """Get a specific version of a company by version number."""
    company = get_object_or_404(Company, id=company_id)
    version = VersionService.get_version_by_number(company, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    return EntityVersionSchema.from_orm(version)


@router.get(
    '/companies/{company_id}/versions/{version_number}/diff',
    response={200: VersionDiffSchema, 404: ErrorSchema},
    summary="Compare company version with current"
)
def get_company_version_diff(request, company_id: UUID, version_number: int):
    """Compare a specific version with the current company state."""
    company = get_object_or_404(Company, id=company_id)
    version = VersionService.get_version_by_number(company, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    diff = VersionService.get_diff_with_current(version)
    
    return {
        'entity_id': str(company.id),
        'entity_type': 'company',
        'entity_name': company.name,
        'version_number': version.version_number,
        'version_date': version.created,
        'differences': diff['differences'],
        'changed_field_count': diff['changed_field_count']
    }


# Ride Model Versions

@router.get(
    '/ride-models/{model_id}/versions',
    response={200: VersionHistoryResponseSchema, 404: ErrorSchema},
    summary="Get ride model version history"
)
def get_ride_model_versions(request, model_id: UUID, limit: int = 50):
    """Get version history for a ride model."""
    model = get_object_or_404(RideModel, id=model_id)
    versions = VersionService.get_version_history(model, limit=limit)
    
    return {
        'entity_id': str(model.id),
        'entity_type': 'ride_model',
        'entity_name': str(model),
        'total_versions': VersionService.get_version_count(model),
        'versions': [
            EntityVersionSchema.from_orm(v) for v in versions
        ]
    }


@router.get(
    '/ride-models/{model_id}/versions/{version_number}',
    response={200: EntityVersionSchema, 404: ErrorSchema},
    summary="Get specific ride model version"
)
def get_ride_model_version(request, model_id: UUID, version_number: int):
    """Get a specific version of a ride model by version number."""
    model = get_object_or_404(RideModel, id=model_id)
    version = VersionService.get_version_by_number(model, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    return EntityVersionSchema.from_orm(version)


@router.get(
    '/ride-models/{model_id}/versions/{version_number}/diff',
    response={200: VersionDiffSchema, 404: ErrorSchema},
    summary="Compare ride model version with current"
)
def get_ride_model_version_diff(request, model_id: UUID, version_number: int):
    """Compare a specific version with the current ride model state."""
    model = get_object_or_404(RideModel, id=model_id)
    version = VersionService.get_version_by_number(model, version_number)
    
    if not version:
        raise Http404("Version not found")
    
    diff = VersionService.get_diff_with_current(version)
    
    return {
        'entity_id': str(model.id),
        'entity_type': 'ride_model',
        'entity_name': str(model),
        'version_number': version.version_number,
        'version_date': version.created,
        'differences': diff['differences'],
        'changed_field_count': diff['changed_field_count']
    }


# Generic Version Endpoints

@router.get(
    '/versions/{version_id}',
    response={200: EntityVersionSchema, 404: ErrorSchema},
    summary="Get version by ID"
)
def get_version(request, version_id: UUID):
    """Get a specific version by its ID."""
    version = get_object_or_404(EntityVersion, id=version_id)
    return EntityVersionSchema.from_orm(version)


@router.get(
    '/versions/{version_id}/compare/{other_version_id}',
    response={200: VersionComparisonSchema, 404: ErrorSchema},
    summary="Compare two versions"
)
def compare_versions(request, version_id: UUID, other_version_id: UUID):
    """
    Compare two versions of the same entity.
    
    Both versions must be for the same entity.
    """
    version1 = get_object_or_404(EntityVersion, id=version_id)
    version2 = get_object_or_404(EntityVersion, id=other_version_id)
    
    comparison = VersionService.compare_versions(version1, version2)
    
    return {
        'version1': EntityVersionSchema.from_orm(version1),
        'version2': EntityVersionSchema.from_orm(version2),
        'differences': comparison['differences'],
        'changed_field_count': comparison['changed_field_count']
    }


# Optional: Version Restoration
# Uncomment if you want to enable version restoration via API

# @router.post(
#     '/versions/{version_id}/restore',
#     response={200: MessageSchema, 404: ErrorSchema},
#     summary="Restore a version"
# )
# def restore_version(request, version_id: UUID):
#     """
#     Restore an entity to a previous version.
#     
#     This creates a new version with change_type='restored'.
#     Requires authentication and appropriate permissions.
#     """
#     version = get_object_or_404(EntityVersion, id=version_id)
#     
#     # Check authentication
#     if not request.user.is_authenticated:
#         return 401, {'error': 'Authentication required'}
#     
#     # Restore version
#     restored_version = VersionService.restore_version(
#         version,
#         user=request.user,
#         comment='Restored via API'
#     )
#     
#     return {
#         'message': f'Successfully restored to version {version.version_number}',
#         'new_version_number': restored_version.version_number
#     }
