# retoor <retoor@molodetz.nl>

from .._shared import endpoint, field

GROUP = {
        "slug": "issues",
        "title": "Issue Reports",
        "intro": """
# Issue Reports

The issue tracker is a full integration with a Gitea repository. The listing and detail views read
issues straight from Gitea with their live status, and a report you file is first rewritten by the
internal AI service into a consistent ticket, then posted to Gitea as an issue. The original
reporter is notified when a developer replies or the status changes, and a comment posted here is
pushed to Gitea and attributed to your account.

Every endpoint follows the shared [Conventions & Errors](/docs/conventions.html) (auth, content
negotiation, pagination, status codes); see [Authentication](/docs/authentication.html) for the
four ways to sign requests.
""",
        "endpoints": [
            endpoint(
                id="issues-list",
                method="GET",
                path="/issues",
                title="List issue tickets",
                summary="Render the issue board from Gitea, paginated and filterable by state.",
                auth="public",
                interactive=True,
                params=[
                    field(
                        "state",
                        "query",
                        "string",
                        False,
                        "open",
                        "Filter: open (default), closed, or all.",
                    ),
                    field("page", "query", "integer", False, "1", "1-based page."),
                ],
            ),
            endpoint(
                id="issues-create",
                method="POST",
                path="/issues/create",
                title="Report an issue",
                summary="Enqueue an issue report. It is enhanced by AI and filed on the tracker.",
                auth="user",
                encoding="form",
                ajax=True,
                destructive=True,
                params=[
                    field(
                        "title",
                        "form",
                        "string",
                        True,
                        "Login button misaligned",
                        "Title, 1-200 characters.",
                    ),
                    field(
                        "description",
                        "form",
                        "textarea",
                        True,
                        "Steps to reproduce...",
                        "Description, 1-5000 characters.",
                    ),
                ],
                notes=["Returns a job uid and status_url. Poll the status_url until status is done to get the issue number."],
                sample_response={
                    "uid": "JOB_UID",
                    "status_url": "/issues/jobs/JOB_UID",
                },
            ),
            endpoint(
                id="issues-job",
                method="GET",
                path="/issues/jobs/{uid}",
                title="Issue filing job status",
                summary="Poll the filing job; the result carries the new issue number and url.",
                auth="public",
                ajax=True,
                params=[field("uid", "path", "string", True, "JOB_UID", "Job uid.")],
                sample_response={
                    "uid": "JOB_UID",
                    "kind": "issue_create",
                    "status": "done",
                    "number": 42,
                    "issue_url": "/issues/42",
                    "enhanced": True,
                    "error": None,
                    "created_at": "2026-06-12T09:00:00+00:00",
                    "completed_at": "2026-06-12T09:00:03+00:00",
                },
            ),
            endpoint(
                id="issues-planning-queue",
                method="POST",
                path="/issues/planning",
                title="Generate a tickets planning report",
                summary="Enqueue a phased markdown implementation document for open tickets, with each ticket's full description reproduced verbatim (inline plus a Source Tickets appendix) alongside implementation steps and acceptance criteria. Admin only.",
                auth="admin",
                encoding="form",
                ajax=True,
                params=[field("numbers", "form", "string", False, "1,4,7", "Comma-separated issue numbers to include. Omit to plan every open ticket.")],
                notes=["Returns a job uid and status_url. Poll the status_url until status is done to read the markdown and download it.", "Provide 'numbers' to plan only a chosen subset of open tickets; omitting it plans all open tickets."],
                sample_response={
                    "uid": "PLANNING_JOB_UID",
                    "status_url": "/issues/planning/PLANNING_JOB_UID",
                },
            ),
            endpoint(
                id="issues-planning-status",
                method="GET",
                path="/issues/planning/{uid}",
                title="Planning report job status",
                summary="Poll the planning job; the result carries the rendered markdown and the download URL. Admin only.",
                auth="admin",
                ajax=True,
                params=[field("uid", "path", "string", True, "PLANNING_JOB_UID", "Planning job uid.")],
                sample_response={
                    "uid": "PLANNING_JOB_UID",
                    "kind": "planning",
                    "status": "done",
                    "download_url": "/issues/planning/PLANNING_JOB_UID/download",
                    "markdown": "# Open Tickets Implementation Plan\n\n...",
                    "ai_used": True,
                    "issue_count": 12,
                    "bytes_out": 4096,
                    "error": None,
                    "created_at": "2026-06-15T09:00:00+00:00",
                    "completed_at": "2026-06-15T09:00:05+00:00",
                },
            ),
            endpoint(
                id="issues-planning-download",
                method="GET",
                path="/issues/planning/{uid}/download",
                title="Download the planning report",
                summary="Download the generated planning report as a markdown file. Admin only.",
                auth="admin",
                interactive=True,
                params=[field("uid", "path", "string", True, "PLANNING_JOB_UID", "Planning job uid.")],
            ),
            endpoint(
                id="issues-detail",
                method="GET",
                path="/issues/{number}",
                title="View an issue ticket",
                summary="Render a Gitea issue and its comments. Returns an HTML page.",
                auth="public",
                interactive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number.")
                ],
            ),
            endpoint(
                id="issues-comment",
                method="POST",
                path="/issues/{number}/comment",
                title="Comment on an issue",
                summary="Post a comment to the Gitea issue, attributed to the current user.",
                auth="user",
                encoding="form",
                destructive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                    field(
                        "body",
                        "form",
                        "textarea",
                        True,
                        "I can reproduce this on mobile.",
                        "Comment, 1-5000 characters.",
                    ),
                ],
            ),
            endpoint(
                id="issues-status",
                method="POST",
                path="/issues/{number}/status",
                title="Change an issue status",
                summary="Open or close the Gitea issue. Admin only.",
                auth="admin",
                encoding="form",
                destructive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                    field(
                        "status",
                        "form",
                        "string",
                        True,
                        "closed",
                        "New status: open or closed.",
                    ),
                ],
            ),
            endpoint(
                id="issues-attachments-list",
                method="GET",
                path="/issues/{number}/attachments",
                title="List issue attachments",
                summary="Return the files attached to an issue ticket.",
                auth="public",
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                ],
            ),
            endpoint(
                id="issues-attachments-add",
                method="POST",
                path="/issues/{number}/attachments",
                title="Attach files to an issue",
                summary=(
                    "Link already-uploaded files (from /uploads/upload) to an open issue. The "
                    "files are also mirrored to the Gitea tracker. Allowed only while the issue is open."
                ),
                auth="user",
                encoding="form",
                destructive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                    field(
                        "attachment_uids",
                        "form",
                        "string",
                        True,
                        "a1b2c3d4,e5f6g7h8",
                        "Comma separated attachment uids returned by /uploads/upload.",
                    ),
                ],
                notes=[
                    "Only the open issue accepts changes; a closed issue returns 409.",
                    "You can only link your own uploads unless you are an administrator.",
                ],
            ),
            endpoint(
                id="issues-attachments-delete",
                method="DELETE",
                path="/issues/{number}/attachments/{uid}",
                title="Delete an issue attachment",
                summary=(
                    "Soft-delete a file from an open issue (owner or administrator) and remove it "
                    "from the tracker."
                ),
                auth="user",
                destructive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                    field("uid", "path", "string", True, "a1b2c3d4", "Attachment uid."),
                ],
            ),
            endpoint(
                id="issues-comment-attachments-add",
                method="POST",
                path="/issues/{number}/comments/{cid}/attachments",
                title="Attach files to an issue comment",
                summary=(
                    "Link already-uploaded files to an issue comment (issue must be open). Mirrored "
                    "to the Gitea comment."
                ),
                auth="user",
                encoding="form",
                destructive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                    field("cid", "path", "integer", True, "1", "Gitea comment id."),
                    field(
                        "attachment_uids",
                        "form",
                        "string",
                        True,
                        "a1b2c3d4",
                        "Comma separated attachment uids returned by /uploads/upload.",
                    ),
                ],
            ),
            endpoint(
                id="issues-comment-attachments-delete",
                method="DELETE",
                path="/issues/{number}/comments/{cid}/attachments/{uid}",
                title="Delete an issue comment attachment",
                summary=(
                    "Soft-delete a file from an issue comment (owner or administrator) and remove it "
                    "from the tracker."
                ),
                auth="user",
                destructive=True,
                params=[
                    field("number", "path", "integer", True, "12", "Issue number."),
                    field("cid", "path", "integer", True, "1", "Gitea comment id."),
                    field("uid", "path", "string", True, "a1b2c3d4", "Attachment uid."),
                ],
            ),
        ],
}
