from dataclasses import dataclass, field
from datetime import datetime
from typing import Any
from uuid import uuid4

from thescientist.dataset import Dataset


# dependent variable
@dataclass(frozen=True)
class Metric:
    name: str
    dtype: type
    not_null: bool = field(default=True)

    def as_dict(self) -> dict[str, Any]:
        return {
            "name": self.name,
            "dtype": str(self.dtype.__name__),
            "not_null": self.not_null
        }


class MetricCollector:
    def __init__(self, name, metrics: list[Metric]) -> None:
        self.name = name
        self.original_metrics = metrics
        self.metrics = {
            metric.name: {
                "schema": metric,
                "dataset": Dataset.empty(schema={"id": str, metric.name: metric.dtype, "collected_at": str})
            }
            for metric in metrics
        }
    
    def __repr__(self) -> str:
        return f"Collector(metrics={self.metrics})::data =\n{self.datasets}"

    def collect(self, metrics: dict[str, Any]) -> None:
        collected_id = str(uuid4())
        collected_at = datetime.now().isoformat()  # datetime.now(timezone.utc)
        
        for metric_name, value in metrics.items():
            metric = self.metrics.get(metric_name)

            if not metric:
                print(f"[WARNING] metric '{metric_name}' not defined.")
                continue

            data = {"id": collected_id, metric["schema"].name: value, "collected_at": collected_at}

            if (value is None) and metric["schema"].not_null:
                print(f"[WARNING] metric '{metric_name}' can not be null.")
                continue

            metric["dataset"].append(data)
