package system

import (
	"context"
	"encoding/json"
	"errors"
	"strconv"
)

// Dictionary 字典实体
type Dictionary struct {
	ID       uint
	Name     string
	Type     string
	Status   *bool
	Desc     string
	ParentID *uint
	Children []*Dictionary
}

// DictionaryDetail 字典详情实体
type DictionaryDetail struct {
	ID              uint
	Label           string
	Value           string
	Extend          string
	Status          *bool
	Sort            int
	SysDictionaryID uint
	ParentID        *uint
	Level           int
	Path            string
	Disabled        bool
	Children        []*DictionaryDetail
}

// DictionaryRepo 字典仓储接口
type DictionaryRepo interface {
	Create(ctx context.Context, dict *Dictionary) error
	Update(ctx context.Context, dict *Dictionary) error
	Delete(ctx context.Context, id uint) error
	FindByID(ctx context.Context, id uint) (*Dictionary, error)
	FindByType(ctx context.Context, typ string) (*Dictionary, error)
	GetByTypeOrID(ctx context.Context, typ string, id uint, status *bool) (*Dictionary, error)
	List(ctx context.Context, name string) ([]*Dictionary, error)
	CheckCircularReference(ctx context.Context, currentID, parentID uint) error
}

// DictionaryDetailRepo 字典详情仓储接口
type DictionaryDetailRepo interface {
	Create(ctx context.Context, detail *DictionaryDetail) error
	Update(ctx context.Context, detail *DictionaryDetail) error
	Delete(ctx context.Context, id uint) error
	FindByID(ctx context.Context, id uint) (*DictionaryDetail, error)
	List(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*DictionaryDetail, int64, error)
	GetListByDictionaryID(ctx context.Context, dictionaryID uint) ([]*DictionaryDetail, error)
	GetTreeList(ctx context.Context, dictionaryID uint) ([]*DictionaryDetail, error)
	GetByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]*DictionaryDetail, error)
	GetByDictionaryIDAndValue(ctx context.Context, dictionaryID uint, value string) (*DictionaryDetail, error)
	GetByTypeAndValue(ctx context.Context, typ, value string) (*DictionaryDetail, error)
	GetTreeListByType(ctx context.Context, typ string) ([]*DictionaryDetail, error)
	GetListByType(ctx context.Context, typ string) ([]*DictionaryDetail, error)
	HasChildren(ctx context.Context, id uint) (bool, error)
	CheckCircularReference(ctx context.Context, id, parentID uint) bool
	UpdateChildrenLevelAndPath(ctx context.Context, parentID uint) error
	GetPath(ctx context.Context, id uint) ([]*DictionaryDetail, error)
	DeleteByDictionaryID(ctx context.Context, dictionaryID uint) error
	BatchCreate(ctx context.Context, details []*DictionaryDetail) error
	BatchUpdateParentID(ctx context.Context, idMap map[uint]uint) error
}

// DictionaryUsecase 字典用例
type DictionaryUsecase struct {
	repo       DictionaryRepo
	detailRepo DictionaryDetailRepo
}

// NewDictionaryUsecase 创建字典用例
func NewDictionaryUsecase(repo DictionaryRepo, detailRepo DictionaryDetailRepo) *DictionaryUsecase {
	return &DictionaryUsecase{repo: repo, detailRepo: detailRepo}
}

// CreateDictionary 创建字典
func (uc *DictionaryUsecase) CreateDictionary(ctx context.Context, dict *Dictionary) error {
	// 检查type是否重复
	existing, err := uc.repo.FindByType(ctx, dict.Type)
	if err == nil && existing != nil {
		return errors.New("存在相同的type，不允许创建")
	}
	return uc.repo.Create(ctx, dict)
}

// UpdateDictionary 更新字典
func (uc *DictionaryUsecase) UpdateDictionary(ctx context.Context, dict *Dictionary) error {
	old, err := uc.repo.FindByID(ctx, dict.ID)
	if err != nil {
		return errors.New("查询字典数据失败")
	}
	// 如果type变更，检查是否重复
	if old.Type != dict.Type {
		existing, err := uc.repo.FindByType(ctx, dict.Type)
		if err == nil && existing != nil {
			return errors.New("存在相同的type，不允许创建")
		}
	}
	// 检查循环引用
	if dict.ParentID != nil && *dict.ParentID != 0 {
		if err := uc.repo.CheckCircularReference(ctx, dict.ID, *dict.ParentID); err != nil {
			return err
		}
	}
	return uc.repo.Update(ctx, dict)
}

// DeleteDictionary 删除字典
func (uc *DictionaryUsecase) DeleteDictionary(ctx context.Context, id uint) error {
	dict, err := uc.repo.FindByID(ctx, id)
	if err != nil {
		return errors.New("请不要搞事")
	}
	if err := uc.repo.Delete(ctx, id); err != nil {
		return err
	}
	// 删除关联的字典详情
	return uc.detailRepo.DeleteByDictionaryID(ctx, dict.ID)
}

// GetDictionary 获取字典
func (uc *DictionaryUsecase) GetDictionary(ctx context.Context, typ string, id uint, status *bool) (*Dictionary, error) {
	return uc.repo.GetByTypeOrID(ctx, typ, id, status)
}

// GetDictionaryList 获取字典列表
func (uc *DictionaryUsecase) GetDictionaryList(ctx context.Context, name string) ([]*Dictionary, error) {
	return uc.repo.List(ctx, name)
}

// ExportDictionary 导出字典
func (uc *DictionaryUsecase) ExportDictionary(ctx context.Context, id uint) (map[string]interface{}, error) {
	dict, err := uc.repo.FindByID(ctx, id)
	if err != nil {
		return nil, err
	}
	details, err := uc.detailRepo.GetListByDictionaryID(ctx, dict.ID)
	if err != nil {
		return nil, err
	}

	// 清理详情数据
	var cleanDetails []map[string]interface{}
	for _, detail := range details {
		cleanDetail := map[string]interface{}{
			"label":  detail.Label,
			"value":  detail.Value,
			"extend": detail.Extend,
			"status": detail.Status,
			"sort":   detail.Sort,
			"level":  detail.Level,
			"path":   detail.Path,
		}
		cleanDetails = append(cleanDetails, cleanDetail)
	}

	return map[string]interface{}{
		"name":                 dict.Name,
		"type":                 dict.Type,
		"status":               dict.Status,
		"desc":                 dict.Desc,
		"sysDictionaryDetails": cleanDetails,
	}, nil
}

// ImportDictionary 导入字典
func (uc *DictionaryUsecase) ImportDictionary(ctx context.Context, jsonStr string) error {
	var importData struct {
		Name                 string              `json:"name"`
		Type                 string              `json:"type"`
		Status               *bool               `json:"status"`
		Desc                 string              `json:"desc"`
		SysDictionaryDetails []*DictionaryDetail `json:"sysDictionaryDetails"`
	}
	if err := json.Unmarshal([]byte(jsonStr), &importData); err != nil {
		return errors.New("JSON 格式错误: " + err.Error())
	}
	if importData.Name == "" {
		return errors.New("字典名称不能为空")
	}
	if importData.Type == "" {
		return errors.New("字典类型不能为空")
	}
	// 检查type是否重复
	existing, err := uc.repo.FindByType(ctx, importData.Type)
	if err == nil && existing != nil {
		return errors.New("存在相同的type，不允许导入")
	}

	// 创建字典
	dict := &Dictionary{
		Name:   importData.Name,
		Type:   importData.Type,
		Status: importData.Status,
		Desc:   importData.Desc,
	}
	if err := uc.repo.Create(ctx, dict); err != nil {
		return err
	}

	// 处理字典详情
	if len(importData.SysDictionaryDetails) > 0 {
		idMap := make(map[uint]uint)
		for _, detail := range importData.SysDictionaryDetails {
			if detail.Label == "" || detail.Value == "" {
				continue
			}
			oldID := detail.ID
			newDetail := &DictionaryDetail{
				Label:           detail.Label,
				Value:           detail.Value,
				Extend:          detail.Extend,
				Status:          detail.Status,
				Sort:            detail.Sort,
				Level:           detail.Level,
				Path:            detail.Path,
				SysDictionaryID: dict.ID,
			}
			if err := uc.detailRepo.Create(ctx, newDetail); err != nil {
				return err
			}
			if oldID > 0 {
				idMap[oldID] = newDetail.ID
			}
		}
		// 更新parent_id关系
		if len(idMap) > 0 {
			if err := uc.detailRepo.BatchUpdateParentID(ctx, idMap); err != nil {
				return err
			}
		}
	}
	return nil
}

// CreateDictionaryDetail 创建字典详情
func (uc *DictionaryUsecase) CreateDictionaryDetail(ctx context.Context, detail *DictionaryDetail) error {
	// 计算层级和路径
	if detail.ParentID != nil && *detail.ParentID != 0 {
		parent, err := uc.detailRepo.FindByID(ctx, *detail.ParentID)
		if err != nil {
			return err
		}
		detail.Level = parent.Level + 1
		if parent.Path == "" {
			detail.Path = strconv.Itoa(int(parent.ID))
		} else {
			detail.Path = parent.Path + "," + strconv.Itoa(int(parent.ID))
		}
	} else {
		detail.Level = 0
		detail.Path = ""
	}
	return uc.detailRepo.Create(ctx, detail)
}

// UpdateDictionaryDetail 更新字典详情
func (uc *DictionaryUsecase) UpdateDictionaryDetail(ctx context.Context, detail *DictionaryDetail) error {
	// 如果更新了父级ID，重新计算层级和路径
	if detail.ParentID != nil && *detail.ParentID != 0 {
		parent, err := uc.detailRepo.FindByID(ctx, *detail.ParentID)
		if err != nil {
			return err
		}
		// 检查循环引用
		if uc.detailRepo.CheckCircularReference(ctx, detail.ID, *detail.ParentID) {
			return errors.New("不能将字典详情设置为自己或其子项的父级")
		}
		detail.Level = parent.Level + 1
		if parent.Path == "" {
			detail.Path = strconv.Itoa(int(parent.ID))
		} else {
			detail.Path = parent.Path + "," + strconv.Itoa(int(parent.ID))
		}
	} else {
		detail.Level = 0
		detail.Path = ""
	}
	if err := uc.detailRepo.Update(ctx, detail); err != nil {
		return err
	}
	// 更新所有子项的层级和路径
	return uc.detailRepo.UpdateChildrenLevelAndPath(ctx, detail.ID)
}

// DeleteDictionaryDetail 删除字典详情
func (uc *DictionaryUsecase) DeleteDictionaryDetail(ctx context.Context, id uint) error {
	hasChildren, err := uc.detailRepo.HasChildren(ctx, id)
	if err != nil {
		return err
	}
	if hasChildren {
		return errors.New("该字典详情下还有子项，无法删除")
	}
	return uc.detailRepo.Delete(ctx, id)
}

// GetDictionaryDetail 获取字典详情
func (uc *DictionaryUsecase) GetDictionaryDetail(ctx context.Context, id uint) (*DictionaryDetail, error) {
	return uc.detailRepo.FindByID(ctx, id)
}

// GetDictionaryDetailList 获取字典详情列表
func (uc *DictionaryUsecase) GetDictionaryDetailList(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*DictionaryDetail, int64, error) {
	return uc.detailRepo.List(ctx, page, pageSize, filters)
}

// GetDictionaryTreeList 获取字典树形列表
func (uc *DictionaryUsecase) GetDictionaryTreeList(ctx context.Context, dictionaryID uint) ([]*DictionaryDetail, error) {
	return uc.detailRepo.GetTreeList(ctx, dictionaryID)
}

// GetDictionaryDetailsByParent 根据父级获取字典详情
func (uc *DictionaryUsecase) GetDictionaryDetailsByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]*DictionaryDetail, error) {
	return uc.detailRepo.GetByParent(ctx, dictionaryID, parentID, includeChildren)
}

// GetDictionaryInfoByValue 根据字典ID和值获取详情
func (uc *DictionaryUsecase) GetDictionaryInfoByValue(ctx context.Context, dictionaryID uint, value string) (*DictionaryDetail, error) {
	return uc.detailRepo.GetByDictionaryIDAndValue(ctx, dictionaryID, value)
}

// GetDictionaryInfoByTypeValue 根据字典类型和值获取详情
func (uc *DictionaryUsecase) GetDictionaryInfoByTypeValue(ctx context.Context, typ, value string) (*DictionaryDetail, error) {
	return uc.detailRepo.GetByTypeAndValue(ctx, typ, value)
}

// GetDictionaryTreeListByType 根据类型获取树形列表
func (uc *DictionaryUsecase) GetDictionaryTreeListByType(ctx context.Context, typ string) ([]*DictionaryDetail, error) {
	return uc.detailRepo.GetTreeListByType(ctx, typ)
}

// GetDictionaryListByType 根据类型获取列表
func (uc *DictionaryUsecase) GetDictionaryListByType(ctx context.Context, typ string) ([]*DictionaryDetail, error) {
	return uc.detailRepo.GetListByType(ctx, typ)
}

// GetDictionaryPath 获取字典详情路径
func (uc *DictionaryUsecase) GetDictionaryPath(ctx context.Context, id uint) ([]*DictionaryDetail, error) {
	return uc.detailRepo.GetPath(ctx, id)
}

// GetDictionaryPathByValue 根据值获取字典详情路径
func (uc *DictionaryUsecase) GetDictionaryPathByValue(ctx context.Context, dictionaryID uint, value string) ([]*DictionaryDetail, error) {
	detail, err := uc.detailRepo.GetByDictionaryIDAndValue(ctx, dictionaryID, value)
	if err != nil {
		return nil, err
	}
	return uc.detailRepo.GetPath(ctx, detail.ID)
}
