"""Gitea service provider — webhook-based 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 .client import GiteaClient

_LOGGER = logging.getLogger(__name__)


# Gitea-specific template variables
GITEA_VARIABLES: list[TemplateVariableDefinition] = [
    TemplateVariableDefinition(
        name="sender",
        type="string",
        description="Username of the user who triggered the event",
        example="alexei",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="sender_name",
        type="string",
        description="Display name of the sender",
        example="Alexei",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="repo_name",
        type="string",
        description="Repository name (without owner)",
        example="my-project",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="repo_full_name",
        type="string",
        description="Full repository name (owner/repo)",
        example="alexei/my-project",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="repo_url",
        type="string",
        description="URL to the repository",
        example="https://gitea.example.com/alexei/my-project",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="branch",
        type="string",
        description="Branch name (push events)",
        example="main",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="commits",
        type="list",
        description="List of commits (push events); each has id, short_id, message, url, author",
        example='[{"short_id": "abc1234", "message": "fix bug", ...}]',
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="commit_count",
        type="int",
        description="Number of commits in push",
        example="3",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="compare_url",
        type="string",
        description="URL to compare changes (push events)",
        example="https://gitea.example.com/alexei/my-project/compare/abc...def",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="issue_number",
        type="int",
        description="Issue number",
        example="42",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="issue_title",
        type="string",
        description="Issue title",
        example="Bug in login page",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="issue_url",
        type="string",
        description="URL to the issue",
        example="https://gitea.example.com/alexei/my-project/issues/42",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="pr_number",
        type="int",
        description="Pull request number",
        example="17",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="pr_title",
        type="string",
        description="Pull request title",
        example="Add dark mode support",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="pr_url",
        type="string",
        description="URL to the pull request",
        example="https://gitea.example.com/alexei/my-project/pulls/17",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="pr_merged",
        type="bool",
        description="Whether the PR was merged (vs closed without merge)",
        example="true",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="pr_base",
        type="string",
        description="Base branch of the PR",
        example="main",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="pr_head",
        type="string",
        description="Head branch of the PR",
        example="feature/dark-mode",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="release_tag",
        type="string",
        description="Release tag name",
        example="v1.2.0",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="release_name",
        type="string",
        description="Release title",
        example="Version 1.2.0",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="release_url",
        type="string",
        description="URL to the release page",
        example="https://gitea.example.com/alexei/my-project/releases/tag/v1.2.0",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="comment_body",
        type="string",
        description="Comment text (comment events)",
        example="Looks good to me!",
        provider_type=ServiceProviderType.GITEA,
    ),
    TemplateVariableDefinition(
        name="comment_url",
        type="string",
        description="URL to the comment",
        example="https://gitea.example.com/.../issues/42#issuecomment-123",
        provider_type=ServiceProviderType.GITEA,
    ),
]


class GiteaServiceProvider(ServiceProvider):
    """Gitea webhook-based provider.

    Unlike Immich (polling), Gitea pushes events to us via webhooks.
    The poll() method is a no-op — events are parsed from incoming
    webhook payloads by event_parser.parse_webhook().
    """

    provider_type = ServiceProviderType.GITEA

    def __init__(
        self,
        session: aiohttp.ClientSession,
        url: str,
        api_token: str,
        name: str = "Gitea",
    ) -> None:
        self._client = GiteaClient(session, url, api_token)
        self._name = name

    @property
    def client(self) -> GiteaClient:
        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]]:
        # Gitea is webhook-based — poll() is not used.
        # Events arrive via the /api/webhooks/gitea route.
        return [], tracker_state

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

    def get_provider_config_schema(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "url": {
                    "type": "string",
                    "description": "Gitea server URL",
                    "example": "https://gitea.example.com",
                },
                "api_token": {
                    "type": "string",
                    "description": "Gitea API token (for connection testing and repo listing)",
                    "secret": True,
                },
                "webhook_secret": {
                    "type": "string",
                    "description": "Shared secret for HMAC-SHA256 webhook signature verification",
                    "secret": True,
                },
            },
            "required": ["url", "webhook_secret"],
        }

    async def list_collections(self) -> list[dict[str, Any]]:
        repos = await self._client.get_repos()
        return [
            {
                "id": r.get("full_name", ""),
                "name": r.get("full_name", ""),
                "description": r.get("description", ""),
                "updated_at": r.get("updated", ""),
            }
            for r in repos
        ]

    async def test_connection(self) -> dict[str, Any]:
        ok = await self._client.ping()
        if ok:
            version = await self._client.get_server_version()
            return {
                "ok": True,
                "message": f"Connected to Gitea{f' v{version}' if version else ''}",
            }
        return {"ok": False, "message": "Failed to connect to Gitea"}
