// deepcopy makes deep copies of things. A standard copy will copy the
// pointers: deep copy copies the values pointed to.  Unexported field
// values are not copied.
//
// Copyright (c)2014-2016, Joel Scoble (github.com/mohae), all rights reserved.
// License: MIT, for more details check the included LICENSE file.
package deepcopy

import (
	"errors"
	"reflect"
	"time"
)

// copyContext 用于追踪已复制的对象，避免循环引用
type copyContext struct {
	seen map[uintptr]reflect.Value
	deep int
}

// Interface for delegating copy process to type
type DeepCopyer interface {
	DeepCopy() interface{}
}

// Copy creates a deep copy of whatever is passed to it and returns the copy
// in an interface{}.  The returned value will need to be asserted to the
// correct type.
// 支持以下类型的复制：
//   - 简单类型（int, string 等）
//   - 时间类型 (time.Time)
//   - 复合类型（map, slice, array）
//   - 指针类型
//   - 结构体（包含匿名字段）
//
// 特性：
//   - 支持循环引用检测
//   - 未导出字段不会被复制
//   - 实现了 DeepCopyer 接口的类型可以自定义复制行为
//   - 不支持的类型（Channel、Function等）会被跳过，不影响其他数据的复制
//
// 限制：
//   - 递归深度限制为20层
//   - 不支持的类型（Channel、Function等）会被跳过不处理
func Copy(src interface{}) (interface{}, error) {
	if src == nil {
		return nil, nil
	}

	// Make the interface a reflect.Value
	original := reflect.ValueOf(src)

	// Make a copy of the same type as the original.
	cpy := reflect.New(original.Type()).Elem()

	// Create a new context for tracking copied objects
	ctx := &copyContext{
		seen: make(map[uintptr]reflect.Value),
		deep: 0,
	}

	// Recursively copy the original.
	if err := copyRecursive(ctx, original, cpy); err != nil {
		return nil, err
	}

	// Return the copy as an interface.
	return cpy.Interface(), nil
}

func MustCopy(src interface{}) interface{} {
	val, err := Copy(src)
	if err != nil {
		panic(err)
	}
	return val
}

// isUnsupportedType checks if the given type is unsupported for deep copy
func isUnsupportedType(k reflect.Kind) bool {
	switch k {
	case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Invalid:
		return true
	}
	return false
}

// copyRecursive does the actual copying of the interface.
// 支持的类型：
//   - 简单类型
//   - 时间类型 (time.Time)
//   - map, slice, array
//   - 指针
//   - 结构体及其匿名字段
//
// 特性：
//   - 使用 copyContext 处理循环引用
//   - 未导出字段会被跳过
//   - 支持 noCopy 标记的结构体
//   - 不支持的类型会被跳过不处理
//
// 参数：
//   - ctx: 复制上下文，用于追踪已复制的对象
//   - original: 原始值
//   - cpy: 目标值（指针的解引用）
func copyRecursive(ctx *copyContext, original, cpy reflect.Value) error {
	ctx.deep++
	if ctx.deep > 20 {
		return errors.New("max recursion depth exceeded")
	}
	defer func() { ctx.deep-- }()

	// Handle nil pointer
	if !original.IsValid() {
		return nil
	}

	// 对不支持的类型直接跳过
	if isUnsupportedType(original.Kind()) {
		return nil
	}

	// Check for circular references
	if original.Kind() == reflect.Ptr || original.Kind() == reflect.Interface {
		if original.Kind() == reflect.Ptr {
			ptr := original.Pointer()
			if copied, ok := ctx.seen[ptr]; ok {
				cpy.Set(copied)
				return nil
			}
			if !original.IsNil() {
				ctx.seen[ptr] = cpy
			}
		}
	}

	// check for implement deepcopy.Interface
	if original.CanInterface() {
		if copier, ok := original.Interface().(DeepCopyer); ok {
			cpy.Set(reflect.ValueOf(copier.DeepCopy()))
			return nil
		}
	}

	var err error
	switch original.Kind() {
	case reflect.Ptr:
		originalValue := original.Elem()
		if !originalValue.IsValid() {
			return nil
		}
		cpy.Set(reflect.New(originalValue.Type()))
		err = copyRecursive(ctx, originalValue, cpy.Elem())

	case reflect.Interface:
		if original.IsNil() {
			return nil
		}
		originalValue := original.Elem()
		copyValue := reflect.New(originalValue.Type()).Elem()
		err = copyRecursive(ctx, originalValue, copyValue)
		if err == nil {
			cpy.Set(copyValue)
		}

	case reflect.Struct:
		t, ok := original.Interface().(time.Time)
		if ok {
			cpy.Set(reflect.ValueOf(t))
			return nil
		}
		oriType := original.Type()
		if _, ok := oriType.FieldByName("noCopy"); ok {
			return nil
		}
		for i := 0; i < original.NumField(); i++ {
			if !oriType.Field(i).IsExported() {
				continue
			}

			err = copyRecursive(ctx, original.Field(i), cpy.Field(i))
			if err != nil {
				// 忽略不支持类型的错误
				continue
			}
		}

	case reflect.Slice:
		if original.IsNil() {
			return nil
		}
		cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
		for i := 0; i < original.Len(); i++ {
			err = copyRecursive(ctx, original.Index(i), cpy.Index(i))
			if err != nil {
				// 忽略不支持类型的错误
				continue
			}
		}

	case reflect.Map:
		if original.IsNil() {
			return nil
		}
		cpy.Set(reflect.MakeMap(original.Type()))
		for _, key := range original.MapKeys() {
			originalValue := original.MapIndex(key)
			copyValue := reflect.New(originalValue.Type()).Elem()
			err = copyRecursive(ctx, originalValue, copyValue)
			if err != nil {
				// 忽略不支持类型的错误
				continue
			}

			copyKey := reflect.New(key.Type()).Elem()
			err = copyRecursive(ctx, key, copyKey)
			if err != nil {
				// 忽略不支持类型的错误
				continue
			}
			cpy.SetMapIndex(copyKey, copyValue)
		}

	case reflect.Array:
		for i := 0; i < original.Len(); i++ {
			err = copyRecursive(ctx, original.Index(i), cpy.Index(i))
			if err != nil {
				// 忽略不支持类型的错误
				continue
			}
		}

	default:
		cpy.Set(original)
	}

	// 只返回非不支持类型的错误
	if err != nil && err.Error() != "max recursion depth exceeded" {
		return nil
	}
	return err
}
