"""Pydantic schemas for OpenAI Structured Outputs in comparative analysis.

These models define the strict LLM output contract that the synthesis engine
must produce. They are separate from the service-level validation models
in comparative_service.py, which govern the API response envelope.
"""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict, Field


class ComparativeServiceDiagnostics(BaseModel):
    """Service-level canonical diagnostics validation model."""

    total_documents: int
    total_chunks_used: int
    llm_provider: str
    llm_model: str
    top_k: int
    similarity_threshold: float
    parallel_tasks_executed: int


class Evidence(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})

    sumber_dokumen: str = Field(description="Judul asli artikel. DILARANG menuliskan tag XML.")
    kutipan_verbatim: str = Field(description="TEKS ASLI minimal 1-3 kalimat. DILARANG hanya menulis judul.")


class AnalisisPoin(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})

    aspek_konteks: str = Field(description="Aspek spesifik atau konteks relasi yang sedang dibahas (misal: 'Metodologi', 'Tujuan', atau relasi edge tertentu).")
    argumen_objektif: str = Field(description="Pernyataan netral dan analitis mendalam (5-10 kalimat deskriptif) mengenai persamaan atau perbedaan yang ditemukan.")
    bukti: list[Evidence] = Field(description="Kutipan langsung atau referensi spesifik dari dokumen beserta judulnya yang membuktikan argumen di atas.")


class PoinKritik(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})

    dokumen_sasaran: str = Field(description="Judul asli SATU artikel yang dikritik. DILARANG menuliskan tag XML.")
    aspek_yang_dikritik: str = Field(description="Aspek spesifik yang menjadi target kritik (contoh: 'Metodologi', 'Validitas Data', 'Bias Sampel').")
    celah_metodologis_atau_klaim: str = Field(description="Identifikasi spesifik mengenai bias, sampel yang lemah, anomali data, atau klaim yang tidak berdasar/overclaim.")
    dampak_kelemahan: str = Field(description="Penjelasan akademis mendalam (5-10 kalimat deskriptif) mengenai dampak dari celah tersebut terhadap validitas kesimpulan dokumen.")
    sumber_bukti: Evidence = Field(description="Kutipan langsung secara verbatim dari dokumen yang menjadi sasaran kritik sebagai bukti.")


class KonvergensiResponse(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})
    konvergensi: list[AnalisisPoin] = Field(description="Daftar titik temu atau kesepakatan antar dokumen yang didukung bukti. Kosongkan array jika murni tidak ada persamaan.")


class DivergensiResponse(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})
    divergensi: list[AnalisisPoin] = Field(description="Daftar pertentangan, perbedaan metode, atau percabangan hasil antar dokumen yang didukung bukti. Kosongkan array jika tidak ada perbedaan.")


class KritikResponse(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})
    kritik_akademis: list[PoinKritik] = Field(description="Evaluasi oposisi yang membongkar kelemahan masing-masing dokumen secara kritis (Devil's Advocate).")


class SintesisMakroResponse(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})
    sintesis_objektif: str = Field(description="Kesimpulan akhir yang netral dan terintegrasi dari seluruh analisis di atas.")


class KeterbatasanResponse(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})
    keterbatasan_analisis: str = Field(description="Pengakuan eksplisit mengenai apa yang TIDAK BISA disimpulkan karena data/teks dokumen tidak lengkap (Prinsip No Forced Fits).")


class AnalisisKomparatifResponse(BaseModel):
    model_config = ConfigDict(json_schema_extra={"additionalProperties": False})

    konvergensi: list[AnalisisPoin] = Field(description="Daftar titik temu atau kesepakatan antar dokumen yang didukung bukti. Kosongkan array jika murni tidak ada persamaan.")
    divergensi: list[AnalisisPoin] = Field(description="Daftar pertentangan, perbedaan metode, atau percabangan hasil antar dokumen yang didukung bukti. Kosongkan array jika tidak ada perbedaan.")
    kritik_akademis: list[PoinKritik] = Field(description="Evaluasi oposisi yang membongkar kelemahan masing-masing dokumen secara kritis (Devil's Advocate).")
    sintesis_objektif: str = Field(description="Kesimpulan akhir yang netral dan terintegrasi dari seluruh analisis di atas.")
    keterbatasan_analisis: str = Field(description="Pengakuan eksplisit mengenai apa yang TIDAK BISA disimpulkan karena data/teks dokumen tidak lengkap (Prinsip No Forced Fits).")
