"""
Do not edit this file
This is the file that will be used to train your model
"""
import os
import json
import requests
from typing import Callable, Coroutine, Mapping

from .utils import make_file, clean_files

class TrainResults:
    """Results of training."""
    # Files is an array of files from open() function
    def __init__(self, pretrained_model: str, metrics: dict[str, float], files: Mapping[str, bytes | str]):
        self.pretrained_model = pretrained_model
        self.metrics = metrics
        self.files = files


async def train(
    # This main function is an async function that returns TrainResults type
    main: Callable[..., Coroutine[None, None, TrainResults]],
    result_id: str,
    api_url: str,
    user_token: str,
    **kwargs,
) -> None:
    """
    Train a model
    This function will provide the dataset path, parameters and result_id
    and will return the results of training.
    """
    try:
        train_results = await main(result_id=result_id, **kwargs)

        # Stringify metrics
        metrics = json.dumps(train_results.metrics)
        data = {
            "result_id": result_id,
            "metrics": metrics,
            "pretrained_model": train_results.pretrained_model,
            "pkg_name": "pymlab.train",
        }

        response = requests.post(api_url, data=data, files=train_results.files,timeout=120, verify=False, headers={"Authorization":f"Bearer {user_token}"})

        if response.status_code == 200:
            # delete files
            clean_files(result_id)
        else:
            raise requests.HTTPError(f"Error uploading results. Status code: {response.status_code}, error: {response.text}")

    except Exception as e:
        file_path = make_file(result_id, "error.txt", str(e))
        with open(file_path, "rb") as f:
            error_file = f.read()
        req_files = {
            "error.txt": error_file,
        }
        requests.post(api_url+f"?error={True}", data={"result_id": result_id, "error": str(e)}, files=req_files, timeout=120, verify=False, headers={"Authorization":f"Bearer {user_token}"})
