import requests

from ._errors import MLDashAuthError, MLDashUploadError


def upload_bundle(zip_path, url, api_key, name, description='',
                  task_type='', framework='', project_id=None):
    """Upload a ZIP bundle to the ML-Dash import endpoint.

    Returns the JSON response body from the server.
    """
    endpoint = url.rstrip('/') + '/api/models/import/'

    from ._api import _SDK_HEADERS
    headers = {
        'X-API-Key': api_key,
        **_SDK_HEADERS,
    }

    data = {
        'name': name,
    }
    if description:
        data['description'] = description
    if task_type:
        data['task_type'] = task_type
    if framework:
        data['framework'] = framework
    if project_id is not None:
        data['project'] = str(project_id)

    try:
        with open(zip_path, 'rb') as f:
            files = {'model_file': ('model.zip', f, 'application/zip')}
            resp = requests.post(endpoint, headers=headers, data=data, files=files)
    except requests.ConnectionError as exc:
        raise MLDashUploadError(
            f"Could not connect to ML-Dash at {url}. Is the server running?"
        ) from exc
    except requests.RequestException as exc:
        raise MLDashUploadError(f"Upload failed: {exc}") from exc

    if resp.status_code == 401:
        detail = resp.json().get('detail', resp.json().get('error', 'Authentication failed'))
        raise MLDashAuthError(detail)
    if resp.status_code == 403:
        detail = resp.json().get('detail', resp.json().get('error', 'Forbidden'))
        raise MLDashAuthError(detail)
    if resp.status_code not in (200, 201):
        try:
            body = resp.json()
            msg = body.get('error') or body.get('detail') or str(body)
        except Exception:
            msg = resp.text[:500]
        raise MLDashUploadError(f"Server returned {resp.status_code}: {msg}")

    return resp.json()
