from __future__ import annotations

from pathlib import Path
from typing import Any, Iterable
import requests

from .config import AgentConfig


class ERPClient:
    def __init__(self, config: AgentConfig):
        self.config = config
        self.session = requests.Session()
        self.session.headers.update(config.headers)

    def _url(self, path: str) -> str:
        return f"{self.config.erp_base_url}{path}"

    def heartbeat(self, payload: dict[str, Any]) -> dict[str, Any]:
        response = self.session.post(
            self._url("/documents/storage-agent/heartbeat"),
            json=payload,
            timeout=self.config.request_timeout_seconds,
        )
        response.raise_for_status()
        return response.json() if response.content else {"status": "ok"}

    def pending_storage_jobs(self) -> list[dict[str, Any]]:
        response = self.session.get(
            self._url("/documents/storage-agent/jobs/pending"),
            timeout=self.config.request_timeout_seconds,
        )
        response.raise_for_status()
        data = response.json()
        if isinstance(data, list):
            return data
        return data.get("jobs", [])

    def download_storage_job(self, job_id: int | str):
        response = self.session.get(
            self._url(f"/documents/storage-agent/jobs/{job_id}/download"),
            stream=True,
            timeout=self.config.request_timeout_seconds,
        )
        response.raise_for_status()
        return response

    def acknowledge_storage_job(self, job_id: int | str, payload: dict[str, Any]) -> dict[str, Any]:
        response = self.session.post(
            self._url(f"/documents/storage-agent/jobs/{job_id}/ack"),
            json=payload,
            timeout=self.config.request_timeout_seconds,
        )
        response.raise_for_status()
        return response.json() if response.content else {"status": "ok"}

    def pending_download_requests(self) -> list[dict[str, Any]]:
        response = self.session.get(
            self._url("/documents/storage-agent/download-requests/pending"),
            timeout=self.config.request_timeout_seconds,
        )
        response.raise_for_status()
        data = response.json()
        if isinstance(data, list):
            return data
        return data.get("requests", [])

    def upload_download_request_file(self, request_id: int | str, file_path: Path, extra: dict[str, Any]) -> dict[str, Any]:
        with file_path.open("rb") as handle:
            files = {"file": (file_path.name, handle, "application/octet-stream")}
            data = {key: str(value) for key, value in extra.items() if value is not None}
            response = self.session.post(
                self._url(f"/documents/storage-agent/download-requests/{request_id}/upload"),
                files=files,
                data=data,
                timeout=max(self.config.request_timeout_seconds, 300),
            )
        response.raise_for_status()
        return response.json() if response.content else {"status": "ok"}


    def update_manifest(self) -> dict[str, Any]:
        response = self.session.get(
            self._url("/documents/erp-local-agent/update-manifest"),
            timeout=self.config.request_timeout_seconds,
        )
        response.raise_for_status()
        return response.json()

    def download_update_package(self) -> bytes:
        response = self.session.get(
            self._url("/documents/erp-local-agent/update-package"),
            timeout=max(self.config.request_timeout_seconds, 300),
        )
        response.raise_for_status()
        return response.content
