"""GitHub App installation store — V2.2c

Persists GitHub App installation_id per repo as a property on Service nodes
(or as a standalone GithubInstallation node when the Service doesn't exist yet).

Public API:
    upsert_installation(repo_full_name, installation_id, account_login) -> None
    get_installation_id(repo_full_name) -> int | None
"""
from __future__ import annotations

import logging

from postura.graph.connection import get_driver

logger = logging.getLogger(__name__)


def upsert_installation(repo_full_name: str, installation_id: int, account_login: str) -> None:
    """
    Store the GitHub App installation_id for a repository.

    Merges on a GithubInstallation node keyed by repo_full_name so the data is
    available even before the repo has been analysed and a Service node created.
    Also updates the Service node if one exists.
    """
    driver = get_driver()
    with driver.session() as session:
        session.run(
            """
            MERGE (gi:GithubInstallation {repo_full_name: $repo})
            SET gi.installation_id = $installation_id,
                gi.account_login   = $account_login,
                gi.updated_at      = datetime()
            """,
            repo=repo_full_name,
            installation_id=installation_id,
            account_login=account_login,
        )
        # Also patch the Service node if it already exists
        session.run(
            """
            MATCH (s:Service {repo_full_name: $repo})
            SET s.installation_id = $installation_id
            """,
            repo=repo_full_name,
            installation_id=installation_id,
        )
    logger.debug("Upserted installation %s for %s", installation_id, repo_full_name)


def get_installation_id(repo_full_name: str) -> int | None:
    """
    Return the stored GitHub App installation_id for a repo, or None if unknown.

    Checks the GithubInstallation node first, falls back to Service node.
    """
    driver = get_driver()
    with driver.session() as session:
        result = session.run(
            """
            OPTIONAL MATCH (gi:GithubInstallation {repo_full_name: $repo})
            OPTIONAL MATCH (s:Service {repo_full_name: $repo})
            RETURN
              coalesce(gi.installation_id, s.installation_id) AS installation_id
            LIMIT 1
            """,
            repo=repo_full_name,
        )
        record = result.single()
        if record and record["installation_id"] is not None:
            return int(record["installation_id"])
    return None
