"""Pydantic schemas для insight (#948 Part A, ТЗ §7.13/§8.9).

InsightCreate  — тело POST-запроса (title/body обязательны).
InsightUpdate  — тело PUT-запроса (все поля опциональны — partial update).
InsightOut     — ответ API (включает id, created_by, created_at, updated_at).

created_by НЕ принимается из тела — проставляется роутером из X-Authenticated-User.
"""

from __future__ import annotations

from datetime import datetime
from typing import Literal

from pydantic import BaseModel, Field

# Рекомендованные категории (мягкий enum, совпадает с CHECK ck_insight_category
# в data/sql/145_insight.sql). None допустим.
InsightCategory = Literal["competition", "permitting", "demand", "risk", "other"]


class InsightCreate(BaseModel):
    title: str = Field(..., min_length=1, max_length=300, description="Заголовок заметки")
    body: str = Field(..., min_length=1, max_length=20000, description="Тело заметки (intel)")
    category: InsightCategory | None = Field(
        None, description="Категория: competition|permitting|demand|risk|other"
    )
    is_confidential: bool = Field(
        False, description="«Непублично» (§7.13): маркировка чувствительной заметки"
    )
    district: str | None = Field(
        None,
        max_length=200,
        description="Location ref (район); Part B промоутит в Location FK",
    )
    cad_num: str | None = Field(
        None, max_length=100, description="Опциональный кадастровый номер участка"
    )
    lon: float | None = Field(None, ge=-180.0, le=180.0, description="Долгота WGS-84 (map-pin)")
    lat: float | None = Field(None, ge=-90.0, le=90.0, description="Широта WGS-84 (map-pin)")
    source: str | None = Field(None, max_length=500, description="Источник intel")


class InsightUpdate(BaseModel):
    """Partial update (PUT) — переданные поля заменяются, отсутствующие не трогаются."""

    title: str | None = Field(None, min_length=1, max_length=300)
    body: str | None = Field(None, min_length=1, max_length=20000)
    category: InsightCategory | None = None
    is_confidential: bool | None = None
    district: str | None = Field(None, max_length=200)
    cad_num: str | None = Field(None, max_length=100)
    lon: float | None = Field(None, ge=-180.0, le=180.0)
    lat: float | None = Field(None, ge=-90.0, le=90.0)
    source: str | None = Field(None, max_length=500)


class InsightOut(BaseModel):
    id: int
    created_by: str
    title: str
    body: str
    category: str | None
    is_confidential: bool
    district: str | None
    cad_num: str | None
    lon: float | None
    lat: float | None
    source: str | None
    created_at: datetime
    updated_at: datetime


class InsightList(BaseModel):
    """Ответ list-эндпоинта: total + страница строк (как admin_leads)."""

    total: int
    limit: int
    offset: int
    rows: list[InsightOut]
