import logging
import os
from typing import NamedTuple

import boto3

from labels.model.core import SourceType

LOGGER = logging.getLogger(__name__)


class ExecutionMetrics(NamedTuple):
    """Metrics collected during execution.

    Attributes:
       group: Group identifier for the metrics
       technique_time: Execution time in seconds

    """

    group: str
    technique_time: float


def is_fluid_batch_env() -> bool:
    return "AWS_BATCH_JOB_ID" in os.environ


def process_sbom_metrics(
    execution_id: str | None,
    technique_time: float,
    source_type: SourceType,
) -> None:
    if source_type != SourceType.DIRECTORY:
        return
    if not is_fluid_batch_env():
        return
    try:
        if (
            execution_id
            and (execution_id_parts := execution_id.split("_"))
            and len(execution_id_parts) >= 3
        ):
            metrics = ExecutionMetrics(
                group=execution_id_parts[0],
                technique_time=round(technique_time, 2),
            )
            send_metrics_to_cloudwatch(metrics)
        else:
            LOGGER.error(
                "Unable to send metrics to cloudwatch",
                extra={
                    "extra": {
                        "execution_id": execution_id,
                    }
                },
            )
    except Exception:
        LOGGER.exception("Error sending metrics to cloudwatch")


def send_metrics_to_cloudwatch(execution_metrics: ExecutionMetrics) -> None:
    try:
        dimensions = [
            {"Name": "Group", "Value": execution_metrics.group},
        ]

        metric_data = [
            {
                "MetricName": "ExecutionTime",
                "Dimensions": dimensions,
                "Value": execution_metrics.technique_time,
                "Unit": "Seconds",
            },
        ]

        LOGGER.debug(
            "Sending metrics to CloudWatch",
            extra={
                "extra": {
                    "namespace": "LabelsMetrics",
                    "group": execution_metrics.group,
                    "execution_time": execution_metrics.technique_time,
                }
            },
        )
        cloudwatch_client = boto3.client("cloudwatch", "us-east-1")  # type: ignore[misc]
        cloudwatch_client.put_metric_data(  # type: ignore[misc]
            Namespace="LabelsMetrics",
            MetricData=metric_data,
        )
        LOGGER.info("CloudWatch metrics sent successfully")
    except Exception as exc:  # noqa: BLE001
        LOGGER.warning("Unable to send metrics to cloudwatch: %s", exc)
