#  Copyright (C) 2026
#  ABM, Moscow
#
#  UNPUBLISHED PROPRIETARY MATERIAL.
#  ALL RIGHTS RESERVED.
#
#  Authors: Mike Orlov <m.orlov@abm-jsc.ru>
import dataclasses

from .._hint import StructureHint, FieldHint
from .._type import get_name_from_type

DEFAULT_REQUIRED_VALUE_PLACEHOLDER = 'REQUIRED'
DEFAULT_DYNAMIC_VALUE_PLACEHOLDER = '...'


def make_ini_from_hint(
        hint: StructureHint,
        *,
        depth: int = 0,
        add_optional: bool = True,
        required_value_placeholder: str = DEFAULT_REQUIRED_VALUE_PLACEHOLDER,
        dynamic_value_placeholder: str = DEFAULT_DYNAMIC_VALUE_PLACEHOLDER,
) -> str:
    section_name_to_lines: dict[str, list[str]] = {}
    section: list[str] | None = None
    for f in hint.fields:
        if isinstance(f, FieldHint):
            section = section or section_name_to_lines.setdefault('', [])
            type_repr = get_name_from_type(f.type)
            if f.default is dataclasses.MISSING:
                section.append(f'; {f.name}: {type_repr}')
                section.append(f'{f.name} = {required_value_placeholder}')
            elif add_optional:
                pass
                if callable(f.default):
                    default_str = f', default={f.default.__module__}.{f.default.__qualname__}'
                    section.append(f'; {f.name} = {dynamic_value_placeholder} ; {type_repr}{default_str}')
                else:
                    section.append(f'; {f.name} = {f.default} ; {type_repr}')
        elif isinstance(f, StructureHint):
            if depth:
                raise ValueError(f"INI format does not support more than one nesting level, got at least two: {f.name}")
            section_name_to_lines[f.name] = [make_ini_from_hint(
                f, depth=depth + 1, add_optional=add_optional, required_value_placeholder=required_value_placeholder,
                dynamic_value_placeholder=dynamic_value_placeholder
            )]
        else:
            raise TypeError(f"unexpected type: {type(f).__qualname__}")

    blocks = []
    if non_section_lines := section_name_to_lines.pop('', []):
        blocks.append('\n'.join(non_section_lines))
    for section_name, lines in section_name_to_lines.items():
        blocks.append(f'[{section_name}]\n' + ('\n'.join(lines)))
    return '\n\n'.join(blocks)
