"""Asset 4: Transform pixel coordinates to real-world 2D coordinates"""

import sys
import numpy as np
from pathlib import Path
from typing import Dict, List
from dagster import asset, AssetExecutionContext

# Add src to path to import existing calibrator
sys.path.insert(0, str(Path(__file__).parent.parent.parent))


@asset(
    io_manager_key="json_io_manager",
    compute_kind="transform",
    description="Transform pixel coordinates to real-world 2D court coordinates using homography"
)
def compute_2d_coordinates(
    context: AssetExecutionContext,
    detect_court_keypoints: Dict,
    detect_ball_positions: List[Dict],
    extract_video_frames: Dict
) -> List[Dict]:
    """
    Transform ball pixel coordinates to real-world court coordinates

    Inputs:
        - detect_court_keypoints: court corners in pixels
        - detect_ball_positions: ball detections in pixels
        - extract_video_frames: video metadata (FPS)

    Outputs:
        - data/compute_2d_coordinates.json

    Returns:
        List of dicts with:
            - frame: frame number
            - timestamp: time in seconds
            - pixel_x, pixel_y: pixel coordinates
            - x_m, y_m: real-world coordinates in meters
            - confidence: detection confidence
    """
    from src.court_calibrator import CourtCalibrator

    context.log.info("Initializing court calibrator...")

    calibrator = CourtCalibrator(
        court_width_m=detect_court_keypoints['court_width_m'],
        court_length_m=detect_court_keypoints['court_length_m']
    )

    # Calibrate using detected corners
    corners = detect_court_keypoints['corners_pixel']
    context.log.info(f"Calibrating with corners: {corners}")

    success = calibrator.calibrate_manual(corners)

    if not success:
        raise RuntimeError("Court calibration failed. Check corner points.")

    context.log.info("✓ Court calibration successful")

    # Transform all ball positions
    fps = extract_video_frames['fps']
    trajectory = []

    detected_count = 0
    for detection in detect_ball_positions:
        frame_num = detection['frame']
        timestamp = frame_num / fps

        if detection['x'] is not None and detection['y'] is not None:
            # Transform pixel → meters
            pixel_coords = [detection['x'], detection['y']]
            real_coords = calibrator.pixel_to_real(pixel_coords)

            if real_coords is not None:
                trajectory.append({
                    "frame": frame_num,
                    "timestamp": round(timestamp, 3),
                    "pixel_x": round(detection['x'], 2),
                    "pixel_y": round(detection['y'], 2),
                    "x_m": round(float(real_coords[0]), 3),
                    "y_m": round(float(real_coords[1]), 3),
                    "confidence": round(detection['confidence'], 3)
                })
                detected_count += 1
            else:
                # Transformation failed (point outside court?)
                trajectory.append({
                    "frame": frame_num,
                    "timestamp": round(timestamp, 3),
                    "pixel_x": round(detection['x'], 2),
                    "pixel_y": round(detection['y'], 2),
                    "x_m": None,
                    "y_m": None,
                    "confidence": round(detection['confidence'], 3)
                })
        else:
            # No detection
            trajectory.append({
                "frame": frame_num,
                "timestamp": round(timestamp, 3),
                "pixel_x": None,
                "pixel_y": None,
                "x_m": None,
                "y_m": None,
                "confidence": 0.0
            })

        # Log progress
        if (frame_num + 1) % 20 == 0:
            context.log.info(f"Transformed {frame_num + 1}/{len(detect_ball_positions)} positions")

    transform_rate = detected_count / len(detect_ball_positions) * 100
    context.log.info(f"✓ Transformed {detected_count}/{len(detect_ball_positions)} positions ({transform_rate:.1f}%)")

    # Calculate statistics
    valid_positions = [t for t in trajectory if t['x_m'] is not None]

    if valid_positions:
        x_coords = [t['x_m'] for t in valid_positions]
        y_coords = [t['y_m'] for t in valid_positions]

        context.log.info(f"Position statistics:")
        context.log.info(f"  X range: {min(x_coords):.2f}m to {max(x_coords):.2f}m")
        context.log.info(f"  Y range: {min(y_coords):.2f}m to {max(y_coords):.2f}m")
        context.log.info(f"  Court dimensions: {calibrator.court_length}m x {calibrator.court_width}m")

    return trajectory
