#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you under the Apache License, Version 2.0 (the
#  "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing,
#  software distributed under the License is distributed on an
#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#  KIND, either express or implied.  See the License for the
#  specific language governing permissions and limitations
#  under the License.

import json
from dataclasses import field, fields, is_dataclass
from typing import Any, Dict, Type, TypeVar, Union, List

T = TypeVar("T")


def json_field(json_name: str, **kwargs):
    """Create a field with custom JSON name"""
    return field(metadata={"json_name": json_name}, **kwargs)


class JSON:

    @staticmethod
    def to_json(obj: Any, **kwargs) -> str:
        """Convert to JSON string"""
        return json.dumps(JSON.__to_dict(obj), ensure_ascii=False, **kwargs)

    @staticmethod
    def from_json(json_str: str, target_class: Type[T]) -> T:
        """Create instance from JSON string"""
        data = json.loads(json_str)
        return JSON.__from_dict(data, target_class)

    @staticmethod
    def __to_dict(obj: Any) -> Dict[str, Any]:
        """Convert to dictionary with custom field names"""
        # If object has custom to_dict method, use it
        if hasattr(obj, "to_dict") and callable(getattr(obj, "to_dict")):
            return obj.to_dict()

        # Otherwise, use dataclass field-by-field serialization
        result = {}
        for field_info in fields(obj):
            field_value = getattr(obj, field_info.name)

            # Get custom JSON name from metadata
            json_name = field_info.metadata.get("json_name", field_info.name)

            # Handle nested objects
            if hasattr(field_value, "to_dict"):
                result[json_name] = field_value.to_dict()
            elif is_dataclass(field_value):
                result[json_name] = JSON.__to_dict(field_value)
            elif isinstance(field_value, list):
                result[json_name] = [
                    item.to_dict() if hasattr(item, "to_dict")
                    else JSON.__to_dict(item) if is_dataclass(item)
                    else item
                    for item in field_value
                ]
            else:
                result[json_name] = field_value

        return result

    @staticmethod
    def __from_dict(data: Dict[str, Any], target_class: Type[T]) -> T:
        """Create instance from dictionary"""
        # If target class has custom from_dict method, use it
        if hasattr(target_class, "from_dict") and callable(getattr(target_class, "from_dict")):
            return target_class.from_dict(data)

        # Otherwise, use dataclass field-by-field deserialization
        # Create field name mapping (json_name -> field_name)
        field_mapping = {}
        type_mapping = {}
        for field_info in fields(target_class):
            json_name = field_info.metadata.get("json_name", field_info.name)
            field_mapping[json_name] = field_info.name
            origin_type = getattr(field_info.type, '__origin__', None)
            args = getattr(field_info.type, '__args__', None)
            field_type = field_info.type
            if origin_type is Union and len(args) == 2:
                field_type = args[0]
            if is_dataclass(field_type):
                type_mapping[json_name] = field_type
            elif origin_type in (list, List) and is_dataclass(args[0]):
                type_mapping[json_name] = field_info.type

        # Map JSON data to field names
        kwargs = {}
        for json_name, value in data.items():
            if json_name in field_mapping:
                field_name = field_mapping[json_name]
                if json_name in type_mapping:
                    tp = getattr(type_mapping[json_name], '__origin__', None)
                    if tp in (list, List):
                        item_type = getattr(type_mapping[json_name], '__args__', None)[0]
                        if is_dataclass(item_type):
                            kwargs[field_name] = [
                                item_type.from_dict(item)
                                if hasattr(item_type, "to_dict")
                                else JSON.__from_dict(item, item_type)
                                for item in value]
                        else:
                            kwargs[field_name] = value
                    else:
                        kwargs[field_name] = JSON.__from_dict(value, type_mapping[json_name])
                else:
                    kwargs[field_name] = value

        return target_class(**kwargs)
