# 既存のインポート部分に追加
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rog.models import NewEvent2, Entry, Location, GpsLog
import logging
from django.db.models import F, Q
from django.conf import settings
import os
from urllib.parse import urljoin

logger = logging.getLogger(__name__)

"""
解説
この実装では以下の処理を行っています：

1.ウェイポイントデータを保存するためのモデル Waypoint を定義
2.POST リクエストからチーム名、イベントコード、ウェイポイントデータ配列を取得
3.データのバリデーションを行う
    - 必要なパラメータが全て揃っているか
    - ウェイポイントデータが配列形式か
    - 各ウェイポイントに必要な情報（緯度、経度、記録時間）が含まれているか
4.イベントとチームの存在確認
5.各ウェイポイントを処理
    - 数値型・日時型の変換
    - 重複チェック（同じ記録時間のデータは無視）
    - データベースに保存
6.処理結果の統計（保存数、スキップ数、無効データ数）を含む応答を返す

この実装により、アプリからチームの位置情報を送信し、サーバーで保存することができます。
保存されたデータは、後でルート表示や分析などに使用できます。
"""

@api_view(['POST'])
def get_waypoint_datas_from_rogapp(request):
    """
    アプリからウェイポイントデータを受信し保存
    
    パラメータ:
    - team_name: チーム名
    - event_code: イベントコード
    - waypoints: ウェイポイントデータの配列
    """
    logger.info("get_waypoint_datas_from_rogapp called")
    
    # リクエストからパラメータを取得
    try:
        data = request.data
        team_name = data.get('team_name')
        event_code = data.get('event_code')
        waypoints_data = data.get('waypoints')
        
        # JSONとして送信された場合はデコード
        if isinstance(waypoints_data, str):
            try:
                waypoints_data = json.loads(waypoints_data)
            except json.JSONDecodeError:
                logger.warning("Invalid JSON format for waypoints")
                return Response({
                    "status": "ERROR", 
                    "message": "ウェイポイントデータのJSONフォーマットが無効です"
                }, status=status.HTTP_400_BAD_REQUEST)
        
        logger.debug(f"Parameters: team_name={team_name}, event_code={event_code}, "
                   f"waypoints_count={len(waypoints_data) if waypoints_data else 0}")
    except Exception as e:
        logger.warning(f"Error parsing request data: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "リクエストデータの解析に失敗しました"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    # パラメータ検証
    if not all([team_name, event_code, waypoints_data]):
        logger.warning("Missing required parameters")
        return Response({
            "status": "ERROR", 
            "message": "チーム名、イベントコード、ウェイポイントデータが必要です"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    # ウェイポイントデータの検証
    if not isinstance(waypoints_data, list):
        logger.warning("Waypoints data is not a list")
        return Response({
            "status": "ERROR", 
            "message": "ウェイポイントデータはリスト形式である必要があります"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    if len(waypoints_data) == 0:
        logger.warning("Empty waypoints list")
        return Response({
            "status": "WARNING", 
            "message": "ウェイポイントリストが空です",
            "saved_count": 0
        })
    
    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, 
            team_name=team_name
        ).first()
        
        if not entry:
            logger.warning(f"Team '{team_name}' not found in event: {event_code}")
            return Response({
                "status": "ERROR", 
                "message": "指定されたチーム名のエントリーが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # チームがスタートしているか確認（オプション）
        if not hasattr(entry, 'start_info'):
            logger.warning(f"Team {team_name} has not started yet")
            # 必要に応じてエラーを返すか、自動的にスタート処理を行う
        
        # トランザクション開始
        saved_count = 0
        skipped_count = 0
        invalid_count = 0
        
        with transaction.atomic():
            for waypoint in waypoints_data:
                try:
                    # 必須フィールドの検証
                    lat = waypoint.get('latitude')
                    lng = waypoint.get('longitude')
                    recorded_at_str = waypoint.get('recorded_at')
                    
                    if not all([lat, lng, recorded_at_str]):
                        logger.warning(f"Missing required fields in waypoint: {waypoint}")
                        invalid_count += 1
                        continue
                    
                    # 数値型の検証
                    try:
                        lat = float(lat)
                        lng = float(lng)
                    except (ValueError, TypeError):
                        logger.warning(f"Invalid coordinate values: lat={lat}, lng={lng}")
                        invalid_count += 1
                        continue
                    
                    # 日時の解析
                    try:
                        # 複数の日付形式に対応
                        recorded_at = None
                        for date_format in [
                            "%Y-%m-%dT%H:%M:%S.%fZ",  # ISO形式（ミリ秒付き）
                            "%Y-%m-%dT%H:%M:%SZ",      # ISO形式
                            "%Y-%m-%d %H:%M:%S",       # 標準形式
                            "%Y/%m/%d %H:%M:%S"        # スラッシュ区切り
                        ]:
                            try:
                                if recorded_at_str.endswith('Z'):
                                    # UTCからローカルタイムに変換する必要がある場合
                                    dt = datetime.strptime(recorded_at_str, date_format)
                                    # ここでUTCからローカルタイムへの変換を行う場合
                                    recorded_at = dt
                                else:
                                    recorded_at = datetime.strptime(recorded_at_str, date_format)
                                break
                            except ValueError:
                                continue
                        
                        if recorded_at is None:
                            raise ValueError(f"No matching date format for: {recorded_at_str}")
                    except ValueError as e:
                        logger.warning(f"Invalid date format: {recorded_at_str} - {str(e)}")
                        invalid_count += 1
                        continue
                    
                    # 重複チェック（同じ記録時間のウェイポイントは無視）
                    if Waypoint.objects.filter(
                        entry=entry,
                        recorded_at=recorded_at
                    ).exists():
                        logger.debug(f"Skipping duplicate waypoint at: {recorded_at_str}")
                        skipped_count += 1
                        continue
                    
                    # オプションフィールドの取得
                    altitude = waypoint.get('altitude')
                    accuracy = waypoint.get('accuracy')
                    speed = waypoint.get('speed')
                    
                    # ウェイポイントの保存
                    Waypoint.objects.create(
                        entry=entry,
                        latitude=lat,
                        longitude=lng,
                        altitude=float(altitude) if altitude not in [None, ''] else None,
                        accuracy=float(accuracy) if accuracy not in [None, ''] else None,
                        speed=float(speed) if speed not in [None, ''] else None,
                        recorded_at=recorded_at
                    )
                    
                    saved_count += 1
                
                except Exception as e:
                    logger.error(f"Error processing waypoint: {str(e)}")
                    invalid_count += 1
            
            logger.info(f"Processed waypoints for team {team_name}: "
                       f"saved={saved_count}, skipped={skipped_count}, invalid={invalid_count}")
            
            return Response({
                "status": "OK", 
                "message": "ウェイポイントデータを正常に保存しました",
                "team_name": team_name,
                "event_code": event_code,
                "total_waypoints": len(waypoints_data),
                "saved_count": saved_count,
                "skipped_count": skipped_count,
                "invalid_count": invalid_count
            })
    
    except Exception as e:
        logger.error(f"Error in get_waypoint_datas_from_rogapp: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

"""
解説
この実装では以下の処理を行っています：

1.チーム名とイベントコードのパラメータを受け取ります
2.パラメータが不足している場合はエラーを返します
3.指定されたイベントとチームの存在を確認します
4.チームの移動経路データを取得します：
    - ウェイポイントデータ（記録時間順）
    - チェックポイント通過情報（時間順）
    - スタート情報とゴール情報
5.移動経路の統計情報を計算します：
    - 総移動距離
    - ウェイポイント数
    - チェックポイント数
6.GeoJSON形式のルートデータを作成します
7.全てのデータを含む応答を返します

実装のポイント：

- ウェイポイントとチェックポイントの両方をルートポイントとして統合
- チェックポイントの座標はLocationモデルから取得（存在する場合）
- ハバーサイン公式を使用して2点間の距離を計算し、総移動距離を算出
- GeoJSON形式のデータも含め、様々な用途に対応できる形式でデータを提供

このエンドポイントにより、チームの移動経路を視覚化したり分析したりすることができます。
"""

@api_view(['GET'])
def get_route(request):
    """
    指定チームのルート情報を取得
    
    パラメータ:
    - team: チーム名
    - event_code: イベントコード
    """
    logger.info("get_route called")
    
    # リクエストからパラメータを取得
    team_name = request.query_params.get('team')
    event_code = request.query_params.get('event_code')
    
    logger.debug(f"Parameters: team={team_name}, event_code={event_code}")
    
    # パラメータ検証
    if not all([team_name, event_code]):
        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, 
            team_name=team_name
        ).first()
        
        if not entry:
            logger.warning(f"Team '{team_name}' not found in event: {event_code}")
            return Response({
                "status": "ERROR", 
                "message": "指定されたチームが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # ウェイポイントデータを取得（時間順）
        waypoints = Waypoint.objects.filter(
            entry=entry
        ).order_by('recorded_at')
        
        # チェックポイント通過情報を取得（時間順）
        checkpoints = GpsLog.objects.filter(
            entry=entry
        ).order_by('checkin_time')
        
        # スタート情報を取得
        start_info = None
        if hasattr(entry, 'start_info'):
            start_info = {
                "start_time": entry.start_info.start_time.strftime("%Y-%m-%d %H:%M:%S")
            }
        
        # ゴール情報を取得
        goal_info = None
        if hasattr(entry, 'goal_info'):
            goal_info = {
                "goal_time": entry.goal_info.goal_time.strftime("%Y-%m-%d %H:%M:%S"),
                "score": entry.goal_info.score
            }
        
        # ウェイポイントを処理
        route_points = []
        for wp in waypoints:
            point = {
                "latitude": wp.latitude,
                "longitude": wp.longitude,
                "timestamp": wp.recorded_at.strftime("%Y-%m-%d %H:%M:%S"),
                "type": "waypoint"
            }
            
            # オプションフィールドがあれば追加
            if wp.altitude is not None:
                point["altitude"] = wp.altitude
            if wp.accuracy is not None:
                point["accuracy"] = wp.accuracy
            if wp.speed is not None:
                point["speed"] = wp.speed
                
            route_points.append(point)
        
        # チェックポイントの座標を追加（イベントのチェックポイント定義がある場合）
        checkpoint_data = []
        for cp in checkpoints:
            cp_data = {
                "cp_number": cp.cp_number,
                "checkin_time": cp.checkin_time.strftime("%Y-%m-%d %H:%M:%S") if cp.checkin_time else None,
                "image_url": cp.image_address,
                "is_service_checked": getattr(cp, 'is_service_checked', False)
            }
            
            # チェックポイントの座標情報を取得（Locationモデルがある場合）
            try:
                event_cp = Location.objects.filter(
                    event=event, 
                    cp_number=cp.cp_number
                ).first()
                
                if event_cp and event_cp.latitude and event_cp.longitude:
                    cp_data["latitude"] = event_cp.latitude
                    cp_data["longitude"] = event_cp.longitude
                    cp_data["cp_name"] = event_cp.cp_name
                    cp_data["cp_point"] = event_cp.cp_point
                    cp_data["is_service_cp"] = event_cp.is_service_cp
                    
                    # ルートポイントとしても追加
                    route_points.append({
                        "latitude": event_cp.latitude,
                        "longitude": event_cp.longitude,
                        "timestamp": cp.checkin_time.strftime("%Y-%m-%d %H:%M:%S") if cp.checkin_time else None,
                        "type": "checkpoint",
                        "cp_number": cp.cp_number,
                        "cp_name": event_cp.cp_name
                    })
            except:
                # Locationモデルが存在しないか、座標が設定されていない場合
                pass
                
            checkpoint_data.append(cp_data)
        
        # ルートの統計情報を計算
        total_distance = 0
        if len(route_points) >= 2:
            from math import sin, cos, sqrt, atan2, radians
            
            def calculate_distance(lat1, lon1, lat2, lon2):
                # 2点間の距離をハバーサイン公式で計算（km単位）
                R = 6371.0  # 地球の半径（km）
                
                lat1_rad = radians(lat1)
                lon1_rad = radians(lon1)
                lat2_rad = radians(lat2)
                lon2_rad = radians(lon2)
                
                dlon = lon2_rad - lon1_rad
                dlat = lat2_rad - lat1_rad
                
                a = sin(dlat / 2)**2 + cos(lat1_rad) * cos(lat2_rad) * sin(dlon / 2)**2
                c = 2 * atan2(sqrt(a), sqrt(1 - a))
                
                distance = R * c
                return distance
            
            for i in range(len(route_points) - 1):
                p1 = route_points[i]
                p2 = route_points[i + 1]
                
                if 'latitude' in p1 and 'longitude' in p1 and 'latitude' in p2 and 'longitude' in p2:
                    distance = calculate_distance(
                        p1['latitude'], p1['longitude'],
                        p2['latitude'], p2['longitude']
                    )
                    total_distance += distance
        
        # GeoJSON形式のルートデータを作成（オプション）
        geo_json = {
            "type": "FeatureCollection",
            "features": [
                {
                    "type": "Feature",
                    "geometry": {
                        "type": "LineString",
                        "coordinates": [
                            [point["longitude"], point["latitude"]] 
                            for point in route_points 
                            if "latitude" in point and "longitude" in point
                        ]
                    },
                    "properties": {
                        "team_name": team_name,
                        "total_distance": round(total_distance, 2),  # km単位で小数点以下2桁まで
                        "waypoint_count": waypoints.count(),
                        "checkpoint_count": checkpoints.count()
                    }
                }
            ]
        }
        
        return Response({
            "status": "OK",
            "team_info": {
                "team_name": team_name,
                "zekken_number": entry.zekken_number,
                "class_name": entry.class_name,
                "event_code": event_code
            },
            "start_info": start_info,
            "goal_info": goal_info,
            "route_statistics": {
                "total_distance": round(total_distance, 2),  # km単位
                "total_waypoints": waypoints.count(),
                "total_checkpoints": checkpoints.count()
            },
            "checkpoints": checkpoint_data,
            "route_points": route_points,
            "geo_json": geo_json
        })
    
    except Exception as e:
        logger.error(f"Error in get_route: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

"""
解説
この実装では以下の処理を行っています：

1.ゼッケン番号とイベントコードのパラメータを受け取ります
2.オプションで limit（返す位置情報の最大数）と time_range（時間範囲）のパラメータも受け取ります
3.パラメータが不足している場合はエラーを返します
4.指定されたイベントとチームの存在を確認します
5.チームのウェイポイントデータを取得します：
    - 新しい順（降順）にソート
    - 時間範囲でフィルタリング（指定された場合）
    - 件数制限（指定された場合）
6.チームの基本情報、最新の位置情報、位置情報履歴を含む応答を作成します
7.GeoJSON形式のデータも提供します：
    - 移動経路を表す LineString フィーチャー
    - 各位置を表す Point フィーチャー

この実装は /getRoute エンドポイントに似ていますが、以下の点で異なります：

- 位置情報の取得に焦点を当てています（チェックポイント情報は含まれません）
- より新しいデータを優先的に返します（降順ソート）
- 時間範囲や件数制限のオプションがあります
- 移動経路の統計情報（距離など）は計算しません
- このエンドポイントは、リアルタイムマップ表示やチームの動きを追跡する場合に便利です。
"""

# 既存のインポート部分に追加
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rog.models import NewEvent2, Entry, Waypoint
import logging
from django.db.models import F, Q
from datetime import datetime, timedelta

logger = logging.getLogger(__name__)

@api_view(['GET'])
def fetch_user_locations(request):
    """
    ユーザーの位置情報履歴を取得
    
    パラメータ:
    - zekken_number: ゼッケン番号
    - event_code: イベントコード
    """
    logger.info("fetch_user_locations called")
    
    # リクエストからパラメータを取得
    zekken_number = request.query_params.get('zekken_number')
    event_code = request.query_params.get('event_code')
    
    # 追加のオプションパラメータ
    limit = request.query_params.get('limit')
    if limit:
        try:
            limit = int(limit)
        except ValueError:
            limit = None
    
    time_range = request.query_params.get('time_range')  # 例: "1h", "30m", "2d"
    
    logger.debug(f"Parameters: zekken_number={zekken_number}, event_code={event_code}, "
                f"limit={limit}, time_range={time_range}")
    
    # パラメータ検証
    if not all([zekken_number, event_code]):
        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"Team with zekken number {zekken_number} not found in event: {event_code}")
            return Response({
                "status": "ERROR", 
                "message": "指定されたゼッケン番号のチームが見つかりません"
            }, status=status.HTTP_404_NOT_FOUND)
        
        # ウェイポイントデータをフィルタリング
        waypoints_query = Waypoint.objects.filter(entry=entry)
        
        # 時間範囲でフィルタリング（オプション）
        if time_range:
            # 時間範囲をパース (例: "1h", "30m", "2d")
            time_value = ""
            time_unit = ""
            for char in time_range:
                if char.isdigit():
                    time_value += char
                else:
                    time_unit += char
            
            if time_value and time_unit:
                time_value = int(time_value)
                now = datetime.now()
                
                if time_unit.lower() == 'h':
                    start_time = now - timedelta(hours=time_value)
                elif time_unit.lower() == 'm':
                    start_time = now - timedelta(minutes=time_value)
                elif time_unit.lower() == 'd':
                    start_time = now - timedelta(days=time_value)
                else:
                    # デフォルトは1時間
                    start_time = now - timedelta(hours=1)
                
                waypoints_query = waypoints_query.filter(recorded_at__gte=start_time)
        
        # 時間順にソート
        waypoints_query = waypoints_query.order_by('-recorded_at')
        
        # 件数制限（オプション）
        if limit:
            waypoints_query = waypoints_query[:limit]
        
        # データの取得
        waypoints = list(waypoints_query)
        
        # チームのスタート・ゴール情報
        start_time = None
        if hasattr(entry, 'start_info'):
            start_time = entry.start_info.start_time
        
        goal_time = None
        if hasattr(entry, 'goal_info'):
            goal_time = entry.goal_info.goal_time
        
        # レスポンスデータの構築
        location_data = []
        
        for wp in waypoints:
            location = {
                "latitude": wp.latitude,
                "longitude": wp.longitude,
                "timestamp": wp.recorded_at.strftime("%Y-%m-%d %H:%M:%S"),
            }
            
            # オプションフィールドがあれば追加
            if wp.altitude is not None:
                location["altitude"] = wp.altitude
            if wp.accuracy is not None:
                location["accuracy"] = wp.accuracy
            if wp.speed is not None:
                location["speed"] = wp.speed
            
            location_data.append(location)
        
        # 最後の位置情報
        latest_location = None
        if location_data:
            latest_location = location_data[0]  # すでに新しい順にソート済み
        
        # GeoJSON形式のデータも作成
        geo_json = {
            "type": "FeatureCollection",
            "features": [
                {
                    "type": "Feature",
                    "geometry": {
                        "type": "LineString",
                        "coordinates": [
                            [point["longitude"], point["latitude"]] 
                            for point in reversed(location_data)  # 時系列順に並べ直す
                        ]
                    },
                    "properties": {
                        "team_name": entry.team_name,
                        "zekken_number": zekken_number,
                        "point_count": len(location_data)
                    }
                }
            ]
        }
        
        # ポイントを個別のフィーチャーとしても追加
        for point in location_data:
            geo_json["features"].append({
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [point["longitude"], point["latitude"]]
                },
                "properties": {
                    "timestamp": point["timestamp"],
                    "speed": point.get("speed"),
                    "altitude": point.get("altitude")
                }
            })
        
        return Response({
            "status": "OK",
            "team_info": {
                "team_name": entry.team_name,
                "zekken_number": zekken_number,
                "class_name": entry.class_name,
                "event_code": event_code,
                "start_time": start_time.strftime("%Y-%m-%d %H:%M:%S") if start_time else None,
                "goal_time": goal_time.strftime("%Y-%m-%d %H:%M:%S") if goal_time else None
            },
            "latest_location": latest_location,
            "locations": location_data,
            "total_locations": len(location_data),
            "geo_json": geo_json
        })
    
    except Exception as e:
        logger.error(f"Error in fetch_user_locations: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


"""
解説
この実装では以下の処理を行っています：

1.イベントコードとオプションでクラス名のパラメータを受け取ります
2.パラメータが不足している場合はエラーを返します
3.指定されたイベントの存在を確認します
4.イベント内のチームをクエリします：
    - スタート情報があるチームのみを対象
    - クラス名が指定された場合はそのクラスに所属するチームのみに限定
5.各チームについて以下の情報を取得します：
    - チームの基本情報（名前、ゼッケン番号、クラス）
    - スタート情報とゴール情報
    - ウェイポイントとチェックポイントのデータ
    - ルートの統計情報（総距離、ウェイポイント数、チェックポイント数）
6.全チームの情報と、GeoJSON形式のデータを含む応答を返します

実装のポイント：

- レスポンスサイズを抑えるため、各チームのルートポイント詳細は含めず、統計情報のみを提供
- GeoJSON形式のデータでは、各チームのルートを1つのフィーチャーとして表現
- 各チームのデータ処理中にエラーが発生した場合でも、他のチームの処理は継続する例外処理
- オプションでクラス名によるフィルタリングが可能

このエンドポイントは、管理画面での全チームの一覧表示や、全チームのルートを1つの地図上に表示したい場合に役立ちます。
"""

@api_view(['GET'])
def get_all_routes(request):
    """
    指定イベントの全チームのルート情報を取得
    
    パラメータ:
    - event_code: イベントコード
    - class_name: クラス名（省略可）
    """
    logger.info("get_all_routes called")
    
    # リクエストからパラメータを取得
    event_code = request.query_params.get('event_code')
    class_name = request.query_params.get('class_name')
    
    # クエリパラメータの別名対応（互換性のため）
    if not event_code:
        event_code = request.query_params.get('event')
    
    logger.debug(f"Parameters: event_code={event_code}, class_name={class_name}")
    
    # パラメータ検証
    if not event_code:
        logger.warning("Missing required event_code parameter")
        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)
        
        # 対象チームのクエリ作成（クラス名でフィルタリング）
        entries_query = Entry.objects.filter(event=event)
        if class_name:
            entries_query = entries_query.filter(class_name=class_name)
        
        # スタート情報があるチームだけ対象にする
        entries_with_start = entries_query.filter(start_info__isnull=False)
        
        if not entries_with_start.exists():
            logger.warning(f"No teams with start info found for event: {event_code}")
            return Response({
                "status": "WARNING", 
                "message": "スタート済みのチームが見つかりません",
                "teams": [],
                "total_teams": 0
            })
        
        # 全チームの情報とルートを取得
        teams_data = []
        geo_json_features = []
        
        for entry in entries_with_start:
            try:
                # ウェイポイントデータを取得（時間順）
                waypoints = Waypoint.objects.filter(
                    entry=entry
                ).order_by('recorded_at')
                
                # チェックポイント通過情報を取得（時間順）
                checkpoints = GpsLog.objects.filter(
                    entry=entry
                ).order_by('checkin_time')
                
                # スタート情報を取得
                start_info = None
                if hasattr(entry, 'start_info'):
                    start_info = {
                        "start_time": entry.start_info.start_time.strftime("%Y-%m-%d %H:%M:%S")
                    }
                
                # ゴール情報を取得
                goal_info = None
                if hasattr(entry, 'goal_info'):
                    goal_info = {
                        "goal_time": entry.goal_info.goal_time.strftime("%Y-%m-%d %H:%M:%S"),
                        "score": entry.goal_info.score
                    }
                
                # ウェイポイントとチェックポイントを処理
                route_points = []
                
                # ウェイポイントを処理
                for wp in waypoints:
                    point = {
                        "latitude": wp.latitude,
                        "longitude": wp.longitude,
                        "timestamp": wp.recorded_at.strftime("%Y-%m-%d %H:%M:%S"),
                        "type": "waypoint"
                    }
                    
                    if wp.altitude is not None:
                        point["altitude"] = wp.altitude
                    if wp.accuracy is not None:
                        point["accuracy"] = wp.accuracy
                    if wp.speed is not None:
                        point["speed"] = wp.speed
                        
                    route_points.append(point)
                
                # チェックポイントの座標を追加（イベントのチェックポイント定義がある場合）
                checkpoint_data = []
                for cp in checkpoints:
                    cp_data = {
                        "cp_number": cp.cp_number,
                        "checkin_time": cp.checkin_time.strftime("%Y-%m-%d %H:%M:%S") if cp.checkin_time else None,
                        "is_service_checked": getattr(cp, 'is_service_checked', False)
                    }
                    
                    # チェックポイントの座標情報を取得
                    try:
                        event_cp = Location.objects.filter(
                            event=event, 
                            cp_number=cp.cp_number
                        ).first()
                        
                        if event_cp and event_cp.latitude and event_cp.longitude:
                            cp_data["latitude"] = event_cp.latitude
                            cp_data["longitude"] = event_cp.longitude
                            cp_data["cp_name"] = event_cp.cp_name
                            cp_data["cp_point"] = event_cp.cp_point
                            
                            # ルートポイントとしても追加
                            route_points.append({
                                "latitude": event_cp.latitude,
                                "longitude": event_cp.longitude,
                                "timestamp": cp.checkin_time.strftime("%Y-%m-%d %H:%M:%S") if cp.checkin_time else None,
                                "type": "checkpoint",
                                "cp_number": cp.cp_number
                            })
                    except:
                        # Locationモデルが存在しないか、座標が設定されていない場合
                        pass
                        
                    checkpoint_data.append(cp_data)
                
                # ルートの統計情報を計算
                total_distance = 0
                if len(route_points) >= 2:
                    def calculate_distance(lat1, lon1, lat2, lon2):
                        # 2点間の距離をハバーサイン公式で計算（km単位）
                        R = 6371.0  # 地球の半径（km）
                        
                        lat1_rad = radians(lat1)
                        lon1_rad = radians(lon1)
                        lat2_rad = radians(lat2)
                        lon2_rad = radians(lon2)
                        
                        dlon = lon2_rad - lon1_rad
                        dlat = lat2_rad - lat1_rad
                        
                        a = sin(dlat / 2)**2 + cos(lat1_rad) * cos(lat2_rad) * sin(dlon / 2)**2
                        c = 2 * atan2(sqrt(a), sqrt(1 - a))
                        
                        distance = R * c
                        return distance
                    
                    for i in range(len(route_points) - 1):
                        p1 = route_points[i]
                        p2 = route_points[i + 1]
                        
                        if 'latitude' in p1 and 'longitude' in p1 and 'latitude' in p2 and 'longitude' in p2:
                            distance = calculate_distance(
                                p1['latitude'], p1['longitude'],
                                p2['latitude'], p2['longitude']
                            )
                            total_distance += distance
                
                # チームデータを追加
                team_data = {
                    "team_name": entry.team_name,
                    "zekken_number": entry.zekken_number,
                    "class_name": entry.class_name,
                    "start_info": start_info,
                    "goal_info": goal_info,
                    "route_statistics": {
                        "total_distance": round(total_distance, 2),
                        "total_waypoints": waypoints.count(),
                        "total_checkpoints": checkpoints.count()
                    },
                    "checkpoints": checkpoint_data,
                    # ルートポイントは量が多いため、必要に応じて個別ルート取得APIを使用する形に
                    "route_points_count": len(route_points)
                }
                
                teams_data.append(team_data)
                
                # GeoJSONフィーチャーを追加
                if route_points:
                    geo_json_features.append({
                        "type": "Feature",
                        "geometry": {
                            "type": "LineString",
                            "coordinates": [
                                [point["longitude"], point["latitude"]] 
                                for point in route_points 
                                if "latitude" in point and "longitude" in point
                            ]
                        },
                        "properties": {
                            "team_name": entry.team_name,
                            "zekken_number": entry.zekken_number,
                            "class_name": entry.class_name,
                            "total_distance": round(total_distance, 2),
                            "waypoint_count": waypoints.count(),
                            "checkpoint_count": checkpoints.count(),
                            "score": goal_info["score"] if goal_info else None
                        }
                    })
            
            except Exception as e:
                logger.error(f"Error processing route for team {entry.team_name}: {str(e)}")
                # エラーが発生したチームはスキップ
                continue
        
        # GeoJSON形式のデータを作成
        geo_json = {
            "type": "FeatureCollection",
            "features": geo_json_features
        }
        
        return Response({
            "status": "OK",
            "event_code": event_code,
            "class_name": class_name,
            "total_teams": len(teams_data),
            "teams": teams_data,
            "geo_json": geo_json
        })
    
    except Exception as e:
        logger.error(f"Error in get_all_routes: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    