"""Thin wrapper around the bits of the Immich API this project needs."""

from __future__ import annotations

from datetime import datetime, timedelta, timezone

import httpx


class ImmichClient:
    def __init__(self, base_url: str, api_key: str):
        self.base_url = base_url.rstrip("/")
        self._headers = {"x-api-key": api_key}

    def list_albums(self) -> list[dict]:
        resp = httpx.get(f"{self.base_url}/api/albums", headers=self._headers, timeout=10)
        resp.raise_for_status()
        return resp.json()

    def list_album_assets(self, album_id: str) -> list[dict]:
        """GET /api/albums/{id} doesn't embed assets in this Immich version
        (AlbumResponseDto only has assetCount) -- assets live behind the
        general search API instead, filtered by albumIds.

        Only returns the first page. Fine for a photo frame cycling
        through an album; worth adding nextPage pagination if someone
        points this at an album large enough to need it.
        """
        resp = httpx.post(
            f"{self.base_url}/api/search/metadata",
            headers=self._headers,
            json={"albumIds": [album_id]},
            timeout=15,
        )
        resp.raise_for_status()
        return resp.json().get("assets", {}).get("items", [])

    def get_asset_faces(self, asset_id: str) -> list[dict]:
        """Face bounding boxes Immich already computed for its own People
        feature -- reused here to bias cropping toward keeping faces on
        screen instead of running our own detection."""
        resp = httpx.get(
            f"{self.base_url}/api/faces",
            params={"id": asset_id},
            headers=self._headers,
            timeout=10,
        )
        resp.raise_for_status()
        return resp.json()

    def download_asset_preview(self, asset_id: str) -> bytes:
        resp = httpx.get(
            f"{self.base_url}/api/assets/{asset_id}/thumbnail",
            params={"size": "preview"},
            headers=self._headers,
            timeout=30,
        )
        resp.raise_for_status()
        return resp.content

    def download_asset_thumbnail(self, asset_id: str) -> tuple[bytes, str]:
        """Smaller than download_asset_preview -- used for the web UI's
        upcoming-photos list, not the actual rendered frame. Returns
        (content, content_type) since this one gets proxied straight to a
        browser <img> tag and needs a correct Content-Type header."""
        resp = httpx.get(
            f"{self.base_url}/api/assets/{asset_id}/thumbnail",
            params={"size": "thumbnail"},
            headers=self._headers,
            timeout=30,
        )
        resp.raise_for_status()
        return resp.content, resp.headers.get("content-type", "image/jpeg")

    def get_asset(self, asset_id: str) -> dict:
        """Full asset metadata, including embedded exifInfo (location,
        capture date) -- used for the manage-button overlay's location/
        date-taken text."""
        resp = httpx.get(f"{self.base_url}/api/assets/{asset_id}", headers=self._headers, timeout=10)
        resp.raise_for_status()
        return resp.json()

    def create_share_link(self, asset_id: str, expires_in_s: int) -> str:
        """Creates a public, view-only Immich share link for a single
        asset, expiring expires_in_s seconds from now, and returns its
        public URL. Used by the manage-button overlay's share QR --
        created lazily (only when someone actually scans it), not when
        the button's pressed, so the expiry clock starts when it's
        actually used."""
        expires_at = (datetime.now(timezone.utc) + timedelta(seconds=expires_in_s)).isoformat()
        resp = httpx.post(
            f"{self.base_url}/api/shared-links",
            headers=self._headers,
            json={
                "type": "INDIVIDUAL",
                "assetIds": [asset_id],
                "expiresAt": expires_at,
                "allowUpload": False,
                "allowDownload": True,
                "showMetadata": True,
            },
            timeout=10,
        )
        resp.raise_for_status()
        key = resp.json()["key"]
        return f"{self.base_url}/share/{key}"
