import logging
import os

import requests
from opentelemetry.trace import Status, StatusCode

from telemetry import get_tracer

logger = logging.getLogger(__name__)


def upload_to_oss(url, file_path):
    """
    使用签名URL上传文件到OSS
    :param str url: 签名URL
    :param str file_path: 文件路径
    :return bool: 是否成功
    """
    tracer = get_tracer(__name__)
    with tracer.start_as_current_span("upload_to_oss") as span:
        span.set_attribute("file.url", url)
        span.set_attribute("file.path", file_path)
        span.set_attribute("file.size", os.path.getsize(file_path))
        max_retries = 5
        retries = 0
        while retries < max_retries:
            with tracer.start_as_current_span("upload_to_oss.request") as req_span:
                req_span.set_attribute("http.retry_count", retries)
                try:
                    req_span.set_attribute("http.method", "PUT")
                    req_span.set_attribute("http.url", url)
                    with open(file_path, 'rb') as f:
                        response = requests.put(url, data=f, timeout=60, headers={"Content-Type": "video/mp4"})
                        req_span.set_attribute("http.status_code", response.status_code)
                        req_span.set_attribute("http.response", response.text)
                        response.raise_for_status()
                        req_span.set_status(Status(StatusCode.OK))
                        span.set_status(Status(StatusCode.OK))
                        return True
                except requests.exceptions.Timeout:
                    req_span.set_attribute("http.error", "Timeout")
                    req_span.set_status(Status(StatusCode.ERROR))
                    retries += 1
                    logger.warning(f"Upload timed out. Retrying {retries}/{max_retries}...")
                except Exception as e:
                    req_span.set_attribute("http.error", str(e))
                    req_span.set_status(Status(StatusCode.ERROR))
                    retries += 1
                    logger.warning(f"Upload failed. Retrying {retries}/{max_retries}...")
        span.set_status(Status(StatusCode.ERROR))
    return False


def download_from_oss(url, file_path):
    """
    使用签名URL下载文件到OSS
    :param str url: 签名URL
    :param Union[LiteralString, str, bytes] file_path: 文件路径
    :return bool: 是否成功
    """
    tracer = get_tracer(__name__)
    with tracer.start_as_current_span("download_from_oss") as span:
        span.set_attribute("file.url", url)
        span.set_attribute("file.path", file_path)
        logging.info("download_from_oss: %s", url)
        file_dir, file_name = os.path.split(file_path)
        if file_dir:
            if not os.path.exists(file_dir):
                os.makedirs(file_dir)
        max_retries = 5
        retries = 0
        while retries < max_retries:
            with tracer.start_as_current_span("download_from_oss.request") as req_span:
                req_span.set_attribute("http.retry_count", retries)
                try:
                    req_span.set_attribute("http.method", "GET")
                    req_span.set_attribute("http.url", url)
                    response = requests.get(url, timeout=15)  # 设置超时时间
                    req_span.set_attribute("http.status_code", response.status_code)
                    with open(file_path, 'wb') as f:
                        f.write(response.content)
                    req_span.set_attribute("file.size", os.path.getsize(file_path))
                    req_span.set_status(Status(StatusCode.OK))
                    span.set_status(Status(StatusCode.OK))
                    return True
                except requests.exceptions.Timeout:
                    req_span.set_attribute("http.error", "Timeout")
                    req_span.set_status(Status(StatusCode.ERROR))
                    retries += 1
                    logger.warning(f"Download timed out. Retrying {retries}/{max_retries}...")
                except Exception as e:
                    req_span.set_attribute("http.error", str(e))
                    req_span.set_status(Status(StatusCode.ERROR))
                    retries += 1
                    logger.warning(f"Download failed. Retrying {retries}/{max_retries}...")
        span.set_status(Status(StatusCode.ERROR))
    return False