"""
競技状態管理API
サーバーAPI変更要求書20250904.mdに基づく実装

Author: システム開発チーム
Date: 2025-09-04
"""

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.db import transaction
from django.utils import timezone
from rog.models import NewEvent2, Entry, Location2025, GpsLog
from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D
import logging

logger = logging.getLogger(__name__)


@api_view(['GET'])
def competition_status(request):
    """
    競技状態取得API
    
    パラメータ:
    - event_code: イベントコード
    - zekken_number: ゼッケン番号
    
    レスポンス:
    {
      "status": "OK",
      "data": {
        "is_in_rog": true,
        "rogaining_counted": false,
        "ready_for_goal": false,
        "is_at_goal": false,
        "start_time": "2025-09-04T09:00:00+09:00",
        "goal_time": null,
        "last_checkin_time": "2025-09-04T09:30:00+09:00"
      }
    }
    """
    logger.info("competition_status API called")
    
    event_code = request.query_params.get('event_code')
    zekken_number = request.query_params.get('zekken_number')
    
    logger.debug(f"Parameters: event_code={event_code}, zekken_number={zekken_number}")
    
    # パラメータ検証
    if not event_code or not zekken_number:
        logger.warning("Missing required parameters")
        return Response({
            "status": "ERROR",
            "message": "イベントコードとゼッケン番号が必要です"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # イベントの存在確認
        event = NewEvent2.objects.filter(event_name=event_code).first()
        if not event:
            logger.warning(f"Event not found: {event_code}")
            return Response({
                "status": "ERROR",
                "message": "指定されたイベントが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # エントリーの存在確認
        entry = Entry.objects.filter(
            event=event,
            zekken_number=zekken_number
        ).first()
        
        if not entry:
            logger.warning(f"Entry not found: zekken_number={zekken_number}, event={event_code}")
            return Response({
                "status": "ERROR",
                "message": "指定されたゼッケン番号のエントリーが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # 競技状態データを返す
        data = {
            "is_in_rog": entry.is_in_rog,
            "rogaining_counted": entry.rogaining_counted,
            "ready_for_goal": entry.ready_for_goal,
            "is_at_goal": entry.is_at_goal,
            "start_time": entry.start_time.strftime("%Y-%m-%dT%H:%M:%S%z") if entry.start_time else None,
            "goal_time": entry.goal_time.strftime("%Y-%m-%dT%H:%M:%S%z") if entry.goal_time else None,
            "last_checkin_time": entry.last_checkin_time.strftime("%Y-%m-%dT%H:%M:%S%z") if entry.last_checkin_time else None
        }
        
        logger.info(f"Competition status retrieved for zekken {zekken_number} in event {event_code}")
        
        return Response({
            "status": "OK",
            "data": data
        })
    
    except Exception as e:
        logger.error(f"Error in competition_status: {str(e)}")
        return Response({
            "status": "ERROR",
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['POST'])
def update_competition_status(request):
    """
    競技状態更新API
    
    パラメータ:
    {
      "event_code": "EVENT2025",
      "zekken_number": "001",
      "is_in_rog": true,
      "rogaining_counted": false,
      "ready_for_goal": false,
      "is_at_goal": false
    }
    
    レスポンス:
    {
      "status": "OK",
      "message": "Competition status updated successfully",
      "updated_at": "2025-09-04T10:00:00+09:00"
    }
    """
    logger.info("update_competition_status API called")
    
    event_code = request.data.get('event_code')
    zekken_number = request.data.get('zekken_number')
    is_in_rog = request.data.get('is_in_rog')
    rogaining_counted = request.data.get('rogaining_counted')
    ready_for_goal = request.data.get('ready_for_goal')
    is_at_goal = request.data.get('is_at_goal')
    
    logger.debug(f"Parameters: event_code={event_code}, zekken_number={zekken_number}")
    
    # パラメータ検証
    if not event_code or not zekken_number:
        logger.warning("Missing required parameters")
        return Response({
            "status": "ERROR",
            "message": "イベントコードとゼッケン番号が必要です"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # イベントの存在確認
        event = NewEvent2.objects.filter(event_name=event_code).first()
        if not event:
            logger.warning(f"Event not found: {event_code}")
            return Response({
                "status": "ERROR",
                "message": "指定されたイベントが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # エントリーの存在確認
        entry = Entry.objects.filter(
            event=event,
            zekken_number=zekken_number
        ).first()
        
        if not entry:
            logger.warning(f"Entry not found: zekken_number={zekken_number}, event={event_code}")
            return Response({
                "status": "ERROR",
                "message": "指定されたゼッケン番号のエントリーが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # トランザクション内で状態更新
        with transaction.atomic():
            # 状態の更新（Noneでない値のみ更新）
            if is_in_rog is not None:
                entry.is_in_rog = is_in_rog
            if rogaining_counted is not None:
                entry.rogaining_counted = rogaining_counted
            if ready_for_goal is not None:
                entry.ready_for_goal = ready_for_goal
            if is_at_goal is not None:
                entry.is_at_goal = is_at_goal
            
            entry.save()
            
            update_time = timezone.now()
            
            logger.info(f"Competition status updated for zekken {zekken_number} in event {event_code}")
            
            return Response({
                "status": "OK",
                "message": "Competition status updated successfully",
                "updated_at": update_time.strftime("%Y-%m-%dT%H:%M:%S%z")
            })
    
    except Exception as e:
        logger.error(f"Error in update_competition_status: {str(e)}")
        return Response({
            "status": "ERROR",
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
def checkpoint_status(request):
    """
    チェックポイント状態取得API
    
    パラメータ:
    - event_code: イベントコード
    - zekken_number: ゼッケン番号
    - cp_number: チェックポイント番号
    
    レスポンス:
    {
      "status": "OK",
      "data": {
        "cp_number": -2,
        "is_checked_in": true,
        "checkin_time": "2025-09-04T09:00:00+09:00",
        "status": "競技中",  // "未", "競技中", "競技終了"
        "points_earned": 0
      }
    }
    """
    logger.info("checkpoint_status API called")
    
    event_code = request.query_params.get('event_code')
    zekken_number = request.query_params.get('zekken_number')
    cp_number = request.query_params.get('cp_number')
    
    logger.debug(f"Parameters: event_code={event_code}, zekken_number={zekken_number}, cp_number={cp_number}")
    
    # パラメータ検証
    if not all([event_code, zekken_number, cp_number]):
        logger.warning("Missing required parameters")
        return Response({
            "status": "ERROR",
            "message": "イベントコード、ゼッケン番号、チェックポイント番号が必要です"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # イベントの存在確認
        event = NewEvent2.objects.filter(event_name=event_code).first()
        if not event:
            logger.warning(f"Event not found: {event_code}")
            return Response({
                "status": "ERROR",
                "message": "指定されたイベントが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # エントリーの存在確認
        entry = Entry.objects.filter(
            event=event,
            zekken_number=zekken_number
        ).first()
        
        if not entry:
            logger.warning(f"Entry not found: zekken_number={zekken_number}, event={event_code}")
            return Response({
                "status": "ERROR",
                "message": "指定されたゼッケン番号のエントリーが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # チェックイン状況の確認
        checkin_record = GpsLog.objects.filter(
            zekken_number=zekken_number,
            event_code=event_code,
            cp_number=cp_number
        ).first()
        
        # チェックポイント情報の取得
        checkpoint = Location2025.objects.filter(
            event=event,
            cp_number=cp_number
        ).first()
        
        # 競技状況の判定
        competition_status = "未"
        if entry.is_at_goal:
            competition_status = "競技終了"
        elif entry.is_in_rog:
            competition_status = "競技中"
        
        # レスポンスデータ構築
        data = {
            "cp_number": int(cp_number),
            "is_checked_in": bool(checkin_record),
            "checkin_time": checkin_record.checkin_time.strftime("%Y-%m-%dT%H:%M:%S%z") if checkin_record else None,
            "status": competition_status,
            "points_earned": checkpoint.point if checkpoint else 0
        }
        
        logger.info(f"Checkpoint status retrieved for CP {cp_number}, zekken {zekken_number} in event {event_code}")
        
        return Response({
            "status": "OK",
            "data": data
        })
    
    except Exception as e:
        logger.error(f"Error in checkpoint_status: {str(e)}")
        return Response({
            "status": "ERROR",
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
