import os
from dataclasses import dataclass
from datetime import datetime
from typing import Optional

import requests

from .recorder_service import RecordResult


@dataclass
class UploadConfig:
    login_url: str = "https://azn.gbdfarm.com/prod-api/auth/login"
    file_upload_url: str = "https://azn.gbdfarm.com/prod-api/file/upload"
    data_upload_url: str = "https://azn.gbdfarm.com/prod-api/base/video/uploadVideo"
    username: str = "admin"
    password: str = "gbd2025"
    code: str = "0"
    timeout_sec: int = 8
    device_id: str = "CAM-001"
    species_type: int = 0
    enable_ir_video_url: bool = True


class ServerUploadClient:
    def __init__(self, config: UploadConfig):
        self.cfg = config

    @staticmethod
    def _fmt_time(dt: datetime) -> str:
        return dt.strftime("%Y-%m-%d %H:%M:%S")

    def _login(self) -> str:
        headers = {"Device-Type": "DEVICE", "Content-Type": "application/json"}
        body = {"username": self.cfg.username, "password": self.cfg.password, "code": self.cfg.code}
        r = requests.post(self.cfg.login_url, json=body, headers=headers, timeout=self.cfg.timeout_sec)
        r.raise_for_status()
        j = r.json()
        if j.get("code") != 200:
            raise RuntimeError(f"login failed: {j}")
        token = j.get("data", {}).get("access_token")
        if not token:
            raise RuntimeError("login success but access_token missing")
        return token

    def _upload_file(self, token: str, file_path: str) -> str:
        if not os.path.exists(file_path):
            raise RuntimeError(f"file not found: {file_path}")

        headers = {"Authorization": token}
        with open(file_path, "rb") as f:
            files = {"file": (os.path.basename(file_path), f)}
            r = requests.post(self.cfg.file_upload_url, headers=headers, files=files, timeout=self.cfg.timeout_sec)
        r.raise_for_status()
        j = r.json()
        if j.get("code") != 200:
            raise RuntimeError(f"file upload failed: {j}")
        url = j.get("data", {}).get("url")
        if not url:
            raise RuntimeError("file upload success but url missing")
        return url

    def upload_record(self, rec: RecordResult) -> None:
        token = self._login()

        rgb_url = self._upload_file(token, rec.rgb_video_path)
        ir_url: Optional[str] = None
        if self.cfg.enable_ir_video_url:
            ir_url = self._upload_file(token, rec.ir_video_path)

        payload = {
            "speciesId": str(rec.species_id),
            "tempValue": round(float(rec.temp_value), 1),
            "tempTime": self._fmt_time(rec.temp_time),
            "deviceId": self.cfg.device_id,
            "speciesType": int(self.cfg.species_type),
            "videoStartTime": self._fmt_time(rec.video_start_time),
            "videoEndTime": self._fmt_time(rec.video_end_time),
            "videoDuration": int(rec.video_duration),
            "videoUrl": rgb_url,
        }

        if ir_url is not None:
            payload["irVideoURL"] = ir_url

        headers = {"Authorization": token, "Content-Type": "application/json"}
        r = requests.post(self.cfg.data_upload_url, json=payload, headers=headers, timeout=self.cfg.timeout_sec)
        r.raise_for_status()
        j = r.json()
        if j.get("code") != 200:
            raise RuntimeError(f"data upload failed: {j}")


