"""
CASE Input Types

Pydantic models for CASE API request validation.
Mirrors the CASE v1.1 Zod schemas from the TypeScript SDK.
"""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field

from timeback_common import NonEmptyString  # noqa: TC001


class InputNodeURI(BaseModel):
    """Node URI reference for association endpoints."""

    title: NonEmptyString
    identifier: NonEmptyString
    uri: NonEmptyString


class CFDocumentInput(BaseModel):
    """Input model for a CASE Framework Document."""

    identifier: NonEmptyString
    uri: NonEmptyString
    last_change_date_time: NonEmptyString = Field(alias="lastChangeDateTime")
    title: NonEmptyString
    creator: NonEmptyString
    official_source_url: str | None = Field(None, alias="officialSourceURL")
    publisher: str | None = None
    description: str | None = None
    language: str | None = None
    version: str | None = None
    case_version: str | None = Field(None, alias="caseVersion")
    adoption_status: str | None = Field(None, alias="adoptionStatus")
    status_start_date: str | None = Field(None, alias="statusStartDate")
    status_end_date: str | None = Field(None, alias="statusEndDate")
    license_uri: str | None = Field(None, alias="licenseUri")
    notes: str | None = None
    subject: list[str] | None = None
    extensions: Any | None = None

    model_config = {"populate_by_name": True}


class CFItemInput(BaseModel):
    """Input model for a CASE Framework Item."""

    identifier: NonEmptyString
    uri: NonEmptyString
    last_change_date_time: NonEmptyString = Field(alias="lastChangeDateTime")
    full_statement: NonEmptyString = Field(alias="fullStatement")
    alternative_label: str | None = Field(None, alias="alternativeLabel")
    cf_item_type: str | None = Field(None, alias="CFItemType")
    cf_item_type_lower: str | None = Field(None, alias="cfItemType")
    human_coding_scheme: str | None = Field(None, alias="humanCodingScheme")
    list_enumeration: str | None = Field(None, alias="listEnumeration")
    abbreviated_statement: str | None = Field(None, alias="abbreviatedStatement")
    concept_keywords: list[str] | None = Field(None, alias="conceptKeywords")
    notes: str | None = None
    subject: list[str] | None = None
    language: str | None = None
    education_level: list[str] | None = Field(None, alias="educationLevel")
    cf_item_type_uri: Any | None = Field(None, alias="CFItemTypeURI")
    license_uri: Any | None = Field(None, alias="licenseURI")
    status_start_date: str | None = Field(None, alias="statusStartDate")
    status_end_date: str | None = Field(None, alias="statusEndDate")
    extensions: Any | None = None

    model_config = {"populate_by_name": True}


class CFAssociationInput(BaseModel):
    """Input model for a CASE Framework Association."""

    identifier: NonEmptyString
    uri: NonEmptyString
    last_change_date_time: NonEmptyString = Field(alias="lastChangeDateTime")
    association_type: NonEmptyString = Field(alias="associationType")
    origin_node_uri: InputNodeURI = Field(alias="originNodeURI")
    destination_node_uri: InputNodeURI = Field(alias="destinationNodeURI")
    sequence_number: int | None = Field(None, alias="sequenceNumber")
    extensions: Any | None = None

    model_config = {"populate_by_name": True}


class CFDefinitions(BaseModel):
    """Optional definitions within a CASE package."""

    cf_item_types: list[Any] | None = Field(None, alias="CFItemTypes")
    cf_subjects: list[Any] | None = Field(None, alias="CFSubjects")
    cf_concepts: list[Any] | None = Field(None, alias="CFConcepts")
    cf_licenses: list[Any] | None = Field(None, alias="CFLicenses")
    cf_association_groupings: list[Any] | None = Field(None, alias="CFAssociationGroupings")
    extensions: Any | None = None

    model_config = {"populate_by_name": True}


class CFPackageInput(BaseModel):
    """
    Input model for creating or replacing a CASE package.

    Validates the required structure:
    - CFDocument: document with required identifier, uri, title, creator, lastChangeDateTime
    - CFItems: array of items with required identifier, uri, fullStatement, lastChangeDateTime
    - CFAssociations: array of associations with required identifier, uri, associationType, nodes
    """

    cf_document: CFDocumentInput = Field(alias="CFDocument")
    cf_items: list[CFItemInput] = Field(alias="CFItems")
    cf_associations: list[CFAssociationInput] = Field(alias="CFAssociations")
    cf_definitions: CFDefinitions | None = Field(None, alias="CFDefinitions")
    extensions: Any | None = None

    model_config = {"populate_by_name": True}
