from __future__ import annotations

import textwrap
import typing
from typing import Annotated, Any, Literal

from pydantic import BaseModel, Field

if typing.TYPE_CHECKING:
    from pydantic.fields import FieldInfo


def Docstring(description: str) -> FieldInfo:
    """Shortcut for creating a description-only Field annotation."""
    description = textwrap.dedent(description).strip()
    return Field(description=description)


class Result(BaseModel):
    """A report generated by the analyzer."""

    count: Annotated[
        int,
        Docstring("The number of issues found in the manifest."),
    ]

    issues: Annotated[
        list[Issue],
        Docstring("A list of issues found in the manifest."),
    ]


class Issue(BaseModel):
    """An issue reported by the analyzer."""

    line: Annotated[
        int,
        Docstring(
            "Line number of the issue occurrence in the source file. The line number is cumulative across all documents in the YAML stream."
        ),
    ]

    column: Annotated[
        int,
        Docstring("Column number of the issue occurrence in the source file."),
    ]

    type: Annotated[
        Literal["error", "failure", "warning"],
        Docstring(
            """
            The type of the issue.
            * ``error`` indicates a critical issue that prevents the analyzer from running.
            * ``failure`` indicates an issue that the analyzer has detected.
            * ``warning`` indicates a potential issue that the analyzer has detected. This is not a critical issue, but it may require attention.
            """
        ),
    ]

    code: Annotated[
        str,
        Docstring("A unique identifier representing the violated rule."),
    ]

    manifest: Annotated[
        str | None,
        Docstring("The manifest name where the issue occurred."),
    ]

    loc: Annotated[
        tuple[str | int, ...],
        Docstring(
            """
            A list of keys indicating the location of the issue in the manifest.
            For example, a issue found in the `spec.containers[0].name` field would have a location of `["spec", "containers", 0, "name"]`.
            """
        ),
    ]

    summary: Annotated[
        str,
        Docstring("A short summary of the issue."),
    ]

    msg: Annotated[
        str,
        Docstring("A human-readable message describing the issue."),
    ]

    input: Annotated[
        str | int | bool | float | Any | None,
        Docstring("The input that caused the issue."),
    ]

    fix: Annotated[
        str | None,
        Docstring(
            """
            A possible fix to the issue.
            This output is based on the analyzer's best guess and may not be correct.
            """
        ),
    ]
