from typing import Any, List

from llm_compact_serializer.domain.schema import CompactSchema, FieldConfig


class DynamicSerializer:
    def __init__(self, root_schema: CompactSchema):
        self.root_schema = root_schema

    def _get_value(self, obj: Any, field_name: str) -> Any:
        if isinstance(obj, dict):
            return obj.get(field_name)
        return getattr(obj, field_name, None)

    def _sanitize_primitive(self, value: Any, default: str) -> str:
        """Handles simple strings, numbers, booleans."""
        if value is None:
            return default
        str_val = str(value).strip()
        if str_val == "":
            return default
        # Escape commas as they are separators
        if "," in str_val:
            str_val = str_val.replace(",", " ")
        return str_val

    def _serialize_recursive(self, obj: Any, schema: CompactSchema) -> str:
        """
        Recursive function that builds the |{ val, val, |{val}| }| string.
        """
        if obj is None:
            return "-"

        values = []
        for field in schema.fields:
            raw_val = self._get_value(obj, field.source_name)

            # CASE A: List of items
            if field.is_list:
                if not raw_val:
                    values.append("[]")
                else:
                    clean_list = [self._sanitize_primitive(v, "-") for v in raw_val]
                    values.append(f"[{', '.join(clean_list)}]")

            # CASE B: Nested Complex Object
            elif field.nested_schema:
                nested_str = self._serialize_recursive(raw_val, field.nested_schema)
                values.append(nested_str)

            # CASE C: Primitive
            else:
                values.append(self._sanitize_primitive(raw_val, field.default_value))

        # --- FIX IS HERE ---
        # Previous: return f"|{{{', '.join(values)}}}"  -> produced |{...}
        # Correct:  return f"|{{{', '.join(values)}}}|" -> produces |{...}|
        return f"|{{{', '.join(values)}}}|"

    def serialize(self, objects: List[Any]) -> str:
        if not objects:
            return ""
        # Map over the list of root objects
        items = [self._serialize_recursive(obj, self.root_schema) for obj in objects]
        return ";".join(items)
