package models

import (
	"fmt"
	"go-admin/app/admin/models/common"
	orm "go-admin/common/global"
	"go-admin/logger"
	"gorm.io/gorm"
)

type Category struct {
	Model

	Name                  string `json:"name"`                    // 分类名称
	Number                string `json:"number"`                  // 编号
	Display               int8   `json:"display"`                 // 1 展示 0 隐藏
	Pid                   uint32 `json:"pid" gorm:"index"`        // 父分类的编号
	CooperativeBusinessId uint32 `json:"cooperative_business_id"` // 合作商id
}

var (
	Display   = 1
	UnDisplay = 0
)

func (c *Category) TableName() string {
	return "erp_category"
}

func (c *Category) BeforeCreate(tx *gorm.DB) error {
	if c.Number == "" {
		n, err := GenerateNumber(c.CooperativeBusinessId, c.Pid)
		if err != nil {
			logger.Error("before create category err", logger.Field("c", c), logger.Field("err", err))
			return err
		}
		c.Number = n
	}
	return nil
}

// GenerateNumber 生成分类编码
func GenerateNumber(cid uint32, pid uint32) (string, error) {
	var count int64
	var err error

	err = orm.Eloquent.Model(Category{}).
		Unscoped().
		Scopes(common.ScopeBusiness(cid)).
		Where("pid", pid).
		Count(&count).
		Error
	if err != nil {
		return "", err
	}
	if pid == 0 {
		return fmt.Sprintf("%03d", count+1), nil
	} else {
		var parent Category
		err = orm.Eloquent.Model(Category{}).
			Scopes(common.ScopeBusiness(cid)).
			Where("id", pid).
			First(&parent).Error
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("%s%03d", parent.Number, count+1), nil
	}
}

// GetCategoryById 通过id获取分类
func GetCategoryById(id uint32) (*Category, error) {
	//var c *Category
	c := new(Category)
	err := orm.Eloquent.Model(c).Where("id", id).First(c).Error
	if err != nil {
		return nil, err
	}

	return c, nil
}

func comparePrefix(a, b string) bool {
	// 获取字符串 a 的长度
	aLen := len(a)

	// 如果 b 的长度比 a 短，则无法比较
	if len(b) < aLen {
		return false
	}

	// 截取 b 的前 aLen 个字符
	bPrefix := b[:aLen]

	// 比较 a 和 b 的前缀部分
	return a == bPrefix
}

// CheckCouponCategory 判断优惠券分类和商品分类是否对应
func CheckCouponCategory(num string, id uint32) bool {
	categoryInfo, err := GetCategoryById(id)
	if err != nil || err == RecordNotFound {
		return false
	}

	return comparePrefix(num, categoryInfo.Number)
}

type CategoryModel struct {
	Category
	SubCategory []*CategoryModel `json:"sub_category" gorm:"-"` //子分类
}

func ScopeOnlyDisplay(db *gorm.DB) *gorm.DB {
	return db.Where("display", Display)
}

// GetCategoryList 分类列表
func GetCategoryList(bid uint32, all bool) ([]*CategoryModel, error) {
	var list = make([]*CategoryModel, 0)
	m := orm.Eloquent.Model(Category{})

	var scopes = []func(db *gorm.DB) *gorm.DB{common.ScopeBusiness(bid)}
	if !all {
		scopes = append(scopes, ScopeOnlyDisplay)
	}

	err := m.Scopes(scopes...).Where("pid = ?", 0).Find(&list).Error
	if err != nil {
		return nil, err
	}
	for _, top := range list {
		top.SubCategory = findChildCategory(top, all)
	}

	return list, nil
}

// 查询子分类
func findChildCategory(prev *CategoryModel, all bool) []*CategoryModel {
	var cs []*CategoryModel
	m := orm.Eloquent.Model(Category{})
	if !all {
		m = m.Scopes(ScopeOnlyDisplay)
	}
	err := m.Where("pid", prev.ID).Find(&cs).Error
	if err != nil {
		return nil
	}

	for _, c := range cs {
		c.SubCategory = findChildCategory(c, all)
	}

	return cs
}

// CheckCommodityByCategory 检查某个分类下是否有商品
func CheckCommodityByCategory(categoryId uint32) bool {
	var count int64
	err := orm.Eloquent.Table("erp_commodity").Where("erp_category_id = ? and count > 0", categoryId).
		Count(&count).Error
	if err != nil {
		logger.Error("CheckCommodityByCategory err:", logger.Field("err", err))
	}

	return count > 0
}

// IsExistingCategory 查询分类资料中某个名称的分类是否存在
func IsExistingCategory(categoryName string) bool {
	if categoryName == "" {
		return true
	}
	// 查询分类名称是否存在的逻辑
	var count int64
	orm.Eloquent.Debug().Model(&Category{}).
		Where("name = ?", categoryName).
		Count(&count)

	return count > 0
}

// IsExistingCategoryByNumber 查询分类资料中某个名称的分类是否存在
func IsExistingCategoryByNumber(number string) bool {
	if number == "" {
		return false
	}
	// 查询分类名称是否存在的逻辑
	var count int64
	orm.Eloquent.Debug().Model(&Category{}).
		Where("number = ?", number).
		Count(&count)

	return count > 0
}

// GetSubcategoryIds 获取指定分类的所有子分类ID
func GetSubcategoryIds(categoryID uint32) ([]uint32, error) {
	var subCategories []Category
	err := orm.Eloquent.Model(&Category{}).Where("pid = ?", categoryID).Find(&subCategories).Error
	if err != nil {
		return nil, err
	}

	var subCategoryIDs []uint32
	for _, subCategory := range subCategories {
		subCategoryIDs = append(subCategoryIDs, subCategory.ID)
		// 递归获取子分类的子分类
		childIDs, err := GetSubcategoryIds(subCategory.ID)
		if err != nil {
			return nil, err
		}
		subCategoryIDs = append(subCategoryIDs, childIDs...)
	}

	return subCategoryIDs, nil
}

// TransformErpCategoryIds 转换 ErpCategoryId，将子分类ID添加进来并去重
func TransformErpCategoryIds(categoryIds []uint32) ([]uint32, error) {
	categoryIDSet := make(map[uint32]struct{}) // 用于去重的集合

	// 遍历传入的 ErpCategoryId
	for _, categoryID := range categoryIds {
		// 获取当前分类及其所有子分类ID
		subCategoryIDs, err := GetSubcategoryIds(categoryID)
		if err != nil {
			return nil, err
		}

		// 将当前分类ID添加到集合中
		categoryIDSet[categoryID] = struct{}{}
		// 将子分类ID添加到集合中
		for _, subID := range subCategoryIDs {
			categoryIDSet[subID] = struct{}{}
		}
	}

	// 将集合转换为切片
	var result []uint32
	for id := range categoryIDSet {
		result = append(result, id)
	}

	return result, nil
}

// CategoryLevels 代表分类层级信息
type CategoryLevels struct {
	Level1 Category `json:"level1"`
	Level2 Category `json:"level2,omitempty"`
	Level3 Category `json:"level3,omitempty"`
}

// GetCategoryLevels 根据商品分类ID获取分类层级信息
func GetCategoryLevels(categoryID uint32) (CategoryLevels, error) {
	var levels CategoryLevels

	// 维持当前分类的ID
	currentID := categoryID
	levelCount := 0

	for currentID != 0 && levelCount < 3 {
		var currentCategory Category

		// 查询当前分类
		err := orm.Eloquent.Model(&Category{}).Where("id = ?", currentID).First(&currentCategory).Error
		if err != nil {
			return levels, err
		}

		// 根据分类编号的长度判断层级
		numberLength := len(currentCategory.Number)
		switch numberLength {
		case 3:
			levels.Level1 = currentCategory // 一级分类
		case 6:
			levels.Level2 = currentCategory // 二级分类
		case 9:
			levels.Level3 = currentCategory // 三级分类
		default:
			return levels, nil // 超过9位返回空
		}

		// 移动到上级分类
		currentID = currentCategory.Pid
		levelCount++
	}

	return levels, nil
}

// GetAllCategories 查询所有分类并返回一个映射
func GetAllCategories() (map[uint32]Category, error) {
	var categories []Category
	err := orm.Eloquent.Model(&Category{}).Find(&categories).Error
	if err != nil {
		return nil, err
	}

	categoryMap := make(map[uint32]Category)
	for _, category := range categories {
		categoryMap[category.ID] = category
	}
	return categoryMap, nil
}

// GetCategoryLevelsFromMap 从预加载的分类信息中获取层级
func GetCategoryLevelsFromMap(categoryID uint32, categoryMap map[uint32]Category) CategoryLevels {
	var levels CategoryLevels

	// 维持当前分类的ID
	currentID := categoryID
	levelCount := 0

	for currentID != 0 && levelCount < 3 {
		currentCategory, exists := categoryMap[currentID]
		if !exists {
			break
		}

		// 根据分类编号的长度判断层级
		numberLength := len(currentCategory.Number)
		switch numberLength {
		case 3:
			levels.Level1 = currentCategory // 一级分类
		case 6:
			levels.Level2 = currentCategory // 二级分类
		case 9:
			levels.Level3 = currentCategory // 三级分类
		default:
			return levels // 超过9位返回空
		}

		// 移动到上级分类
		currentID = currentCategory.Pid
		levelCount++
	}

	return levels
}

// GetAllFirstCategories 查询所有1级分类
func GetAllFirstCategories() ([]Category, error) {
	var categories []Category
	err := orm.Eloquent.Model(&Category{}).Where("pid = 0 and display = 1").Find(&categories).Error
	if err != nil {
		return nil, err
	}

	return categories, nil
}

// getCategoryNameByID 获取分类名称
func getCategoryNameByCategoryID(categoryID uint32) string {
	// 假设有一个GetCategoryByID函数返回分类信息
	category, err := GetCategoryById(categoryID)
	if err != nil {
		return "未知分类"
	}
	return category.Name
}
