"""Training Results Analysis page: Analysis of training results and model performance."""

from typing import cast

import streamlit as st

from entropice.dashboard.sections.cv_result import (
    render_confusion_matrices,
    render_cv_statistics_section,
    render_metrics_section,
    render_run_information,
)
from entropice.dashboard.sections.hparam_space import render_hparam_space_section
from entropice.dashboard.sections.regression_analysis import render_regression_analysis
from entropice.dashboard.utils.formatters import format_metric_name
from entropice.dashboard.utils.loaders import TrainingResult, load_all_training_results
from entropice.dashboard.utils.stats import CVMetricStatistics


def render_analysis_settings_sidebar(training_results: list[TrainingResult]) -> tuple[TrainingResult, str, str]:
    """Render sidebar for training run and analysis settings selection.

    Args:
        training_results: List of available TrainingResult objects.

    Returns:
        Tuple of (selected_result, selected_metric, refit_metric, top_n).

    """
    with st.sidebar.form("training_analysis_settings_form"):
        st.header("Select Training Run")

        # Create selection options with task-first naming
        training_options = {tr.display_info.get_display_name("task_first"): tr for tr in training_results}

        selected_name = st.selectbox(
            "Training Run",
            options=list(training_options.keys()),
            index=0,
            help="Select a training run to analyze",
            key="training_run_select",
        )

        selected_result = cast(TrainingResult, training_options[selected_name])

        st.divider()

        # Metric selection for detailed analysis
        st.subheader("Analysis Settings")

        available_metrics = selected_result.available_metrics

        # Try to get refit metric from settings
        if selected_result.run.task == "binary":
            refit_metric = "f1"
        elif selected_result.run.task in ["count_regimes", "density_regimes"]:
            refit_metric = "f1_weighted"
        else:
            refit_metric = "r2"

        if refit_metric in available_metrics:
            default_metric_idx = available_metrics.index(refit_metric)
        else:
            default_metric_idx = 0

        selected_metric = st.selectbox(
            "Primary Metric for Analysis",
            options=available_metrics,
            index=default_metric_idx,
            format_func=format_metric_name,
            help="Select the metric to focus on for detailed analysis",
            key="metric_select",
        )

        # Form submit button
        submitted = st.form_submit_button(
            "Load Training Result",
            type="primary",
            use_container_width=True,
        )

        if not submitted:
            st.info("👆 Click 'Load Training Result' to apply changes.")
            st.stop()

    return selected_result, selected_metric, refit_metric


def render_training_analysis_page():
    """Render the Training Results Analysis page of the dashboard."""
    st.title("🦾 Training Results Analysis")

    st.markdown(
        """
        Analyze training results, hyperparameter search performance, and model configurations.
        Select a training run from the sidebar to explore detailed metrics and parameter analysis.
        """
    )

    # Load training results
    training_results = load_all_training_results()

    if not training_results:
        st.warning("No training results found. Please run some training experiments first.")
        st.stop()
        return

    st.write(f"Found **{len(training_results)}** training result(s)")

    st.divider()
    selected_result, selected_metric, refit_metric = render_analysis_settings_sidebar(training_results)

    cv_statistics = CVMetricStatistics.compute(selected_result, selected_metric)

    render_run_information(selected_result, refit_metric)

    st.divider()

    render_metrics_section(selected_result)

    st.divider()

    # Render confusion matrices for classification, regression analysis for regression
    if selected_result.run.task in ["binary", "count_regimes", "density_regimes"]:
        render_confusion_matrices(selected_result)
    else:
        render_regression_analysis(selected_result)

    st.divider()

    if cv_statistics is not None:
        test_score = selected_result._get_best_score("test")
        render_cv_statistics_section(cv_statistics, test_score)

        st.divider()

    render_hparam_space_section(selected_result, selected_metric)

    st.divider()

    # List all results at the end
    if selected_result.run.method_type == "HPOCV":
        st.header("📄 All Cross-Validation Results")
        st.dataframe(selected_result.run.cv_results)
    elif selected_result.run.method_type == "AutoML":
        st.header("📄 Model Leaderboard")
        st.dataframe(selected_result.run.leaderboard)

    st.balloons()
