"""
KML Schedule Generation System.

Generates Google Earth compatible KML files showing scientific operations only.
Creates geospatial visualizations of cruise activities for geographic analysis
and planning. Only includes scientific operations (stations, moorings, surveys)
in the KML output, excluding navigation transits.

Notes
-----
KML files can be opened directly in Google Earth or other GIS applications.
Each operation type is styled differently for visual distinction. Point features
include detailed metadata in popups.
"""

import logging
from pathlib import Path
from typing import List

from cruiseplan.calculators.scheduler import ActivityRecord
from cruiseplan.core.validation import CruiseConfig
from cruiseplan.utils.activity_utils import is_line_operation, is_scientific_operation

logger = logging.getLogger(__name__)


class KMLGenerator:
    """
    Manages KML generation for cruise schedules showing only scientific operations.

    This class generates Google Earth compatible KML files containing geospatial
    representations of scientific cruise activities. Only scientific operations
    are included, with different styling for each operation type.
    """

    def __init__(self):
        """Initialize the KML generator."""
        pass

    def generate_schedule_kml(
        self, config: CruiseConfig, timeline: List[ActivityRecord], output_file: Path
    ) -> Path:
        """
        Generate KML schedule output with only scientific operations.

        Parameters
        ----------
        config : CruiseConfig
            The cruise configuration object
        timeline : List[ActivityRecord]
            Timeline generated by the scheduler
        output_file : Path
            Path to output KML file

        Returns
        -------
        Path
            Path to generated KML file
        """
        # Define KML styles for different operation types
        kml_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
    <Document>
        <name>{config.cruise_name} - Schedule</name>
        <description>{config.description or 'Cruise schedule'}</description>
        
        <!-- Styles for different operation types -->
        <Style id="stationStyle">
            <IconStyle>
                <color>ff0000ff</color>
                <scale>1.2</scale>
                <Icon>
                    <href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png</href>
                </Icon>
            </IconStyle>
        </Style>
        
        <Style id="mooringStyle">
            <IconStyle>
                <color>ff00ff00</color>
                <scale>1.2</scale>
                <Icon>
                    <href>http://maps.google.com/mapfiles/kml/shapes/placemark_square.png</href>
                </Icon>
            </IconStyle>
        </Style>
        
        <Style id="lineOpStyle">
            <LineStyle>
                <color>ffff0000</color>
                <width>3</width>
            </LineStyle>
        </Style>
        
        <Style id="areaStyle">
            <LineStyle>
                <color>ff00ffff</color>
                <width>2</width>
            </LineStyle>
            <PolyStyle>
                <color>4000ffff</color>
                <fill>1</fill>
            </PolyStyle>
        </Style>
"""

        # Filter timeline to only include scientific operations
        scientific_activities = [
            activity for activity in timeline if is_scientific_operation(activity)
        ]

        for activity in scientific_activities:
            if is_line_operation(activity):
                # Line operation - create line with label at midpoint
                start_lat = activity["start_lat"]
                start_lon = activity["start_lon"]
                end_lat = activity["lat"]
                end_lon = activity["lon"]

                # Calculate midpoint for label
                mid_lat = (start_lat + end_lat) / 2
                mid_lon = (start_lon + end_lon) / 2

                action_str = activity.get("action", "Survey")

                kml_content += f"""
        <Placemark>
            <name>{activity['label']} - {action_str}</name>
            <description>
                Activity: {activity['activity']} ({action_str})
                Start: {activity['start_time'].strftime('%Y-%m-%d %H:%M')}
                Duration: {activity['duration_minutes']:.1f} min
                Operation Distance: {activity.get('operation_dist_nm', 0):.1f} nm
            </description>
            <styleUrl>#lineOpStyle</styleUrl>
            <LineString>
                <coordinates>
                    {start_lon},{start_lat},0
                    {end_lon},{end_lat},0
                </coordinates>
            </LineString>
        </Placemark>
        
        <Placemark>
            <name>{activity['label']}</name>
            <description>Midpoint label for {action_str} operation</description>
            <Point>
                <coordinates>{mid_lon},{mid_lat},0</coordinates>
            </Point>
        </Placemark>
"""
            elif activity["activity"] == "Area":
                # Area operation - create polygon with corners
                corners = activity.get("corners", [])
                if corners and len(corners) >= 3:
                    # Create coordinate list for polygon (close the polygon by repeating first point)
                    coord_list = []
                    for corner in corners:
                        coord_list.append(
                            f"{corner['longitude']},{corner['latitude']},0"
                        )
                    # Close the polygon
                    if len(corners) > 0:
                        coord_list.append(
                            f"{corners[0]['longitude']},{corners[0]['latitude']},0"
                        )

                    coordinates_str = " ".join(coord_list)
                    action_str = activity.get("action", "Survey")

                    kml_content += f"""
        <Placemark>
            <name>{activity['label']} - {action_str}</name>
            <description>
                Activity: {activity['activity']} ({action_str})
                Start: {activity['start_time'].strftime('%Y-%m-%d %H:%M')}
                Duration: {activity['duration_minutes']:.1f} min
                Area: {len(corners)} corners
            </description>
            <styleUrl>#areaStyle</styleUrl>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>{coordinates_str}</coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>
        </Placemark>
"""
                else:
                    # Fallback to center point if no corners defined
                    kml_content += f"""
        <Placemark>
            <name>{activity['label']}</name>
            <description>
                Activity: {activity['activity']} (Area - no corners defined)
                Start: {activity['start_time'].strftime('%Y-%m-%d %H:%M')}
                Duration: {activity['duration_minutes']:.1f} min
            </description>
            <styleUrl>#stationStyle</styleUrl>
            <Point>
                <coordinates>{activity['lon']},{activity['lat']},0</coordinates>
            </Point>
        </Placemark>
"""
            else:
                # Point operation - Station or Mooring
                style_id = (
                    "stationStyle"
                    if activity["activity"] == "Station"
                    else "mooringStyle"
                )
                depth_str = (
                    f"Depth: {activity.get('depth', 0):.1f} m"
                    if activity.get("depth")
                    else ""
                )

                kml_content += f"""
        <Placemark>
            <name>{activity['label']}</name>
            <description>
                Activity: {activity['activity']}
                Start: {activity['start_time'].strftime('%Y-%m-%d %H:%M')}
                Duration: {activity['duration_minutes']:.1f} min
                {depth_str}
            </description>
            <styleUrl>#{style_id}</styleUrl>
            <Point>
                <coordinates>{activity['lon']},{activity['lat']},0</coordinates>
            </Point>
        </Placemark>
"""

        kml_content += """
    </Document>
</kml>
"""

        # Write to file
        output_file.parent.mkdir(parents=True, exist_ok=True)
        with open(output_file, "w", encoding="utf-8") as f:
            f.write(kml_content)

        logger.info(
            f"KML schedule saved to: {output_file} ({len(scientific_activities)} scientific operations)"
        )
        return output_file


def generate_kml_schedule(
    config: CruiseConfig, timeline: List[ActivityRecord], output_file: Path
) -> Path:
    """
    Main interface to generate KML schedule from scheduler timeline.

    Parameters
    ----------
    config : CruiseConfig
        The cruise configuration object
    timeline : List[ActivityRecord]
        Timeline generated by the scheduler
    output_file : Path
        Path to output KML file

    Returns
    -------
    Path
        Path to generated KML file
    """
    generator = KMLGenerator()
    return generator.generate_schedule_kml(config, timeline, output_file)
