"""
Utilitaires pour les opérations de base de données.

Ce module contient des fonctions helper pour convertir entre les modèles
Pydantic et les modèles SQLAlchemy.
"""

from datetime import datetime
from typing import List

from pipeline_mco_pmsi.database.models import (
    AuditRecordDB,
    ClinicalDocumentDB,
    ClinicalFactDB,
    CodeDB,
    EvidenceDB,
    GroupageResultDB,
    QuestionDB,
    ReferentielVersionDB,
    StayDB,
    TIMCorrectionDB,
    ValidationIssueDB,
    VerificationResultDB,
)
from pipeline_mco_pmsi.models.clinical import (
    ClinicalDocument,
    ClinicalFact,
    Evidence,
    Qualifier,
    Span,
)
from pipeline_mco_pmsi.models.coding import (
    Code,
    CodingProposal,
    DIMError,
    VerificationResult,
)
from pipeline_mco_pmsi.models.metadata import (
    AuditRecord,
    ReferentielVersion,
    StayMetadata,
    VersionInfo,
)
from pipeline_mco_pmsi.models.validation import (
    EligibilityCriteria,
    GroupageResult,
    Question,
    ValidationIssue,
)


def stay_metadata_to_db(stay: StayMetadata) -> StayDB:
    """Convertit StayMetadata en StayDB."""
    return StayDB(
        stay_id=stay.stay_id,
        admission_date=stay.admission_date,
        discharge_date=stay.discharge_date,
        specialty=stay.specialty,
        unit=stay.unit,
        age=stay.age,
        sex=stay.sex,
    )


def stay_db_to_metadata(stay_db: StayDB) -> StayMetadata:
    """Convertit StayDB en StayMetadata."""
    return StayMetadata(
        stay_id=stay_db.stay_id,
        admission_date=stay_db.admission_date,
        discharge_date=stay_db.discharge_date,
        specialty=stay_db.specialty,
        unit=stay_db.unit,
        age=stay_db.age,
        sex=stay_db.sex,
    )


def clinical_document_to_db(doc: ClinicalDocument, stay_db_id: int) -> ClinicalDocumentDB:
    """Convertit ClinicalDocument en ClinicalDocumentDB."""
    return ClinicalDocumentDB(
        document_id=doc.document_id,
        stay_id=stay_db_id,
        document_type=doc.document_type,
        content=doc.content,
        creation_date=doc.creation_date,
        author=doc.author,
        priority=doc.priority,
    )


def clinical_document_from_db(doc_db: ClinicalDocumentDB) -> ClinicalDocument:
    """Convertit ClinicalDocumentDB en ClinicalDocument."""
    return ClinicalDocument(
        document_id=doc_db.document_id,
        document_type=doc_db.document_type,
        content=doc_db.content,
        creation_date=doc_db.creation_date,
        author=doc_db.author,
        priority=doc_db.priority,
    )


def clinical_fact_to_db(fact: ClinicalFact, stay_db_id: int) -> ClinicalFactDB:
    """Convertit ClinicalFact en ClinicalFactDB."""
    return ClinicalFactDB(
        fact_id=fact.fact_id,
        stay_id=stay_db_id,
        type=fact.type,
        text=fact.text,
        qualifier_certainty=fact.qualifier.certainty,
        qualifier_markers=fact.qualifier.markers,
        qualifier_confidence=fact.qualifier.confidence,
        temporality=fact.temporality,
        confidence=fact.confidence,
        evidence_document_id=fact.evidence.document_id,
        evidence_span_start=fact.evidence.span.start,
        evidence_span_end=fact.evidence.span.end,
        evidence_text=fact.evidence.text,
        evidence_context=fact.evidence.context,
    )


def clinical_fact_from_db(fact_db: ClinicalFactDB) -> ClinicalFact:
    """Convertit ClinicalFactDB en ClinicalFact."""
    return ClinicalFact(
        fact_id=fact_db.fact_id,
        type=fact_db.type,
        text=fact_db.text,
        qualifier=Qualifier(
            certainty=fact_db.qualifier_certainty,
            markers=fact_db.qualifier_markers,
            confidence=fact_db.qualifier_confidence,
        ),
        temporality=fact_db.temporality,
        confidence=fact_db.confidence,
        evidence=Evidence(
            document_id=fact_db.evidence_document_id,
            span=Span(start=fact_db.evidence_span_start, end=fact_db.evidence_span_end),
            text=fact_db.evidence_text,
            context=fact_db.evidence_context,
        ),
    )


def code_to_db(code: Code, stay_db_id: int, model_version: VersionInfo) -> CodeDB:
    """Convertit Code en CodeDB."""
    return CodeDB(
        stay_id=stay_db_id,
        code=code.code,
        label=code.label,
        type=code.type,
        confidence=code.confidence,
        reasoning=code.reasoning,
        referentiel_version=code.referentiel_version,
        model_name=model_version.model_name,
        model_digest=model_version.model_digest,
        prompt_version=model_version.prompt_version,
        ccam_realization_date=None,  # À définir séparément si CCAM
    )


def code_from_db(code_db: CodeDB, evidences: List[Evidence]) -> Code:
    """Convertit CodeDB en Code."""
    return Code(
        code=code_db.code,
        label=code_db.label,
        type=code_db.type,
        evidence=evidences,
        confidence=code_db.confidence,
        reasoning=code_db.reasoning,
        referentiel_version=code_db.referentiel_version,
    )


def evidence_to_db(evidence: Evidence, code_db_id: int, document_db_id: int) -> EvidenceDB:
    """Convertit Evidence en EvidenceDB."""
    return EvidenceDB(
        code_id=code_db_id,
        document_id=document_db_id,
        span_start=evidence.span.start,
        span_end=evidence.span.end,
        text=evidence.text,
        context=evidence.context,
    )


def evidence_from_db(evidence_db: EvidenceDB) -> Evidence:
    """Convertit EvidenceDB en Evidence."""
    return Evidence(
        document_id=evidence_db.document.document_id,
        span=Span(start=evidence_db.span_start, end=evidence_db.span_end),
        text=evidence_db.text,
        context=evidence_db.context,
    )


def validation_issue_to_db(issue: ValidationIssue, stay_db_id: int) -> ValidationIssueDB:
    """Convertit ValidationIssue en ValidationIssueDB."""
    return ValidationIssueDB(
        issue_id=issue.issue_id,
        stay_id=stay_db_id,
        severity=issue.severity,
        category=issue.category,
        message=issue.message,
        affected_codes=issue.affected_codes,
        suggested_action=issue.suggested_action,
    )


def validation_issue_from_db(issue_db: ValidationIssueDB) -> ValidationIssue:
    """Convertit ValidationIssueDB en ValidationIssue."""
    return ValidationIssue(
        issue_id=issue_db.issue_id,
        severity=issue_db.severity,
        category=issue_db.category,
        message=issue_db.message,
        affected_codes=issue_db.affected_codes,
        suggested_action=issue_db.suggested_action,
    )


def question_to_db(question: Question, stay_db_id: int) -> QuestionDB:
    """Convertit Question en QuestionDB."""
    return QuestionDB(
        question_id=question.question_id,
        stay_id=stay_db_id,
        text=question.text,
        priority=question.priority,
        category=question.category,
        context=question.context,
        suggested_answers=question.suggested_answers,
    )


def question_from_db(question_db: QuestionDB) -> Question:
    """Convertit QuestionDB en Question."""
    return Question(
        question_id=question_db.question_id,
        text=question_db.text,
        priority=question_db.priority,
        category=question_db.category,
        context=question_db.context,
        suggested_answers=question_db.suggested_answers,
    )


def audit_record_to_db(record: AuditRecord, stay_db_id: int) -> AuditRecordDB:
    """Convertit AuditRecord en AuditRecordDB."""
    return AuditRecordDB(
        record_id=record.record_id,
        stay_id=stay_db_id,
        timestamp=record.timestamp,
        event_type=record.event_type,
        actor=record.actor,
        data=record.data,
        model_name=record.versions.model_name,
        model_digest=record.versions.model_digest,
        prompt_version=record.versions.prompt_version,
        prompt_hash=record.versions.prompt_hash,
        rules_version=record.versions.rules_version,
        rules_hash=record.versions.rules_hash,
        groupage_version=record.versions.groupage_version,
        referentiels_versions={
            k: {
                "type": v.type,
                "version": v.version,
                "file_hash": v.file_hash,
                "index_hash": v.index_hash,
            }
            for k, v in record.versions.referentiels.items()
        },
        inference_params=record.versions.inference_params,
    )


def audit_record_from_db(record_db: AuditRecordDB) -> AuditRecord:
    """Convertit AuditRecordDB en AuditRecord."""
    return AuditRecord(
        record_id=record_db.record_id,
        stay_id=str(record_db.stay_id),
        timestamp=record_db.timestamp,
        event_type=record_db.event_type,
        actor=record_db.actor,
        data=record_db.data,
        versions=VersionInfo(
            model_name=record_db.model_name,
            model_tag="",  # Non stocké en DB
            model_digest=record_db.model_digest,
            prompt_version=record_db.prompt_version,
            prompt_hash=record_db.prompt_hash,
            referentiels={
                k: ReferentielVersion(
                    type=v["type"],
                    version=v["version"],
                    import_date=datetime.utcnow(),  # Non stocké en DB
                    file_hash=v["file_hash"],
                    chunk_count=0,  # Non stocké en DB
                    index_hash=v["index_hash"],
                )
                for k, v in record_db.referentiels_versions.items()
            },
            rules_version=record_db.rules_version,
            rules_hash=record_db.rules_hash,
            groupage_version=record_db.groupage_version,
            inference_params=record_db.inference_params,
        ),
    )


def referentiel_version_to_db(ref: ReferentielVersion) -> ReferentielVersionDB:
    """Convertit ReferentielVersion en ReferentielVersionDB."""
    return ReferentielVersionDB(
        type=ref.type,
        version=ref.version,
        import_date=ref.import_date,
        file_hash=ref.file_hash,
        chunk_count=ref.chunk_count,
        index_hash=ref.index_hash,
    )


def referentiel_version_from_db(ref_db: ReferentielVersionDB) -> ReferentielVersion:
    """Convertit ReferentielVersionDB en ReferentielVersion."""
    return ReferentielVersion(
        type=ref_db.type,
        version=ref_db.version,
        import_date=ref_db.import_date,
        file_hash=ref_db.file_hash,
        chunk_count=ref_db.chunk_count,
        index_hash=ref_db.index_hash,
    )


def verification_result_to_db(result: VerificationResult, stay_db_id: int) -> VerificationResultDB:
    """Convertit VerificationResult en VerificationResultDB."""
    return VerificationResultDB(
        stay_id=stay_db_id,
        decision=result.decision,
        dim_errors=[
            {
                "error_type": err.error_type,
                "message": err.message,
                "affected_codes": err.affected_codes,
                "severity": err.severity,
            }
            for err in result.dim_errors
        ],
        contradictions=result.contradictions,
        alternatives=[
            {
                "code": alt.code,
                "label": alt.label,
                "type": alt.type,
                "confidence": alt.confidence,
            }
            for alt in result.alternatives
        ],
        reasoning=result.reasoning,
        model_name=result.model_version.model_name,
        model_digest=result.model_version.model_digest,
        prompt_version=result.prompt_version,
    )


def verification_result_from_db(result_db: VerificationResultDB) -> VerificationResult:
    """Convertit VerificationResultDB en VerificationResult."""
    from pipeline_mco_pmsi.models.metadata import ModelVersion

    return VerificationResult(
        stay_id=str(result_db.stay_id),
        decision=result_db.decision,
        dim_errors=[
            DIMError(
                error_type=err["error_type"],
                message=err["message"],
                affected_codes=err["affected_codes"],
                severity=err["severity"],
            )
            for err in result_db.dim_errors
        ],
        contradictions=result_db.contradictions,
        alternatives=[],  # Reconstruction complète nécessiterait plus de données
        reasoning=result_db.reasoning,
        model_version=ModelVersion(
            model_name=result_db.model_name,
            model_tag="",  # Non stocké
            model_digest=result_db.model_digest,
            quantization=None,
        ),
        prompt_version=result_db.prompt_version,
    )


def groupage_result_to_db(result: GroupageResult, stay_db_id: int) -> GroupageResultDB:
    """Convertit GroupageResult en GroupageResultDB."""
    return GroupageResultDB(
        stay_id=stay_db_id,
        ghm=result.ghm,
        ghs=result.ghs,
        groupage_errors=[
            {
                "issue_id": err.issue_id,
                "severity": err.severity,
                "category": err.category,
                "message": err.message,
            }
            for err in result.groupage_errors
        ],
        ccam_date_errors=result.ccam_date_errors,
        groupage_version=result.groupage_version,
        groupage_date=result.groupage_date,
    )


def groupage_result_from_db(result_db: GroupageResultDB) -> GroupageResult:
    """Convertit GroupageResultDB en GroupageResult."""
    return GroupageResult(
        stay_id=str(result_db.stay_id),
        ghm=result_db.ghm,
        ghs=result_db.ghs,
        groupage_errors=[
            ValidationIssue(
                issue_id=err["issue_id"],
                severity=err["severity"],
                category=err["category"],
                message=err["message"],
                affected_codes=[],
                suggested_action="",
            )
            for err in result_db.groupage_errors
        ],
        ccam_date_errors=result_db.ccam_date_errors,
        groupage_version=result_db.groupage_version,
        groupage_date=result_db.groupage_date,
    )
