package controller

import (
	"encoding/json"
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"
	_type "xianyv/type"
	"xianyv/utils/checkUtil"
	"xianyv/utils/creatGoodsUtil"

	"github.com/xuri/excelize/v2"
)

type GoodsController struct {
	ExcelPath string
	TxtPath   string
	SheetName string
}

// 简化缓存结构，避免复杂锁嵌套
type FileCache struct {
	categoryMap   map[string]string
	categoryTime  time.Time
	categoryMutex sync.RWMutex

	// Excel数据内存缓存，key为sheetName，value为map[col][int32]bool
	excelCache         map[string]map[string]map[int32]bool
	excelCacheTime     map[string]time.Time
	excelCacheMutex    sync.RWMutex
	excelCacheDuration time.Duration

	// Excel操作全局互斥锁（兼容老逻辑，后续可移除）
	excelMutex    sync.Mutex
	cacheDuration time.Duration
}

var (
	fileCacheInstance *FileCache
	once              sync.Once
)

func GetFileCache() *FileCache {
	once.Do(func() {
		fileCacheInstance = &FileCache{
			cacheDuration:      5 * time.Minute,
			excelCache:         make(map[string]map[string]map[int32]bool),
			excelCacheTime:     make(map[string]time.Time),
			excelCacheDuration: 5 * time.Minute,
		}
	})
	return fileCacheInstance
}

// 预加载Excel校验数据到内存
func (fc *FileCache) PreloadExcelCache(filename, sheetName string, columns []string) error {
	fc.excelCacheMutex.Lock()
	defer fc.excelCacheMutex.Unlock()

	// 只加载指定sheet和列
	cache := make(map[string]map[int32]bool) // col -> set of int32

	f, err := excelize.OpenFile(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	rows, err := f.GetRows(sheetName)
	if err != nil {
		return err
	}

	for _, col := range columns {
		cache[col] = make(map[int32]bool)
	}
	for rowNum := 1; rowNum <= len(rows); rowNum++ {
		for _, col := range columns {
			cellAddress := fmt.Sprintf("%s%d", col, rowNum)
			cellValue, err := f.GetCellValue(sheetName, cellAddress)
			if err != nil || cellValue == "" {
				continue
			}
			cellInt, err := strconv.ParseInt(cellValue, 10, 32)
			if err != nil {
				continue
			}
			cache[col][int32(cellInt)] = true
		}
	}
	if fc.excelCache == nil {
		fc.excelCache = make(map[string]map[string]map[int32]bool)
	}
	fc.excelCache[sheetName] = cache
	if fc.excelCacheTime == nil {
		fc.excelCacheTime = make(map[string]time.Time)
	}
	fc.excelCacheTime[sheetName] = time.Now()
	return nil
}

// GetCategoryMap 获取类目映射（简化版本）
func (fc *FileCache) GetCategoryMap(txtPath string) (map[string]string, error) {
	fc.categoryMutex.RLock()
	if fc.categoryMap != nil && time.Since(fc.categoryTime) < fc.cacheDuration {
		defer fc.categoryMutex.RUnlock()
		return fc.categoryMap, nil
	}
	fc.categoryMutex.RUnlock()

	fc.categoryMutex.Lock()
	defer fc.categoryMutex.Unlock()

	// 双重检查
	if fc.categoryMap != nil && time.Since(fc.categoryTime) < fc.cacheDuration {
		return fc.categoryMap, nil
	}

	log.Printf("更新类目缓存...")
	categoryMap, err := checkUtil.CheckValuesInTxt(txtPath)
	if err != nil {
		return nil, err
	}

	fc.categoryMap = categoryMap
	fc.categoryTime = time.Now()
	log.Printf("类目缓存更新完成，共 %d 个类目", len(categoryMap))
	return categoryMap, nil
}

// CheckValuesInExcelWithMutex 优先用内存缓存校验，若无则自动预加载
func (fc *FileCache) CheckValuesInExcelWithMutex(filename, sheetName string, values map[string]int32) (map[string]bool, error) {
	// 先尝试用内存缓存
	fc.excelCacheMutex.RLock()
	cache, ok := fc.excelCache[sheetName]
	fc.excelCacheMutex.RUnlock()
	columns := make([]string, 0, len(values))
	for col := range values {
		columns = append(columns, col)
	}
	if !ok {
		// 缓存不存在，自动预加载
		if err := fc.PreloadExcelCache(filename, sheetName, columns); err != nil {
			return nil, err
		}
		fc.excelCacheMutex.RLock()
		cache, ok = fc.excelCache[sheetName]
		fc.excelCacheMutex.RUnlock()
		if !ok {
			return nil, fmt.Errorf("Excel缓存加载失败: %s", sheetName)
		}
	}
	// 校验
	result := make(map[string]bool)
	for col, target := range values {
		if colMap, ok := cache[col]; ok {
			result[col] = colMap[target]
		} else {
			result[col] = false
		}
	}
	return result, nil
}

// createErrorResponse 创建错误响应
func createErrorResponse(format string, args ...interface{}) ([]byte, error) {
	resp := _type.ErrResponse{
		Code: 0,
		Msg:  fmt.Sprintf(format, args...),
		Data: struct{}{},
	}
	response, err := json.Marshal(resp)
	return response, err
}

// GoodsCreatController 修复死锁问题的版本
func (c *GoodsController) GoodsCreatController(body _type.Body, batchCreatRequest, domain string, flag bool) ([]byte, error) {
	startTime := time.Now()
	defer func() {
		log.Printf("GoodsCreatController 执行时间: %v", time.Since(startTime))
	}()

	fileCache := GetFileCache()

	// 类目ID基础校验
	catStart := time.Now()
	categoryMap, err := fileCache.GetCategoryMap(c.TxtPath)
	log.Printf("GetCategoryMap elapsed=%v", time.Since(catStart))
	if err != nil {
		log.Printf("读取文件失败: %v", err)
		return createErrorResponse("读取文件失败: %v", err)
	}

	if _, exists := categoryMap[body.CatIds]; !exists {
		log.Printf("错误的类目ID: %s", body.CatIds)
		return createErrorResponse("错误的类目ID: %s", body.CatIds)
	}

	// 省市区基础校验
	valuesToCheck := map[string]int32{
		"A": body.Province,
		"C": body.City,
		"E": body.District,
	}

	checkStart := time.Now()
	checkResults, err := fileCache.CheckValuesInExcelWithMutex(c.ExcelPath, c.SheetName, valuesToCheck)
	log.Printf("CheckValuesInExcelWithMutex elapsed=%v", time.Since(checkStart))
	if err != nil {
		log.Printf("Excel检查失败: %v", err)
	} else {
		log.Printf("检查结果: %v", checkResults)
	}

	// 业务逻辑处理
	switch body.TypePlatform {
	case 4:
		createStart := time.Now()
		createResponse, err := creatGoodsUtil.XianYvCreat(body, batchCreatRequest, body.AppId, body.AppSecret, domain, flag)
		log.Printf("XianYvCreat elapsed=%v", time.Since(createStart))
		if err != nil {
			log.Printf("创建商品失败: %v", err)
			return createErrorResponse("创建商品失败: %v", err)
		}
		return createResponse, nil
	default:
		return createErrorResponse("平台编号有误: %d", body.TypePlatform)
	}
}

// GoodsCreatController 分离BookData的全局变量
func (c *GoodsController) GoodsCreatControllerNew(body _type.BodyNew, batchCreatRequest, domain string, flag bool) ([]byte, error) {
	startTime := time.Now()
	defer func() {
		log.Printf("GoodsCreatController 执行时间: %v", time.Since(startTime))
	}()

	fileCache := GetFileCache()

	// 类目ID基础校验
	catStart := time.Now()
	categoryMap, err := fileCache.GetCategoryMap(c.TxtPath)
	log.Printf("GetCategoryMap elapsed=%v", time.Since(catStart))
	if err != nil {
		log.Printf("读取文件失败: %v", err)
		return createErrorResponse("读取文件失败: %v", err)
	}

	if _, exists := categoryMap[body.CatIds]; !exists {
		log.Printf("错误的类目ID: %s", body.CatIds)
		return createErrorResponse("错误的类目ID: %s", body.CatIds)
	}

	// 省市区基础校验
	valuesToCheck := map[string]int32{
		"A": body.Province,
		"C": body.City,
		"E": body.District,
	}

	checkStart := time.Now()
	checkResults, err := fileCache.CheckValuesInExcelWithMutex(c.ExcelPath, c.SheetName, valuesToCheck)
	log.Printf("CheckValuesInExcelWithMutex elapsed=%v", time.Since(checkStart))
	if err != nil {
		log.Printf("Excel检查失败: %v", err)
	} else {
		log.Printf("检查结果: %v", checkResults)
	}

	// 业务逻辑处理
	switch body.TypePlatform {
	case 4:
		createStart := time.Now()
		if len(body.BookData) > 0 {
			createResponse, err := creatGoodsUtil.XianYvCreatNew(body, batchCreatRequest, body.AppId, body.AppSecret, domain, flag)
			log.Printf("XianYvCreat elapsed=%v", time.Since(createStart))
			if err != nil {
				log.Printf("创建商品失败: %v", err)
				return createErrorResponse("创建商品失败: %v", err)
			}
			return createResponse, nil
		} else {
			createResponse, err := creatGoodsUtil.XianYvCreatNoIsbn(body, batchCreatRequest, body.AppId, body.AppSecret, domain, flag)
			log.Printf("XianYvCreat elapsed=%v", time.Since(createStart))
			if err != nil {
				log.Printf("创建商品失败: %v", err)
				return createErrorResponse("创建商品失败: %v", err)
			}
			return createResponse, nil
		}

	default:
		return createErrorResponse("平台编号有误: %d", body.TypePlatform)
	}
}

// 刷新指定sheet的Excel缓存（重新加载）
func (fc *FileCache) RefreshExcelCache(filename, sheetName string, columns []string) error {
	return fc.PreloadExcelCache(filename, sheetName, columns)
}

// 清空所有Excel缓存（下次校验时会自动重新加载）
func (fc *FileCache) ClearAllExcelCache() {
	fc.excelCacheMutex.Lock()
	defer fc.excelCacheMutex.Unlock()
	fc.excelCache = make(map[string]map[string]map[int32]bool)
	fc.excelCacheTime = make(map[string]time.Time)
}

// 直接在内存缓存校验Excel值
// values: map[col]目标值
// 返回: map[col]是否存在
func (fc *FileCache) CheckValuesInExcelCache(sheetName string, values map[string]int32) (map[string]bool, error) {
	fc.excelCacheMutex.RLock()
	defer fc.excelCacheMutex.RUnlock()
	result := make(map[string]bool)
	cache, ok := fc.excelCache[sheetName]
	if !ok {
		return nil, fmt.Errorf("Excel缓存未加载: %s", sheetName)
	}
	for col, target := range values {
		if colMap, ok := cache[col]; ok {
			result[col] = colMap[target]
		} else {
			result[col] = false
		}
	}
	return result, nil
}
