"""Google Drive API service wrapper."""

from __future__ import annotations

import base64
import io
import mimetypes
import os
from pathlib import Path
from typing import Any, Optional

from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseUpload, MediaIoBaseDownload

from ..auth.oauth import get_credentials, resolve_profile


def _get_service(profile: Optional[str] = None):
    return build("drive", "v3", credentials=get_credentials(resolve_profile(profile)))


FIELDS = "id, name, mimeType, size, modifiedTime, parents, webViewLink"


# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------

def list_files(
    profile: Optional[str] = None,
    folder_id: Optional[str] = None,
    query: Optional[str] = None,
    max_results: int = 30,
    page_token: Optional[str] = None,
) -> dict[str, Any]:
    svc = _get_service(profile)
    q_parts: list[str] = []
    if query:
        q_parts.append(f"({query})")
    if folder_id:
        q_parts.append(f"'{folder_id}' in parents")
    q_parts.append("trashed = false")
    q = " and ".join(q_parts)

    res = svc.files().list(
        q=q, pageSize=max_results, pageToken=page_token,
        fields=f"nextPageToken, files({FIELDS})",
        orderBy="modifiedTime desc",
    ).execute()

    return {
        "nextPageToken": res.get("nextPageToken"),
        "files": res.get("files", []),
    }


def upload_file(
    local_path: str,
    profile: Optional[str] = None,
    folder_id: Optional[str] = None,
    name: Optional[str] = None,
    mime_type: Optional[str] = None,
) -> dict[str, Any]:
    svc = _get_service(profile)
    file_name = name or os.path.basename(local_path)
    if not mime_type:
        mime_type, _ = mimetypes.guess_type(local_path)
        mime_type = mime_type or "application/octet-stream"

    parents = [folder_id] if folder_id else None
    media = MediaFileUpload(local_path, mimetype=mime_type, resumable=True)
    res = svc.files().create(
        body={"name": file_name, "parents": parents, "mimeType": mime_type},
        media_body=media,
        fields=FIELDS,
    ).execute()
    return res


def upload_base64(
    base64_data: str,
    name: str,
    mime_type: str,
    profile: Optional[str] = None,
    folder_id: Optional[str] = None,
) -> dict[str, Any]:
    svc = _get_service(profile)
    data = base64.b64decode(base64_data)
    media = MediaIoBaseUpload(io.BytesIO(data), mimetype=mime_type, resumable=True)
    parents = [folder_id] if folder_id else None
    res = svc.files().create(
        body={"name": name, "parents": parents, "mimeType": mime_type},
        media_body=media,
        fields=FIELDS,
    ).execute()
    return res


def download_file(file_id: str, save_path: str, profile: Optional[str] = None) -> dict[str, Any]:
    svc = _get_service(profile)
    request = svc.files().get_media(fileId=file_id)
    Path(save_path).parent.mkdir(parents=True, exist_ok=True)

    with open(save_path, "wb") as f:
        downloader = MediaIoBaseDownload(f, request)
        done = False
        while not done:
            _, done = downloader.next_chunk()

    return {"saved": save_path, "size": os.path.getsize(save_path)}


def create_folder(
    name: str,
    profile: Optional[str] = None,
    parent_id: Optional[str] = None,
) -> dict[str, Any]:
    svc = _get_service(profile)
    parents = [parent_id] if parent_id else None
    res = svc.files().create(
        body={
            "name": name,
            "mimeType": "application/vnd.google-apps.folder",
            "parents": parents,
        },
        fields=FIELDS,
    ).execute()
    return res


def move_file(file_id: str, new_parent_id: str, profile: Optional[str] = None) -> dict[str, Any]:
    svc = _get_service(profile)
    file = svc.files().get(fileId=file_id, fields="parents").execute()
    old_parents = ",".join(file.get("parents", []))
    res = svc.files().update(
        fileId=file_id,
        addParents=new_parent_id,
        removeParents=old_parents,
        fields=FIELDS,
    ).execute()
    return res


def trash_file(file_id: str, profile: Optional[str] = None) -> dict[str, Any]:
    svc = _get_service(profile)
    svc.files().update(fileId=file_id, body={"trashed": True}).execute()
    return {"fileId": file_id, "status": "trashed"}
