from __future__ import annotations

import re

from auraindex.models import ParsedQueryFeatures

_SELECT_STAR_PATTERN = re.compile(r"^\s*select\s+\*", re.IGNORECASE)
_ORDER_BY_PATTERN = re.compile(r"\border\s+by\b", re.IGNORECASE)
_LIMIT_PATTERN = re.compile(r"\blimit\b", re.IGNORECASE)
_LEADING_WILDCARD_LIKE_PATTERN = re.compile(r"\blike\s+['\"]%[^'\"]*['\"]", re.IGNORECASE)


def analyze_query_advisories(
    parsed_queries: list[ParsedQueryFeatures],
    *,
    max_items: int = 120,
) -> list[dict[str, object]]:
    advisories: list[dict[str, object]] = []
    seen: set[tuple[str, int, str]] = set()

    for parsed in parsed_queries:
        sql_text = parsed.query.sql
        context = parsed.query.context
        statement_kind = parsed.statement_kind
        if statement_kind != "select":
            continue

        candidate_advisories = []
        if _SELECT_STAR_PATTERN.search(sql_text):
            candidate_advisories.append(
                (
                    "select_star",
                    "medium",
                    "Avoid SELECT * in production paths; project only required columns to reduce IO and row width.",
                )
            )

        if _ORDER_BY_PATTERN.search(sql_text) and not _LIMIT_PATTERN.search(sql_text):
            candidate_advisories.append(
                (
                    "order_by_without_limit",
                    "medium",
                    "ORDER BY without LIMIT can force large sorts; add LIMIT/pagination where possible.",
                )
            )

        if _LEADING_WILDCARD_LIKE_PATTERN.search(sql_text):
            candidate_advisories.append(
                (
                    "leading_wildcard_like",
                    "high",
                    "Leading wildcard LIKE pattern disables normal index seeks; consider trigram/full-text index strategy.",
                )
            )

        for rule_id, severity, message in candidate_advisories:
            dedupe_key = (context.file_path, context.line, rule_id)
            if dedupe_key in seen:
                continue
            seen.add(dedupe_key)
            advisories.append(
                {
                    "rule_id": rule_id,
                    "severity": severity,
                    "message": message,
                    "file_path": context.file_path,
                    "line": context.line,
                    "source_kind": context.source_kind,
                    "sql_excerpt": sql_text[:320],
                }
            )
            if len(advisories) >= max(1, max_items):
                return advisories

    return advisories
