"""Upload local files to a connector-scoped R2 bucket via S3-compatible API."""
from __future__ import annotations

import mimetypes
import os
from typing import Any

SINGLE_PUT_MAX_BYTES = 100 * 1024 * 1024  # 100 MB — above this use multipart
MULTIPART_PART_BYTES = 8 * 1024 * 1024  # 8 MB parts


def r2_endpoint(account_id: str) -> str:
    return f"https://{account_id}.r2.cloudflarestorage.com"


def s3_client(*, account_id: str, access_key_id: str, secret_access_key: str):
    import boto3

    return boto3.client(
        "s3",
        endpoint_url=r2_endpoint(account_id),
        aws_access_key_id=access_key_id,
        aws_secret_access_key=secret_access_key,
        region_name="auto",
    )


def guess_content_type(path: str) -> str:
    ct, _ = mimetypes.guess_type(path)
    return ct or "application/octet-stream"


def upload_file_from_path(
    *,
    account_id: str,
    access_key_id: str,
    secret_access_key: str,
    bucket: str,
    key: str,
    local_path: str,
    content_type: str | None = None,
) -> dict[str, Any]:
    """Upload a file from disk to R2, using multipart upload for large files."""
    size = os.path.getsize(local_path)
    ct = content_type or guess_content_type(local_path)
    s3 = s3_client(
        account_id=account_id,
        access_key_id=access_key_id,
        secret_access_key=secret_access_key,
    )

    if size <= SINGLE_PUT_MAX_BYTES:
        with open(local_path, "rb") as fh:
            s3.put_object(Bucket=bucket, Key=key, Body=fh, ContentType=ct)
        return {"key": key, "size_bytes": size, "multipart": False}

    resp = s3.create_multipart_upload(Bucket=bucket, Key=key, ContentType=ct)
    upload_id = resp["UploadId"]
    parts: list[dict[str, Any]] = []
    part_number = 1
    try:
        with open(local_path, "rb") as fh:
            while True:
                chunk = fh.read(MULTIPART_PART_BYTES)
                if not chunk:
                    break
                part = s3.upload_part(
                    Bucket=bucket,
                    Key=key,
                    UploadId=upload_id,
                    PartNumber=part_number,
                    Body=chunk,
                )
                parts.append({"PartNumber": part_number, "ETag": part["ETag"]})
                part_number += 1
        s3.complete_multipart_upload(
            Bucket=bucket,
            Key=key,
            UploadId=upload_id,
            MultipartUpload={"Parts": parts},
        )
    except Exception:
        try:
            s3.abort_multipart_upload(Bucket=bucket, Key=key, UploadId=upload_id)
        except Exception:
            pass
        raise

    return {"key": key, "size_bytes": size, "multipart": True, "parts": len(parts)}
