"""Choropleth map figure factory for Toronto housing data."""

from typing import Any

import plotly.express as px
import plotly.graph_objects as go


def create_choropleth_figure(
    geojson: dict[str, Any] | None,
    data: list[dict[str, Any]],
    location_key: str,
    color_column: str,
    hover_data: list[str] | None = None,
    color_scale: str = "Blues",
    title: str | None = None,
    map_style: str = "carto-positron",
    center: dict[str, float] | None = None,
    zoom: float = 9.5,
) -> go.Figure:
    """Create a choropleth map figure.

    Args:
        geojson: GeoJSON FeatureCollection for boundaries.
        data: List of data records with location keys and values.
        location_key: Column name for location identifier.
        color_column: Column name for color values.
        hover_data: Additional columns to show on hover.
        color_scale: Plotly color scale name.
        title: Optional chart title.
        map_style: Mapbox style (carto-positron, open-street-map, etc.).
        center: Map center coordinates {"lat": float, "lon": float}.
        zoom: Initial zoom level.

    Returns:
        Plotly Figure object.
    """
    # Default center to Toronto
    if center is None:
        center = {"lat": 43.7, "lon": -79.4}

    # If no geojson provided, create a placeholder map
    if geojson is None or not data:
        fig = go.Figure(go.Scattermapbox())
        fig.update_layout(
            mapbox={
                "style": map_style,
                "center": center,
                "zoom": zoom,
            },
            margin={"l": 0, "r": 0, "t": 40, "b": 0},
            title=title or "Toronto Housing Map",
            height=500,
        )
        fig.add_annotation(
            text="No geometry data available. Complete QGIS digitization to enable map.",
            xref="paper",
            yref="paper",
            x=0.5,
            y=0.5,
            showarrow=False,
            font={"size": 14, "color": "gray"},
        )
        return fig

    # Create choropleth with data
    import pandas as pd

    df = pd.DataFrame(data)

    fig = px.choropleth_mapbox(
        df,
        geojson=geojson,
        locations=location_key,
        featureidkey=f"properties.{location_key}",
        color=color_column,
        color_continuous_scale=color_scale,
        hover_data=hover_data,
        mapbox_style=map_style,
        center=center,
        zoom=zoom,
        opacity=0.7,
    )

    fig.update_layout(
        margin={"l": 0, "r": 0, "t": 40, "b": 0},
        title=title,
        height=500,
        coloraxis_colorbar={
            "title": color_column.replace("_", " ").title(),
            "thickness": 15,
            "len": 0.7,
        },
    )

    return fig


def create_district_map(
    districts_geojson: dict[str, Any] | None,
    purchase_data: list[dict[str, Any]],
    metric: str = "avg_price",
) -> go.Figure:
    """Create choropleth map for TRREB districts.

    Args:
        districts_geojson: GeoJSON for TRREB district boundaries.
        purchase_data: Purchase statistics by district.
        metric: Metric to display (avg_price, sales_count, etc.).

    Returns:
        Plotly Figure object.
    """
    hover_columns = ["district_name", "sales_count", "avg_price", "median_price"]

    return create_choropleth_figure(
        geojson=districts_geojson,
        data=purchase_data,
        location_key="district_code",
        color_column=metric,
        hover_data=[c for c in hover_columns if c != metric],
        color_scale="Blues" if "price" in metric else "Greens",
        title="Toronto Purchase Market by District",
    )


def create_zone_map(
    zones_geojson: dict[str, Any] | None,
    rental_data: list[dict[str, Any]],
    metric: str = "avg_rent",
) -> go.Figure:
    """Create choropleth map for CMHC zones.

    Args:
        zones_geojson: GeoJSON for CMHC zone boundaries.
        rental_data: Rental statistics by zone.
        metric: Metric to display (avg_rent, vacancy_rate, etc.).

    Returns:
        Plotly Figure object.
    """
    hover_columns = ["zone_name", "avg_rent", "vacancy_rate", "rental_universe"]

    return create_choropleth_figure(
        geojson=zones_geojson,
        data=rental_data,
        location_key="zone_code",
        color_column=metric,
        hover_data=[c for c in hover_columns if c != metric],
        color_scale="Oranges" if "rent" in metric else "Purples",
        title="Toronto Rental Market by Zone",
    )
