"""Google Photos service provider — concrete implementation of ServiceProvider."""

from __future__ import annotations

import logging
from typing import Any

import aiohttp

from notify_bridge_core.models.events import ServiceEvent
from notify_bridge_core.providers.base import ServiceProvider, ServiceProviderType
from notify_bridge_core.templates.variables import TemplateVariableDefinition

from .change_detector import detect_album_changes
from .client import GooglePhotosClient
from .models import GooglePhotosAlbumData

_LOGGER = logging.getLogger(__name__)


# Google Photos specific template variables
GOOGLE_PHOTOS_VARIABLES: list[TemplateVariableDefinition] = [
    TemplateVariableDefinition(
        name="album_name",
        type="string",
        description="Album name (alias for collection_name)",
        example="Vacation 2026",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="album_id",
        type="string",
        description="Album ID (alias for collection_id)",
        example="ABc123...",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="album_url",
        type="string",
        description="Web URL to the album in Google Photos",
        example="https://photos.google.com/lr/album/ABc123...",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="photo_count",
        type="int",
        description="Number of photos in album",
        example="42",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="video_count",
        type="int",
        description="Number of videos in album",
        example="8",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="shared",
        type="bool",
        description="Whether the album is shared",
        example="true",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="old_album_name",
        type="string",
        description="Previous album name (for rename events)",
        example="Old Name",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
    TemplateVariableDefinition(
        name="new_album_name",
        type="string",
        description="New album name (for rename events)",
        example="New Name",
        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
    ),
]


class GooglePhotosServiceProvider(ServiceProvider):
    """Google Photos Library API provider."""

    provider_type = ServiceProviderType.GOOGLE_PHOTOS

    def __init__(
        self,
        session: aiohttp.ClientSession,
        client_id: str,
        client_secret: str,
        refresh_token: str,
        name: str = "Google Photos",
    ) -> None:
        self._client = GooglePhotosClient(session, client_id, client_secret, refresh_token)
        self._name = name

    @property
    def client(self) -> GooglePhotosClient:
        return self._client

    async def connect(self) -> bool:
        return await self._client.ping()

    async def disconnect(self) -> None:
        pass  # session lifecycle managed by caller

    async def poll(
        self,
        collection_ids: list[str],
        tracker_state: dict[str, Any],
    ) -> tuple[list[ServiceEvent], dict[str, Any]]:
        events: list[ServiceEvent] = []
        new_state = dict(tracker_state)

        for album_id in collection_ids:
            album = await self._client.get_album_with_items(album_id)
            if album is None:
                # Album deleted or inaccessible
                if album_id in new_state:
                    from notify_bridge_core.models.events import EventType
                    from datetime import datetime, timezone

                    events.append(ServiceEvent(
                        event_type=EventType.COLLECTION_DELETED,
                        provider_type=ServiceProviderType.GOOGLE_PHOTOS,
                        provider_name=self._name,
                        collection_id=album_id,
                        collection_name=new_state.get(album_id, {}).get("name", "Unknown"),
                        timestamp=datetime.now(timezone.utc),
                    ))
                    del new_state[album_id]
                continue

            # Get previous state
            prev = new_state.get(album_id)
            if prev is None:
                # First time seeing this album — store state, no event
                new_state[album_id] = _serialize_album_state(album)
                continue

            # Reconstruct previous album data for comparison
            old_album = _deserialize_album_state(album_id, prev)
            pending = set(prev.get("pending_asset_ids", []))

            detected_events, updated_pending = detect_album_changes(
                old_album, album, pending, self._name,
            )

            if detected_events:
                events.extend(detected_events)

            # Update state
            state = _serialize_album_state(album)
            state["pending_asset_ids"] = list(updated_pending)
            new_state[album_id] = state

        return events, new_state

    def get_available_variables(self) -> list[TemplateVariableDefinition]:
        return list(GOOGLE_PHOTOS_VARIABLES)

    def get_provider_config_schema(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "client_id": {
                    "type": "string",
                    "description": "Google OAuth2 Client ID",
                },
                "client_secret": {
                    "type": "string",
                    "description": "Google OAuth2 Client Secret",
                    "secret": True,
                },
                "refresh_token": {
                    "type": "string",
                    "description": "OAuth2 Refresh Token (from Google OAuth Playground)",
                    "secret": True,
                },
            },
            "required": ["client_id", "client_secret", "refresh_token"],
        }

    async def list_collections(self) -> list[dict[str, Any]]:
        albums = await self._client.list_albums(include_shared=True)
        return [
            {
                "id": a.get("id", ""),
                "name": a.get("title", "Untitled"),
                "asset_count": int(a.get("mediaItemsCount", 0)),
            }
            for a in albums
        ]

    async def test_connection(self) -> dict[str, Any]:
        ok = await self._client.ping()
        if ok:
            albums = await self._client.list_albums(include_shared=False)
            return {
                "ok": True,
                "message": f"Connected to Google Photos ({len(albums)} albums found)",
            }
        return {"ok": False, "message": "Failed to connect to Google Photos"}


def _serialize_album_state(album: GooglePhotosAlbumData) -> dict[str, Any]:
    """Serialize album state for persistence."""
    return {
        "name": album.name,
        "asset_ids": list(album.asset_ids),
        "shared": album.is_shared,
        "pending_asset_ids": [],
    }


def _deserialize_album_state(album_id: str, state: dict[str, Any]) -> GooglePhotosAlbumData:
    """Create a minimal GooglePhotosAlbumData from saved state for comparison."""
    return GooglePhotosAlbumData(
        id=album_id,
        name=state.get("name", ""),
        asset_count=len(state.get("asset_ids", [])),
        product_url="",
        is_shared=state.get("shared", False),
        asset_ids=set(state.get("asset_ids", [])),
    )
