# 既存のインポート部分に追加
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rog.models import NewEvent2, Entry, Location2025, 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__)

"""
get_start_point()

解説:

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

1.イベントコードのパラメータを受け取ります
2.パラメータが不足している場合はエラーを返します
3.指定されたイベントの存在を確認します
4. イベントのスタートポイント情報を取得します：
    - 緯度・経度
    - スタート地点の名前
    - スタート地点の説明
5.GeoJSON形式のデータも提供します（座標情報がある場合）
    - スタート地点をPointとして表現
    - プロパティとして名前や説明も含む

このエンドポイントは、アプリでイベントのスタート地点を地図上に表示したり、
スタート地点の詳細情報を表示したりするために使用できます。
これにより、参加者はどこに集合すればよいかを正確に把握できます。
"""

@api_view(['GET'])
def get_start_point(request):
    """
    イベントのスタートポイント情報を取得
    
    パラメータ:
    - event: イベントコード
    """
    logger.info("get_start_point called")
    
    # リクエストからパラメータを取得
    event_code = request.query_params.get('event')
    
    logger.debug(f"Parameters: event={event_code}")
    
    # パラメータ検証
    if not event_code:
        logger.warning("Missing required event 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)
        
        # スタートポイント情報の取得
        start_point = {
            "event_code": event_code,
            "event_name": event.event_name
        }
        
        # 座標情報があれば追加
        if event.start_latitude is not None and event.start_longitude is not None:
            start_point["latitude"] = event.start_latitude
            start_point["longitude"] = event.start_longitude
        
        # 名前や説明があれば追加
        if hasattr(event, 'start_name') and event.start_name:
            start_point["name"] = event.start_name
        
        if hasattr(event, 'start_description') and event.start_description:
            start_point["description"] = event.start_description
        
        # GeoJSON形式のデータも作成
        geo_json = None
        if event.start_latitude is not None and event.start_longitude is not None:
            geo_json = {
                "type": "FeatureCollection",
                "features": [
                    {
                        "type": "Feature",
                        "geometry": {
                            "type": "Point",
                            "coordinates": [event.start_longitude, event.start_latitude]
                        },
                        "properties": {
                            "name": event.start_name if hasattr(event, 'start_name') else "スタート地点",
                            "description": event.start_description if hasattr(event, 'start_description') else "",
                            "event_code": event_code
                        }
                    }
                ]
            }
        
        return Response({
            "status": "OK",
            "start_point": start_point,
            "geo_json": geo_json
        })
    
    except Exception as e:
        logger.error(f"Error in get_start_point: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


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

1.緯度、経度、チーム名、イベントコードのパラメータを受け取ります
2.パラメータが不足している場合はエラーを返します
3.指定されたイベントとチームの存在を確認します
4.チームのウェイポイントデータを取得し、指定された座標からの距離を計算します
5.最も近いウェイポイントを特定し、以下の情報を含む分析結果を作成します：
    - 最近接ポイントの詳細（位置、時間、標高、精度、速度など）
    - 速度分析（前後のポイントから計算した速度と移動タイプの推測）
    - 周辺ポイント（時間的・空間的に近いウェイポイント）
    - 最も近いチェックポイントとの関係（オプション）

実装のポイント：

- ハバーサイン公式を使用して、2点間の地理的距離を正確に計算
- 速度から移動タイプを推測（静止、歩行、ジョギング、ランニングなど）
- チェックポイントとの近接性分析も行い、チームが通過済みかどうかも確認
- 周辺ポイントも提供することで、より広い範囲での動きを把握可能

このエンドポイントは、特定地点での移動状況を詳細に分析したい場合に役立ちます。
例えば、チームの移動戦略の分析や、特定地点でのパフォーマンス評価などに使用できます。


"""

@api_view(['GET'])
def analyze_point(request):
    """
    指定地点の情報を分析（速度、移動タイプなど）
    
    パラメータ:
    - lat: 緯度
    - lng: 経度
    - team_name: チーム名
    - event_code: イベントコード
    """
    logger.info("analyze_point called")
    
    # リクエストからパラメータを取得
    latitude = request.query_params.get('lat')
    longitude = request.query_params.get('lng')
    team_name = request.query_params.get('team_name')
    event_code = request.query_params.get('event_code')
    
    logger.debug(f"Parameters: lat={latitude}, lng={longitude}, team_name={team_name}, event_code={event_code}")
    
    # パラメータ検証
    if not all([latitude, longitude, team_name, event_code]):
        logger.warning("Missing required parameters")
        return Response({
            "status": "ERROR", 
            "message": "緯度、経度、チーム名、イベントコードが全て必要です"
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # 数値型に変換
        try:
            lat = float(latitude)
            lng = float(longitude)
        except ValueError:
            logger.warning(f"Invalid coordinate values: lat={latitude}, lng={longitude}")
            return Response({
                "status": "ERROR", 
                "message": "緯度と経度は数値である必要があります"
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # イベントの存在確認
        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)
        
        # 最も近い位置にあるウェイポイントを見つける
        # 指定座標からの距離を計算するヘルパー関数
        def calculate_distance(waypoint):
            wp_lat = waypoint.latitude
            wp_lng = waypoint.longitude
            
            # ハバーサイン公式で距離を計算
            R = 6371.0  # 地球の半径（km）
            
            lat1_rad = radians(lat)
            lon1_rad = radians(lng)
            lat2_rad = radians(wp_lat)
            lon2_rad = radians(wp_lng)
            
            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 * 1000  # メートル単位に変換
            return distance
        
        # チームの全ウェイポイントを取得
        all_waypoints = Waypoint.objects.filter(entry=entry).order_by('recorded_at')
        
        if not all_waypoints.exists():
            logger.warning(f"No waypoints found for team {team_name}")
            return Response({
                "status": "WARNING", 
                "message": "このチームのウェイポイントデータがありません",
                "team_name": team_name,
                "event_code": event_code,
                "latitude": lat,
                "longitude": lng
            })
        
        # 各ウェイポイントについて指定座標からの距離を計算
        waypoints_with_distance = [(wp, calculate_distance(wp)) for wp in all_waypoints]
        
        # 距離でソート
        waypoints_with_distance.sort(key=lambda x: x[1])
        
        # 最も近いウェイポイント
        nearest_waypoint, nearest_distance = waypoints_with_distance[0]
        
        # 分析結果
        analysis = {
            "nearest_point": {
                "latitude": nearest_waypoint.latitude,
                "longitude": nearest_waypoint.longitude,
                "timestamp": nearest_waypoint.recorded_at.strftime("%Y-%m-%d %H:%M:%S"),
                "distance": round(nearest_distance, 2),  # メートル単位
                "altitude": nearest_waypoint.altitude,
                "accuracy": nearest_waypoint.accuracy,
                "speed": nearest_waypoint.speed
            }
        }
        
        # 前後のウェイポイントを取得して速度分析
        waypoint_index = list(all_waypoints).index(nearest_waypoint)
        
        # 前のウェイポイント（あれば）
        if waypoint_index > 0:
            prev_waypoint = all_waypoints[waypoint_index - 1]
            time_diff = (nearest_waypoint.recorded_at - prev_waypoint.recorded_at).total_seconds()
            
            if time_diff > 0:
                # 2点間の距離を計算
                prev_distance = calculate_distance(prev_waypoint)
                
                # 速度を計算（m/s）
                speed_mps = abs(nearest_distance - prev_distance) / time_diff
                
                analysis["speed_analysis"] = {
                    "speed_mps": round(speed_mps, 2),
                    "speed_kmh": round(speed_mps * 3.6, 2),  # km/h に変換
                    "time_diff_seconds": time_diff
                }
                
                # 移動タイプを推測
                if speed_mps < 1.5:
                    mobility_type = "静止またはゆっくり歩行"
                elif speed_mps < 2.5:
                    mobility_type = "歩行"
                elif speed_mps < 4.0:
                    mobility_type = "速歩き"
                elif speed_mps < 7.0:
                    mobility_type = "ジョギング"
                elif speed_mps < 12.0:
                    mobility_type = "ランニング"
                else:
                    mobility_type = "自転車または車両"
                
                analysis["speed_analysis"]["mobility_type"] = mobility_type
        
        # 周辺の他のウェイポイントも取得（時間範囲内で）
        # 前後30分以内のウェイポイントを検索
        time_range = timedelta(minutes=30)
        nearby_waypoints = []
        
        for wp in all_waypoints:
            if abs((wp.recorded_at - nearest_waypoint.recorded_at).total_seconds()) <= time_range.total_seconds():
                # 距離も近いものだけ（1km以内）
                distance = calculate_distance(wp)
                if distance <= 1000:
                    nearby_waypoints.append({
                        "latitude": wp.latitude,
                        "longitude": wp.longitude,
                        "timestamp": wp.recorded_at.strftime("%Y-%m-%d %H:%M:%S"),
                        "distance": round(distance, 2),
                        "altitude": wp.altitude,
                        "speed": wp.speed
                    })
        
        analysis["nearby_points"] = nearby_waypoints
        analysis["nearby_points_count"] = len(nearby_waypoints)
        
        # チェックポイントとの関係を分析（オプション）
        try:
            
            # イベントのチェックポイント定義を取得
            event_cps = Location2025.objects.filter(event=event)
            
            # チームが通過したチェックポイントを取得
            team_cps = GpsLog.objects.filter(entry=entry)
            
            if event_cps.exists():
                # 指定地点から最も近いチェックポイントを見つける
                closest_cp = None
                closest_cp_distance = float('inf')
                
                for cp in event_cps:
                    if cp.latitude is not None and cp.longitude is not None:
                        # チェックポイントからの距離を計算
                        cp_lat = cp.latitude
                        cp_lng = cp.longitude
                        
                        R = 6371.0
                        lat1_rad = radians(lat)
                        lon1_rad = radians(lng)
                        lat2_rad = radians(cp_lat)
                        lon2_rad = radians(cp_lng)
                        
                        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 * 1000  # メートル単位
                        
                        if distance < closest_cp_distance:
                            closest_cp = cp
                            closest_cp_distance = distance
                
                if closest_cp:
                    # チームがこのチェックポイントを通過したかを確認
                    team_cp = team_cps.filter(cp_number=closest_cp.cp_number).first()
                    visited = team_cp is not None
                    
                    analysis["nearest_checkpoint"] = {
                        "cp_number": closest_cp.cp_number,
                        "cp_name": closest_cp.cp_name,
                        "cp_point": closest_cp.cp_point,
                        "distance": round(closest_cp_distance, 2),
                        "visited": visited,
                        "checkin_time": team_cp.checkin_time.strftime("%Y-%m-%d %H:%M:%S") if visited and team_cp.checkin_time else None
                    }
        except:
            # Location モデルがない場合などはスキップ
            pass
        
        return Response({
            "status": "OK",
            "team_name": team_name,
            "event_code": event_code,
            "latitude": lat,
            "longitude": lng,
            "analysis": analysis
        })
    
    except Exception as e:
        logger.error(f"Error in analyze_point: {str(e)}")
        return Response({
            "status": "ERROR", 
            "message": "サーバーエラーが発生しました"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

