"""Dispatch GitHub **user** App webhooks — sync installation suspension with DB."""
from __future__ import annotations

from typing import Any

import structlog
from sqlalchemy.ext.asyncio import AsyncSession

from src.domain.github_user_mirror.repository import WorkspaceUserGithubInstallationRepository

logger = structlog.get_logger()


async def dispatch(db: AsyncSession, event: str, payload: dict[str, Any]) -> dict[str, Any]:
    if event == "ping":
        return {"action": "pong"}

    repo = WorkspaceUserGithubInstallationRepository(db)

    if event == "installation":
        action = payload.get("action") or ""
        inst = payload.get("installation") or {}
        iid = inst.get("id")
        if not iid:
            return {"action": "ignored", "reason": "no_installation_id"}
        if action == "deleted":
            rows = await repo.list_by_github_installation_id(int(iid))
            for row in rows:
                await repo.delete(row.id)
            logger.info(
                "github_user_installation_deleted",
                installation_id=iid,
                count=len(rows),
            )
            return {"action": "installation_removed", "installation_id": iid}
        if action == "suspend":
            await repo.set_suspended(int(iid), True)
            logger.info("github_user_installation_suspended", installation_id=iid)
            return {"action": "installation_suspended", "installation_id": iid}
        if action == "unsuspend":
            await repo.set_suspended(int(iid), False)
            return {"action": "installation_unsuspended", "installation_id": iid}
        if action in ("created", "new_permissions_accepted"):
            # Linking is done via API; optionally refresh selection from payload
            sel = (inst.get("repository_selection") or "all").lower()
            rows = await repo.list_by_github_installation_id(int(iid))
            if rows and sel in ("all", "selected"):
                for row in rows:
                    row.repository_selection = sel
                await repo.flush()
            return {
                "action": "installation_noted",
                "installation_id": iid,
                "count": len(rows),
            }
        return {"action": "installation_ignored", "sub_action": action}

    if event == "installation_repositories":
        # User added/removed repos from selection
        inst = payload.get("installation") or {}
        iid = inst.get("id")
        if iid:
            rows = await repo.list_by_github_installation_id(int(iid))
            if rows:
                sel = (
                    inst.get("repository_selection")
                    or rows[0].repository_selection
                ).lower()
                if sel in ("all", "selected"):
                    for row in rows:
                        row.repository_selection = sel
                    await repo.flush()
        return {
            "action": "repositories_updated",
            "installation_id": iid,
            "count": len(rows) if iid else 0,
        }

    return {"action": "ignored", "event": event}
