"""Lightweight shared generation configuration.

This module is intentionally kept smaller than ``config.py`` so the CLI can
validate command-line options without importing parser/model configuration
classes that are only needed once generation starts.
"""

from __future__ import annotations

from collections.abc import Sequence  # noqa: TC003 - used at runtime by Pydantic
from pathlib import Path  # noqa: TC003 - used at runtime by Pydantic
from typing import TYPE_CHECKING, TypeAlias

from pydantic import BaseModel, ConfigDict, model_validator
from typing_extensions import Self

from datamodel_code_generator._format_types import (
    DateClassType,
    DatetimeClassType,
    Formatter,
    PythonVersion,
    PythonVersionMin,
)
from datamodel_code_generator.enums import (
    DEFAULT_SHARED_MODULE_NAME,
    AliasGenerator,
    AllExportsCollisionStrategy,
    AllExportsScope,
    AllOfClassHierarchy,
    AllOfMergeMode,
    ClassNameAffixScope,
    CollapseRootModelsNameStrategy,
    DataclassArguments,
    DataModelType,
    FieldTypeCollisionStrategy,
    InputFileType,
    ModuleSplitMode,
    NamingStrategy,
    ReadOnlyWriteOnlyModelType,
    ReuseScope,
    SchemaValidatorType,
    TargetPydanticVersion,
    UnionMode,
    VersionMode,
)
from datamodel_code_generator.parser import LiteralType  # noqa: TC001 - used at runtime by Pydantic

if TYPE_CHECKING:
    from datamodel_code_generator.preset_names import PresetName as PresetNameValue
else:
    PresetNameValue: TypeAlias = str


class BaseGenerateConfig(BaseModel):
    """Shared generation configuration fields."""

    model_config = ConfigDict(
        extra="forbid",
        arbitrary_types_allowed=True,
        protected_namespaces=(),
        defer_build=True,
    )

    input_file_type: InputFileType = InputFileType.Auto
    output: Path | None = None
    emit_model_metadata: Path | None = None
    output_model_type: DataModelType = DataModelType.PydanticV2BaseModel
    preset: PresetNameValue | None = None
    target_python_version: PythonVersion = PythonVersionMin
    target_pydantic_version: TargetPydanticVersion | None = None
    base_class: str = ""
    base_class_map: dict[str, str | list[str]] | None = None
    model_name_map: dict[str, str] | None = None
    additional_imports: list[str] | None = None
    class_decorators: list[str] | None = None
    custom_template_dir: Path | None = None
    schema_validator_type: SchemaValidatorType | None = None
    generate_schema_validators: bool = False
    schema_validator_base_class_name: str | None = None
    validation: bool = False
    field_constraints: bool = False
    alias_generator: AliasGenerator | None = None
    snake_case_field: bool = False
    strip_default_none: bool = False
    disable_timestamp: bool = False
    enable_version_header: bool = False
    enable_command_header: bool = False
    enable_generated_header_marker: bool = False
    allow_population_by_field_name: bool = False
    allow_extra_fields: bool = False
    extra_fields: str | None = None
    use_generic_base_class: bool = False
    class_name: str | None = None
    allow_leading_underscore_class_name: bool = False
    class_name_prefix: str | None = None
    class_name_suffix: str | None = None
    class_name_affix_scope: ClassNameAffixScope = ClassNameAffixScope.All
    use_standard_collections: bool = True
    use_schema_description: bool = False
    use_field_description: bool = False
    use_field_description_example: bool = False
    use_attribute_docstrings: bool = False
    use_inline_field_description: bool = False
    use_single_line_docstring: bool = False
    use_default_kwarg: bool = False
    use_missing_sentinel: bool = False
    reuse_model: bool = False
    reuse_scope: ReuseScope = ReuseScope.Module
    shared_module_name: str = DEFAULT_SHARED_MODULE_NAME
    encoding: str = "utf-8"
    enum_field_as_literal: LiteralType | None = None
    enum_field_as_literal_map: dict[str, str] | None = None
    ignore_enum_constraints: bool = False
    use_one_literal_as_default: bool = False
    use_enum_values_in_discriminator: bool = False
    set_default_enum_member: bool = False
    use_subclass_enum: bool = False
    use_specialized_enum: bool = True
    strict_nullable: bool = False
    use_generic_container_types: bool = False
    enable_faux_immutability: bool = False
    disable_appending_item_suffix: bool = False
    empty_enum_field_name: str | None = None
    field_extra_keys: set[str] | None = None
    field_include_all_keys: bool = False
    field_extra_keys_without_x_prefix: set[str] | None = None
    model_extra_keys: set[str] | None = None
    model_extra_keys_without_x_prefix: set[str] | None = None
    include_path_parameters: bool = False
    openapi_include_paths: list[str] | None = None
    openapi_include_info_version: bool = False
    graphql_no_typename: bool = False
    wrap_string_literal: bool | None = None
    use_title_as_name: bool = False
    infer_union_variant_names: bool = False
    use_operation_id_as_name: bool = False
    use_unique_items_as_set: bool = False
    use_tuple_for_fixed_items: bool = False
    use_closed_typed_dict: bool = True
    allof_merge_mode: AllOfMergeMode = AllOfMergeMode.Constraints
    allof_class_hierarchy: AllOfClassHierarchy = AllOfClassHierarchy.IfNoConflict
    allow_remote_refs: bool | None = None
    allow_private_network: bool = False
    http_headers: Sequence[tuple[str, str]] | None = None
    http_local_ref_path: Path | None = None
    http_ignore_tls: bool = False
    http_timeout: float | None = None
    use_annotated: bool = False
    use_serialize_as_any: bool = False
    use_non_positive_negative_number_constrained_types: bool = False
    use_decimal_for_multiple_of: bool = False
    original_field_name_delimiter: str | None = None
    use_double_quotes: bool = False
    use_union_operator: bool = True
    collapse_root_models: bool = False
    collapse_root_models_name_strategy: CollapseRootModelsNameStrategy | None = None
    collapse_reuse_models: bool = False
    skip_root_model: bool = False
    use_root_model_sequence_interface: bool = False
    use_type_alias: bool = False
    use_root_model_type_alias: bool = False
    special_field_name_prefix: str | None = None
    remove_special_field_name_prefix: bool = False
    capitalise_enum_members: bool = False
    keep_model_order: bool = False
    custom_file_header: str | None = None
    custom_file_header_path: Path | None = None
    custom_formatters: list[str] | None = None
    use_pendulum: bool = False
    use_standard_primitive_types: bool = False
    use_object_type: bool = False
    http_query_parameters: Sequence[tuple[str, str]] | None = None
    treat_dot_as_module: bool | None = None
    use_exact_imports: bool = False
    use_type_checking_imports: bool | None = None
    union_mode: UnionMode | None = None
    output_datetime_class: DatetimeClassType | None = None
    output_date_class: DateClassType | None = None
    keyword_only: bool = False
    frozen_dataclasses: bool = False
    no_alias: bool = False
    use_serialization_alias: bool = False
    use_frozen_field: bool = False
    use_default_factory_for_optional_nested_models: bool = False
    formatters: list[Formatter] | None = None
    builtin_format_line_length: int | None = None
    parent_scoped_naming: bool = False
    naming_strategy: NamingStrategy | None = None
    duplicate_name_suffix: dict[str, str] | None = None
    dataclass_arguments: DataclassArguments | None = None
    disable_future_imports: bool = False
    type_mappings: list[str] | None = None
    type_overrides: dict[str, str] | None = None
    read_only_write_only_model_type: ReadOnlyWriteOnlyModelType | None = None
    use_status_code_in_response_name: bool = False
    all_exports_scope: AllExportsScope | None = None
    all_exports_collision_strategy: AllExportsCollisionStrategy | None = None
    field_type_collision_strategy: FieldTypeCollisionStrategy | None = None
    module_split_mode: ModuleSplitMode | None = None
    schema_version: str | None = None
    schema_version_mode: VersionMode | None = None
    external_ref_mapping: dict[str, str] | None = None

    @model_validator(mode="after")
    def normalize_schema_validator_type(self) -> Self:
        """Keep the legacy boolean flag and explicit backend selection in sync."""
        if self.generate_schema_validators and self.schema_validator_type is None:
            self.schema_validator_type = SchemaValidatorType.PydanticV2
        if self.schema_validator_type is not None:
            self.generate_schema_validators = True
        return self


__all__ = ["BaseGenerateConfig"]
