"""Space-Track TLE Collector

Collects satellite TLE (Two-Line Element) data from Space-Track.org.
API documentation: https://www.space-track.org/documentation
"""

import json
from typing import Dict, Any, List
import httpx

from app.services.collectors.base import BaseCollector
from app.core.data_sources import get_data_sources_config


class SpaceTrackTLECollector(BaseCollector):
    name = "spacetrack_tle"
    priority = "P2"
    module = "L3"
    frequency_hours = 24
    data_type = "satellite_tle"

    @property
    def base_url(self) -> str:
        config = get_data_sources_config()
        if self._resolved_url:
            return self._resolved_url
        return config.get_yaml_url("spacetrack_tle")

    async def fetch(self) -> List[Dict[str, Any]]:
        from app.core.config import settings

        username = settings.SPACETRACK_USERNAME
        password = settings.SPACETRACK_PASSWORD

        if not username or not password:
            print("SPACETRACK: No credentials configured, using sample data")
            return self._get_sample_data()

        print(f"SPACETRACK: Attempting to fetch TLE data with username: {username}")

        try:
            async with httpx.AsyncClient(
                timeout=120.0,
                follow_redirects=True,
                headers={
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
                    "Accept": "application/json, text/html, */*",
                    "Accept-Language": "en-US,en;q=0.9",
                    "Referer": "https://www.space-track.org/",
                },
            ) as client:
                await client.get("https://www.space-track.org/")

                login_response = await client.post(
                    "https://www.space-track.org/ajaxauth/login",
                    data={
                        "identity": username,
                        "password": password,
                    },
                )
                print(f"SPACETRACK: Login response status: {login_response.status_code}")
                print(f"SPACETRACK: Login response URL: {login_response.url}")

                if login_response.status_code == 403:
                    print("SPACETRACK: Trying alternate login method...")

                    async with httpx.AsyncClient(
                        timeout=120.0,
                        follow_redirects=True,
                    ) as alt_client:
                        await alt_client.get("https://www.space-track.org/")

                        form_data = {
                            "username": username,
                            "password": password,
                            "query": "class/gp/NORAD_CAT_ID/25544/format/json",
                        }
                        alt_login = await alt_client.post(
                            "https://www.space-track.org/ajaxauth/login",
                            data={
                                "identity": username,
                                "password": password,
                            },
                        )
                        print(f"SPACETRACK: Alt login status: {alt_login.status_code}")

                        if alt_login.status_code == 200:
                            tle_response = await alt_client.get(
                                "https://www.space-track.org/basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json"
                            )
                            if tle_response.status_code == 200:
                                data = tle_response.json()
                                print(f"SPACETRACK: Received {len(data)} records via alt method")
                                return data

                if login_response.status_code != 200:
                    print(f"SPACETRACK: Login failed, using sample data")
                    return self._get_sample_data()

                tle_response = await client.get(
                    "https://www.space-track.org/basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json"
                )
                print(f"SPACETRACK: TLE query status: {tle_response.status_code}")

                if tle_response.status_code != 200:
                    print(f"SPACETRACK: Query failed, using sample data")
                    return self._get_sample_data()

                data = tle_response.json()
                print(f"SPACETRACK: Received {len(data)} records")
                return data
        except Exception as e:
            print(f"SPACETRACK: Error - {e}, using sample data")
            return self._get_sample_data()

        print(f"SPACETRACK: Attempting to fetch TLE data with username: {username}")

        try:
            async with httpx.AsyncClient(
                timeout=120.0,
                follow_redirects=True,
                headers={
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
                    "Accept": "application/json, text/html, */*",
                    "Accept-Language": "en-US,en;q=0.9",
                },
            ) as client:
                # First, visit the main page to get any cookies
                await client.get("https://www.space-track.org/")

                # Login to get session cookie
                login_response = await client.post(
                    "https://www.space-track.org/ajaxauth/login",
                    data={
                        "identity": username,
                        "password": password,
                    },
                )
                print(f"SPACETRACK: Login response status: {login_response.status_code}")
                print(f"SPACETRACK: Login response URL: {login_response.url}")
                print(f"SPACETRACK: Login response body: {login_response.text[:500]}")

                if login_response.status_code != 200:
                    print(f"SPACETRACK: Login failed, using sample data")
                    return self._get_sample_data()

                # Query for TLE data (get first 1000 satellites)
                tle_response = await client.get(
                    "https://www.space-track.org/basicspacedata/query"
                    "/class/gp"
                    "/orderby/EPOCH%20desc"
                    "/limit/1000"
                    "/format/json"
                )
                print(f"SPACETRACK: TLE query status: {tle_response.status_code}")

                if tle_response.status_code != 200:
                    print(f"SPACETRACK: Query failed, using sample data")
                    return self._get_sample_data()

                data = tle_response.json()
                print(f"SPACETRACK: Received {len(data)} records")
                return data
        except Exception as e:
            print(f"SPACETRACK: Error - {e}, using sample data")
            return self._get_sample_data()

    def transform(self, raw_data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """Transform TLE data to internal format"""
        transformed = []
        for item in raw_data:
            transformed.append(
                {
                    "name": item.get("OBJECT_NAME", "Unknown"),
                    "norad_cat_id": item.get("NORAD_CAT_ID"),
                    "international_designator": item.get("INTL_DESIGNATOR"),
                    "epoch": item.get("EPOCH"),
                    "mean_motion": item.get("MEAN_MOTION"),
                    "eccentricity": item.get("ECCENTRICITY"),
                    "inclination": item.get("INCLINATION"),
                    "raan": item.get("RAAN"),
                    "arg_of_perigee": item.get("ARG_OF_PERIGEE"),
                    "mean_anomaly": item.get("MEAN_ANOMALY"),
                    "ephemeris_type": item.get("EPHEMERIS_TYPE"),
                    "classification_type": item.get("CLASSIFICATION_TYPE"),
                    "element_set_no": item.get("ELEMENT_SET_NO"),
                    "rev_at_epoch": item.get("REV_AT_EPOCH"),
                    "bstar": item.get("BSTAR"),
                    "mean_motion_dot": item.get("MEAN_MOTION_DOT"),
                    "mean_motion_ddot": item.get("MEAN_MOTION_DDOT"),
                }
            )
        return transformed

    def _get_sample_data(self) -> List[Dict[str, Any]]:
        """Return sample TLE data for testing"""
        return [
            {
                "name": "ISS (ZARYA)",
                "norad_cat_id": 25544,
                "international_designator": "1998-067A",
                "epoch": "2026-03-13T00:00:00Z",
                "mean_motion": 15.49872723,
                "eccentricity": 0.0006292,
                "inclination": 51.6400,
                "raan": 315.0000,
                "arg_of_perigee": 100.0000,
                "mean_anomaly": 260.0000,
            },
            {
                "name": "STARLINK-1000",
                "norad_cat_id": 44720,
                "international_designator": "2019-029AZ",
                "epoch": "2026-03-13T00:00:00Z",
                "mean_motion": 15.79234567,
                "eccentricity": 0.0001234,
                "inclination": 53.0000,
                "raan": 120.0000,
                "arg_of_perigee": 90.0000,
                "mean_anomaly": 270.0000,
            },
        ]
