from contextlib import suppress
from functools import lru_cache

from fastapi import APIRouter, Header, HTTPException, Request

from maur.components import worker_tasks
from maur.linear.client import verify_webhook, post_comment
from maur.linear.schemas import LinearIssue, LinearWebhookPayload
from maur.linear.settings import LinearSettings
from maur.models import CodingTask
from maur.repos import CodingTaskRepoDep, DuplicateTaskError
from maur.worker import CodingTaskMessage


router = APIRouter()


@lru_cache
def linear_settings() -> LinearSettings:
    return LinearSettings.from_env()


@router.post("/webhook")
async def linear_webhook(
    request: Request,
    tasks: CodingTaskRepoDep,
    x_linear_signature: str = Header(default=""),
) -> dict[str, bool]:
    body = await request.body()
    settings = linear_settings()

    if not verify_webhook(
        settings.linear_webhook_secret.get_secret_value(),
        body,
        x_linear_signature,
    ):
        raise HTTPException(status_code=403, detail="Invalid signature")

    payload = LinearWebhookPayload.model_validate_json(body)

    if payload.type != "Issue" or payload.action not in ("create", "update"):
        return {"ok": True}

    issue = payload.issue
    if not isinstance(issue, LinearIssue):
        return {"ok": True}

    if settings.label_filter and settings.label_filter not in issue.label_names:
        return {"ok": True}

    prompt = settings.prompt_template.format(
        title=issue.title,
        description=issue.description or "",
    )

    with suppress(DuplicateTaskError):
        task = await tasks.insert(
            CodingTask(
                source="linear",
                source_id=issue.id,
                repo_branch=settings.repo_branch,
                prompt=prompt,
            )
        )
        await worker_tasks.publish(CodingTaskMessage(task_id=task.id))

        with suppress(Exception):
            await post_comment(
                settings.linear_api_key.get_secret_value(),
                issue.id,
                f"Maur agent picked up this issue. Task ID: `{task.id}`",
            )

    return {"ok": True}
