import os
import uuid
import json

from openai import AzureOpenAI

from .eval import EvaluationFactory
from .parser import Parser  
from .tracer import Tracer
from .model import Model
from .tracer import TracerFactory
from .parser import Experiment
from .config import ExperimentConfig
import os
from pydantic import BaseModel, HttpUrl
from typing import List, Dict, Any

# @dataclass
class ExperimentRunner:

    def run(self, experiment_config: ExperimentConfig):

        experiment = Parser.parse(experiment_config)
        model = Model(model_params=experiment_config.model)
        model.invoke(experiment)
        
        self._run_evaluations(experiment_config, experiment)
        self._trace_results(experiment_config, experiment)
    
    def _run_evaluations(self, experiment_config: ExperimentConfig, experiment: Experiment):
        for evaluation in experiment.evaluations:
            evaluator = EvaluationFactory.get_evaluator(evaluation.metric)
            for prompt in experiment.prompts:
                evaluator.evaluate(prompt)
    
    def _trace_results(self, experiment_config: ExperimentConfig, experiment: Experiment):
        tracer = TracerFactory.get_tracer(experiment_config.tracer.type, experiment_config.tracer.target)
        tracer.trace(experiment, experiment_config.model)

class PrompTrace:
    def __init__(self):
        self._config_validator = ExperimentConfigValidator()
        self._runner = None

    def run(self, _experiment: dict):
        experiment_config = self._config_validator.validate(_experiment)

        self._runner = ExperimentRunner()
        
        self._runner.run(experiment_config)

class ExperimentConfigValidator:
    def validate(self, _experiment: dict) -> ExperimentConfig:
        try:
            return ExperimentConfig.model_validate(_experiment)
        except Exception as e:
            raise ValueError(f"Invalid experiment configuration: {str(e)}")