"""
Metrics API.
Chuẩn POST: Accuracy, Precision, Recall, F1-Score, Confusion Matrix (bắt buộc).
Dùng kwslib.standards.metrics.build_metrics_payload hoặc metrics_from_sklearn để tạo payload.
"""

from typing import Optional, Dict, Any, List, Union
from .base import BaseAPI


class MetricsAPI(BaseAPI):
    """Metrics endpoints (bảng mlflow.metrics). Chuẩn: accuracy, precision, recall, f1_score, confusion_matrix."""

    def list(
        self,
        model_id: Optional[int] = None,
        dataset_split_id: Optional[int] = None,
        page: int = 1,
        page_size: int = 20,
    ) -> Dict[str, Any]:
        """List metrics. Filter: model_id, dataset_split_id."""
        params = {"page": page, "page_size": min(page_size, 100)}
        if model_id is not None:
            params["model_id"] = model_id
        if dataset_split_id is not None:
            params["dataset_split_id"] = dataset_split_id
        return self.client._request("GET", "metrics/", params=params)

    def get(self, metric_id: int) -> Dict[str, Any]:
        """Get metric by ID"""
        return self.client._request("GET", f"metrics/{metric_id}")

    def create(
        self,
        model_id: int,
        dataset_split_id: int,
        experiment_run_id: int,
        accuracy: float,
        precision: float,
        recall: float,
        f1_score: float,
        confusion_matrix: Optional[Union[List[List[int]], Dict[str, Any]]] = None,
        auc_macro: Optional[float] = None,
        auc_micro: Optional[float] = None,
        ap_macro: Optional[float] = None,
        ap_micro: Optional[float] = None,
        roc_curve: Optional[Dict[str, Any]] = None,
        pr_curve: Optional[Dict[str, Any]] = None,
        *,
        payload: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """
        Create metric (POST /api/v1/metrics).
        Chuẩn bắt buộc: accuracy, precision, recall, f1_score, confusion_matrix (2D list int).

        Có thể gửi toàn bộ payload từ build_metrics_payload hoặc metrics_from_sklearn:
            client.metrics.create(payload=payload)
        """
        if payload is not None:
            return self.client._request("POST", "metrics/", json=payload)
        data = {
            "model_id": model_id,
            "dataset_split_id": dataset_split_id,
            "experiment_run_id": experiment_run_id,
            "accuracy": float(accuracy),
            "precision": float(precision),
            "recall": float(recall),
            "f1_score": float(f1_score),
            "confusion_matrix": confusion_matrix,
        }
        if auc_macro is not None:
            data["auc_macro"] = auc_macro
        if auc_micro is not None:
            data["auc_micro"] = auc_micro
        if ap_macro is not None:
            data["ap_macro"] = ap_macro
        if ap_micro is not None:
            data["ap_micro"] = ap_micro
        if roc_curve is not None:
            data["roc_curve"] = roc_curve
        if pr_curve is not None:
            data["pr_curve"] = pr_curve
        return self.client._request("POST", "metrics/", json=data)

    def compare_metrics(
        self,
        model_ids: Union[List[int], str],
        split_id: int,
    ) -> List[Dict[str, Any]]:
        """
        So sánh metrics giữa các model trên một split.
        GET /api/v1/metrics/compare?model_ids=1,2,3&split_id=...

        Args:
            model_ids: List ID model hoặc chuỗi "1,2,3"
            split_id: Dataset split ID

        Returns:
            List dict: model_id, dataset_split_id, accuracy, f1_score, recall, precision, auc_macro, auc_micro
        """
        if isinstance(model_ids, list):
            model_ids = ",".join(str(x) for x in model_ids)
        return self.client._request(
            "GET",
            "metrics/compare",
            params={"model_ids": model_ids, "split_id": split_id},
        )