# retoor <retoor@molodetz.nl>

import logging

from devplacepy.database import get_issue_usage
from devplacepy.services.base import BaseService
from devplacepy.services.gitea import runtime, store
from devplacepy.services.gitea.client import GiteaError
from devplacepy.services.gitea.config import CONFIG_FIELDS, gitea_config
from devplacepy.services.openai_gateway.usage import usage_metric_cards
from devplacepy.utils import create_notification

logger = logging.getLogger(__name__)


class IssueTrackerService(BaseService):
    interval_key = "issue_tracker_interval"
    min_interval = 30
    default_enabled = False
    title = "Issue Tracker"
    description = (
        "Holds the Gitea connection and AI settings for the issue tracker and polls every "
        "tracked issue for developer replies and status changes, notifying the original "
        "reporter when their ticket is updated. Reports the aggregated AI usage spent on "
        "ticket enhancement and planning."
    )
    config_fields = CONFIG_FIELDS

    def __init__(self):
        super().__init__(name="issue_tracker", interval_seconds=120)

    def collect_metrics(self) -> dict:
        return {"stats": usage_metric_cards(get_issue_usage())}

    async def run_once(self) -> None:
        config = gitea_config()
        if not config.is_configured:
            self.log("Gitea integration not configured; skipping poll")
            return

        client = runtime.get_client()
        tickets = store.tracked_tickets()
        self.log(f"Polling {len(tickets)} tracked tickets")
        checked = 0
        notified = 0
        for ticket in tickets:
            number = int(ticket["gitea_number"])
            try:
                issue = await client.get_issue(number)
            except GiteaError as exc:
                self.log(f"Could not poll #{number}: {exc}")
                continue
            checked += 1
            notified += await self._reconcile(client, ticket, issue)
        self.log(f"Polled {checked} tickets, sent {notified} notifications")

    async def _reconcile(self, client, ticket: dict, issue: dict) -> int:
        number = int(ticket["gitea_number"])
        author_uid = ticket["author_uid"]
        state = issue.get("state", "open")
        comment_count = int(issue.get("comments", 0))
        last_count = int(ticket.get("last_comment_count", 0))
        last_status = ticket.get("last_status", "open")
        notified = 0

        if comment_count > last_count:
            try:
                comments = await client.list_comments(number)
            except GiteaError as exc:
                self.log(f"Could not load comments for #{number}: {exc}")
                return notified
            local_ids = store.local_comment_ids(number)
            fresh = comments[last_count:]
            external = [c for c in fresh if int(c.get("id", 0)) not in local_ids]
            if external:
                create_notification(
                    author_uid,
                    "issue",
                    f"New developer reply on your issue #{number}",
                    str(number),
                    f"/issues/{number}",
                )
                self._audit("issue.sync.reply", author_uid, number)
                notified += 1

        if state != last_status:
            verb = "closed" if state == "closed" else "reopened"
            create_notification(
                author_uid,
                "issue",
                f"Your issue #{number} was {verb}",
                str(number),
                f"/issues/{number}",
            )
            self._audit("issue.sync.status", author_uid, number, {"state": state})
            notified += 1

        store.update_ticket_cache(number, state, comment_count)
        return notified

    def _audit(
        self, event: str, author_uid: str, number: int, metadata: dict | None = None
    ) -> None:
        from devplacepy.services.audit import record as audit

        audit.record_system(
            event,
            actor_kind="service",
            target_type="issue",
            target_uid=str(number),
            metadata={"number": number, **(metadata or {})},
            summary=f"issue #{number} update detected",
            links=[audit.recipient(author_uid)],
        )
