import pandas as pd
from algorithms.location import haversine_nm, bd09_to_wgs84, compute_bd09_offset  # noqa: F401

MAX_FISHING_SPEED_KNOTS = 25.0


def detect_teleportation(df_vessel: pd.DataFrame,
                         max_speed_knots: float = MAX_FISHING_SPEED_KNOTS) -> list[dict]:
    """연속 AIS 포인트 간 물리적 불가능 이동 탐지."""
    if len(df_vessel) < 2:
        return []

    anomalies = []
    records = df_vessel.sort_values('timestamp').to_dict('records')

    for i in range(1, len(records)):
        prev, curr = records[i - 1], records[i]
        dist_nm = haversine_nm(prev['lat'], prev['lon'], curr['lat'], curr['lon'])
        dt_hours = (
            pd.Timestamp(curr['timestamp']) - pd.Timestamp(prev['timestamp'])
        ).total_seconds() / 3600

        if dt_hours <= 0:
            continue

        implied_speed = dist_nm / dt_hours

        if implied_speed > max_speed_knots:
            anomalies.append({
                'idx': i,
                'dist_nm': round(dist_nm, 2),
                'implied_kn': round(implied_speed, 1),
                'type': 'TELEPORTATION',
                'confidence': 'HIGH' if implied_speed > 50 else 'MED',
            })

    return anomalies


def count_speed_jumps(df_vessel: pd.DataFrame, threshold_knots: float = 10.0) -> int:
    """연속 SOG 급변 횟수."""
    if len(df_vessel) < 2:
        return 0

    sog = df_vessel['sog'].values
    jumps = 0
    for i in range(1, len(sog)):
        if abs(sog[i] - sog[i - 1]) > threshold_knots:
            jumps += 1
    return jumps


def compute_spoofing_score(df_vessel: pd.DataFrame) -> float:
    """종합 GPS 스푸핑 점수 (0~1)."""
    if len(df_vessel) < 2:
        return 0.0

    score = 0.0
    n = len(df_vessel)

    # 순간이동 비율
    teleports = detect_teleportation(df_vessel)
    if teleports:
        score += min(0.4, len(teleports) / n * 10)

    # SOG 급변 비율
    jumps = count_speed_jumps(df_vessel)
    if jumps > 0:
        score += min(0.3, jumps / n * 5)

    # BD09 오프셋 (중국 좌표 사용 의심)
    mid_idx = len(df_vessel) // 2
    row = df_vessel.iloc[mid_idx]
    offset = compute_bd09_offset(row['lat'], row['lon'])
    if offset > 300:  # 300m 이상
        score += 0.3
    elif offset > 100:
        score += 0.1

    return round(min(score, 1.0), 4)
