"""Experiment Results Section for the Entropice Dashboard."""

from datetime import datetime

import streamlit as st

from entropice.dashboard.utils.loaders import TrainingResult
from entropice.utils.types import (
    GridConfig,
)


def render_training_results_summary(training_results: list[TrainingResult]):
    """Render summary metrics for training results."""
    st.header("📊 Training Results Summary")
    col1, col2, col3, col4 = st.columns(4)

    with col1:
        experiments = {tr.experiment for tr in training_results if tr.experiment}
        st.metric("Experiments", len(experiments))

    with col2:
        st.metric("Total Runs", len(training_results))

    with col3:
        models = {tr.run.model_type for tr in training_results}
        st.metric("Model Types", len(models))

    with col4:
        latest = training_results[0]  # Already sorted by creation time
        latest_datetime = datetime.fromtimestamp(latest.created_at).strftime("%Y-%m-%d %H:%M")
        st.metric("Latest Run", latest_datetime)


@st.fragment
def render_experiment_results(training_results: list[TrainingResult]):  # noqa: C901
    """Render detailed experiment results table and expandable details."""
    st.header("🎯 Experiment Results")

    # Filters
    experiments = sorted({tr.experiment for tr in training_results if tr.experiment})
    tasks = sorted({tr.run.task for tr in training_results})
    models = sorted({tr.run.model_type for tr in training_results})
    grids = sorted({f"{tr.run.dataset.grid}-{tr.run.dataset.level}" for tr in training_results})

    # Create filter columns
    filter_cols = st.columns(4)

    with filter_cols[0]:
        if experiments:
            selected_experiment = st.selectbox(
                "Experiment",
                options=["All", *experiments],
                index=0,
                key="exp_results_experiment",
            )
        else:
            selected_experiment = "All"

    with filter_cols[1]:
        selected_task = st.selectbox(
            "Task",
            options=["All", *tasks],
            index=0,
            key="exp_results_task",
        )

    with filter_cols[2]:
        selected_model = st.selectbox(
            "Model",
            options=["All", *models],
            index=0,
            key="exp_results_model",
        )

    with filter_cols[3]:
        selected_grid = st.selectbox(
            "Grid",
            options=["All", *grids],
            index=0,
            key="exp_results_grid",
        )

    # Apply filters
    filtered_results: list[TrainingResult] = training_results
    if selected_experiment != "All":
        filtered_results = [tr for tr in filtered_results if tr.experiment == selected_experiment]
    if selected_task != "All":
        filtered_results = [tr for tr in filtered_results if tr.run.task == selected_task]
    if selected_model != "All":
        filtered_results = [tr for tr in filtered_results if tr.run.model_type == selected_model]
    if selected_grid != "All":
        filtered_results = [
            tr for tr in filtered_results if f"{tr.run.dataset.grid}-{tr.run.dataset.level}" == selected_grid
        ]

    st.subheader("Results Table")

    summary_df = TrainingResult.to_dataframe(filtered_results)

    # Display with color coding for best scores
    st.dataframe(
        summary_df,
        width="stretch",
        hide_index=True,
    )

    # Expandable details for each result
    with st.expander("Show Individual Experiment Details", expanded=False):
        for tr in filtered_results:
            tr_info = tr.display_info
            display_name = tr_info.get_display_name("model_first")
            model = tr.run.model_type
            with st.expander(display_name):
                col1, col2 = st.columns([1, 2])

                with col1:
                    grid_config = GridConfig.from_grid_level((tr.run.dataset.grid, tr.run.dataset.level))
                    st.write(
                        "**Configuration:**\n"
                        f"- **Experiment:** {tr.experiment}\n"
                        f"- **Task:** {tr.run.task}\n"
                        f"- **Target:** {tr.run.target}\n"
                        f"- **Model:** {model}\n"
                        f"- **Grid:** {grid_config.display_name}\n"
                        f"- **Created At:** {tr_info.timestamp.strftime('%Y-%m-%d %H:%M')}\n"
                        f"- **Temporal Mode:** {tr.run.dataset.temporal_mode}\n"
                        f"- **Members:** {', '.join(tr.run.dataset.members)}\n"
                    )

                    file_str = "\n**Files:**\n"
                    for file in tr.files:
                        if file.name == "search_settings.toml":
                            file_str += f"- ⚙️ `{file.name}`\n"
                        elif file.name == "best_estimator_model.pkl":
                            file_str += f"- 🧮 `{file.name}`\n"
                        elif file.name == "search_results.parquet":
                            file_str += f"- 📊 `{file.name}`\n"
                        elif file.name == "predicted_probabilities.parquet":
                            file_str += f"- 🎯 `{file.name}`\n"
                        else:
                            file_str += f"- 📄 `{file.name}`\n"
                    st.write(file_str)
                with col2:
                    if tr.run.method_type == "AutoML":
                        st.write("**Leaderboard:**")
                        st.dataframe(tr.run.leaderboard, width="stretch", hide_index=True)
                    else:
                        st.write("**CV Score Summary:**")
                        # Extract all test scores
                        metric_df = tr.get_cv_results_dataframe()
                        if metric_df is not None:
                            st.dataframe(metric_df, width="stretch", hide_index=True)
                        else:
                            st.write("No test scores found in results.")

                        cv_results = tr.run.cv_results
                        assert cv_results is not None, "CV results should not be None for non-AutoML runs"

                        # Show parameter space explored
                        if "initial_K" in cv_results.columns:  # Common parameter
                            st.write("\n**Parameter Ranges Explored:**")
                            for param in ["initial_K", "eps_cl", "eps_e"]:
                                if param in cv_results.columns:
                                    min_val = cv_results[param].min()
                                    max_val = cv_results[param].max()
                                    unique_vals = cv_results[param].nunique()
                                    st.write(f"- **{param}:** {unique_vals} values ({min_val:.2e} to {max_val:.2e})")

                        st.write("**CV Results DataFrame:**")
                        st.dataframe(cv_results, width="stretch", hide_index=True)

                st.write(f"\n**Path:** `{tr.path}`")
