package plant

import (
	"context"
	"errors"
	"sundynix-go/global"
	common "sundynix-go/model/commom/request"
	"sundynix-go/model/plant"
	plantReq "sundynix-go/model/plant/request"
	plantRes "sundynix-go/model/plant/response"
	"sundynix-go/model/system"
	"sundynix-go/utils/timer"
	"time"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

type MyPlantService struct{}

var MyPlantServiceApp = new(MyPlantService)

// AddPlant 添加植物
func (s *MyPlantService) AddPlant(req plantReq.CreateMyPlant, userId string) error {
	err := global.DB.Transaction(func(tx *gorm.DB) error {
		//1. 验证oss是否存在
		var ossList []*system.Oss
		err := tx.Where("id in ?", req.OssIds).Find(&ossList).Error
		if err != nil {
			return err
		}
		bgTime := timer.GetZeroTime()
		//2. 处理养护计划
		var carePlans []*plant.CarePlan
		for _, v := range req.CarePlans {
			carePlans = append(carePlans, &plant.CarePlan{
				UserId:       userId,
				Name:         v.Name,
				Icon:         v.Icon,
				Period:       v.Period,
				TargetAction: v.TargetAction,
			})
		}
		//3.保存数据 myPlant钩子函数自动处理创建careTask
		myPlant := plant.MyPlant{
			UserId:           userId,
			Name:             req.Name,
			PlantTime:        bgTime,
			Status:           1,
			Placement:        req.Placement,
			PotMaterial:      req.PotMaterial,
			PotSize:          req.PotSize,
			Sunlight:         req.Sunlight,
			PlantingMaterial: req.PlantingMaterial,
			CarePlans:        carePlans,
		}
		err = tx.Create(&myPlant).Error
		if err != nil {
			return err
		}

		//4.处理图片关系
		if len(ossList) > 0 {
			var relations []map[string]interface{}
			for _, oss := range ossList {
				relations = append(relations, map[string]interface{}{
					"my_plant_id": myPlant.Id,
					"oss_id":      oss.Id,
				})
			}
			err = tx.Table("sundynix_my_plant_oss").Create(relations).Error
			if err != nil {
				return err
			}
		}
		//5.更新用户中心数据
		err = tx.Model(&plant.UserProfile{}).Where("user_id = ?", userId).
			Update("plant_count", gorm.Expr("plant_count + 1")).Error
		if err != nil {
			return err
		}
		return nil
	})
	return err

}

// PlantPage 植物列表
func (s *MyPlantService) PlantPage(req common.PageInfo, userId string) (list interface{}, total int64, err error) {
	limit := req.PageSize
	offset := req.PageSize * (req.Current - 1)
	db := global.DB.Model(&plant.MyPlant{}).Preload("ImgList", func(db *gorm.DB) *gorm.DB {
		return db.Order("created_at desc")
	})
	var myPlants []*plant.MyPlant
	db = db.Where("user_id = ?", userId)
	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Order("created_at desc").Find(&myPlants).Error
	return myPlants, total, err
}

// PlantDetail 植物详情
func (s *MyPlantService) PlantDetail(id string) (p plant.MyPlant, err error) {
	var res plant.MyPlant
	err = global.DB.Where("id = ?", id).
		Preload("ImgList", func(db *gorm.DB) *gorm.DB {
			return db.Order("created_at desc")
		}).
		Preload("CarePlans").
		Preload("CareRecords", func(db *gorm.DB) *gorm.DB {
			return db.Order("created_at desc")
		}).
		Preload("GrowthRecords", func(db *gorm.DB) *gorm.DB {
			return db.Preload("ImgList", func(db *gorm.DB) *gorm.DB {
				return db.Order("created_at desc")
			}).Order("created_at desc")
		}).
		First(&res).Error

	//不存在的时候不要返回错误，而是返回nil
	if err != nil {
		return res, err
	}
	return res, nil
}

func (s *MyPlantService) UpdatePlant(req plantReq.UpdateMyPlant) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		var myPlant plant.MyPlant
		err := tx.Where("id = ?", req.Id).First(&myPlant).Error
		if err != nil {
			return err
		}
		// 以map形式更新 先构建map
		updateMap := map[string]interface{}{
			"name":              req.Name,
			"placement":         req.Placement,
			"planting_material": req.PlantingMaterial,
			"pot_material":      req.PotMaterial,
			"pot_size":          req.PotSize,
			"sunlight":          req.Sunlight,
		}
		//1.修改基本信息
		err = tx.Model(&plant.MyPlant{}).Where("id = ?", req.Id).Updates(updateMap).Error
		if err != nil {
			return err
		}
		//2.修改计划
		if len(req.CarePlans) > 0 {
			today := timer.GetZeroTime()
			for _, plan := range req.CarePlans {
				err = tx.Model(&plant.CarePlan{}).Where("id = ?", plan.Id).Updates(map[string]interface{}{
					"icon":          plan.Icon,
					"name":          plan.Name,
					"period":        plan.Period,
					"target_action": plan.TargetAction,
				}).Error
				if err != nil {
					return err
				}
				//3.重新生成任务
				//3.1 删除旧任务
				err = tx.Where("plan_id = ?", plan.Id).Unscoped().Delete(&plant.CareTask{}).Error
				if err != nil {
					return err
				}
				//3.2 创建新任务
				dueDate := today.AddDate(0, 0, plan.Period)
				task := plant.CareTask{
					UserId:       myPlant.UserId,
					PlantId:      myPlant.Id,
					PlanId:       plan.Id,
					Name:         plan.Name,
					Icon:         plan.Icon,
					DueDate:      dueDate,
					Status:       1,
					TargetAction: plan.TargetAction,
				}
				err = tx.Create(&task).Error
				if err != nil {
					return err
				}
			}
		}
		return nil
	})
}

// TodayTask 今日任务
func (s *MyPlantService) TodayTask(userId string) ([]plantRes.PlantTaskVO, error) {
	today := timer.GetZeroTime()
	endOfToday := today.Add(24 * time.Hour)

	var tasks []*plant.CareTask
	// 查询条件：1.未完成的任务(包含今天和以前逾期的) 2.今天已经完成的任务
	err := global.DB.Where("user_id = ? AND ("+
		"(status = 1 AND due_date < ?) OR "+
		"(status = 2 AND completed_at >= ? AND completed_at < ?)"+
		")", userId, endOfToday, today, endOfToday).
		Order("due_date ASC").
		Find(&tasks).Error
	if err != nil {
		return nil, err
	}
	// 2.内存处理：聚合数据
	plantTaskMap := make(map[string][]*plant.CareTask)
	expiredMap := make(map[string]bool)
	var plantIds []string
	for _, t := range tasks {
		plantIds = append(plantIds, t.PlantId)
		plantTaskMap[t.PlantId] = append(plantTaskMap[t.PlantId], t)
		// 判定右上角红标：状态为待办 且 应做时间早于今天
		if t.Status == 1 && t.DueDate.Before(today) {
			expiredMap[t.PlantId] = true
		}
	}
	//3.批量查询植物
	var myPlants []*plant.MyPlant
	err = global.DB.Where("id in ?", plantIds).Preload("ImgList", func(db *gorm.DB) *gorm.DB {
		return db.Order("created_at desc")
	}).Find(&myPlants).Error
	if err != nil {
		return nil, err
	}
	//4.组装结果
	var res []plantRes.PlantTaskVO
	for _, p := range myPlants {
		plantTaskVO := plantRes.PlantTaskVO{
			MyPlant:    p,
			HasExpired: expiredMap[p.Id],
			Tasks:      plantTaskMap[p.Id],
		}
		res = append(res, plantTaskVO)
	}
	return res, nil
}

// CompleteTask 完成任务
func (s *MyPlantService) CompleteTask(req plantReq.CompleteTask, userId string) (*plantRes.TaskCompletionResult, error) {
	var result plantRes.TaskCompletionResult
	err := global.DB.Transaction(func(tx *gorm.DB) error {
		var task plant.CareTask
		if err := tx.Where("id = ?", req.TaskId).First(&task).Error; err != nil {
			return err
		}
		//1.更新当前任务为完成
		updateData := map[string]interface{}{
			"status":       2,
			"completed_at": time.Now(),
		}
		if err := tx.Model(&task).Where("id = ?", req.TaskId).Updates(updateData).Error; err != nil {
			return err
		}
		//2.获取计划模版
		var plan plant.CarePlan
		if err := tx.Where("id = ?", task.PlanId).First(&plan).Error; err != nil {
			return err
		}
		//3.生成下个周期的任务
		today := timer.GetZeroTime()
		nextDueDate := today.AddDate(0, 0, plan.Period)
		newTask := plant.CareTask{
			UserId:       plan.UserId,
			PlantId:      plan.PlantId,
			PlanId:       plan.Id,
			Name:         plan.Name,
			Icon:         plan.Icon,
			TargetAction: plan.TargetAction,
			DueDate:      nextDueDate,
			Status:       1,
		}
		if err := tx.Create(&newTask).Error; err != nil {
			return err
		}
		//4.保存养护记录
		record := plant.CareRecord{
			UserId:  plan.UserId,
			PlantId: plan.PlantId,
			PlanId:  plan.Id,
			Name:    plan.Name,
			Icon:    plan.Icon,
			Remark:  req.Remark,
		}
		if err := tx.Create(&record).Error; err != nil {
			return err
		}
		//4.等级与阳光计算
		var profile plant.UserProfile
		if err := tx.Set("gorm:query_option", "FOR UPDATE").Where("user_id = ?", userId).First(&profile).Error; err != nil {
			return err
		}
		fieldMap := map[string]string{
			"ACT_WATER":     "water_count",
			"ACT_FERTILIZE": "fertilize_count",
			"ACT_REPOT":     "repot_count",
			"ACT_PRUNE":     "prune_count",
		}
		column, ok := fieldMap[task.TargetAction]
		if !ok {
			column = "care_count" // 默认备用
		}
		const TaskReward = 50
		newTotalSunlight := profile.TotalSunlight + TaskReward
		newCurrentSunlight := profile.CurrentSunlight + TaskReward
		// 5. 等级判定 (根据累计阳光查出当前应有的等级)
		var latestLevel plant.LevelConfig
		if err := tx.Where("min_sunlight <= ?", newTotalSunlight).
			Order("min_sunlight DESC").First(&latestLevel).Error; err != nil {
			return errors.New("等级配置异常")
		}
		result.CurrentLevel = &latestLevel
		result.IsLevelUp = latestLevel.Id != profile.LevelId
		// 6. 执行 Profile 更新 (任务阳光 + 计数自增 + 等级同步)
		profileData := map[string]interface{}{
			column:             gorm.Expr(column + " + 1"),
			"current_sunlight": newCurrentSunlight,
			"total_sunlight":   newTotalSunlight,
			"level_id":         latestLevel.Id,
		}
		if err := tx.Model(&plant.UserProfile{}).Where("user_id = ?", userId).Updates(profileData).Error; err != nil {
			return err
		}
		// 7. 徽章判定逻辑
		// 7.1 计算当前动作的最新逻辑数值
		var currentActionVal int64
		switch task.TargetAction {
		case "ACT_WATER":
			currentActionVal = profile.WaterCount + 1
		case "ACT_FERTILIZE":
			currentActionVal = profile.FertilizeCount + 1
		case "ACT_REPOT":
			currentActionVal = profile.RepotCount + 1
		case "ACT_PRUNE":
			currentActionVal = profile.PruneCount + 1
		default:
			currentActionVal = 0
		}
		// 7.2 查询已拥有的徽章 ID (用于去重)
		var ownedBadgeIds []string
		tx.Model(&plant.UserBadge{}).Where("user_id = ?", userId).Pluck("badge_id", &ownedBadgeIds)
		ownedMap := make(map[string]bool)
		for _, id := range ownedBadgeIds {
			ownedMap[id] = true
		}
		// 7.3 筛选当前 Action 下满足条件的最高级徽章
		var badgeConfigs []plant.BadgeConfig
		tx.Where("target_action = ?", task.TargetAction).Preload("Icon").Find(&badgeConfigs)

		for i := range badgeConfigs {
			conf := &badgeConfigs[i]
			// 如果没拿过且数值达标
			if !ownedMap[conf.Id] && currentActionVal >= conf.Threshold {
				// 寻找 Tier 最大的那个
				if result.NewBadge == nil || conf.Tier > result.NewBadge.Tier {
					result.NewBadge = conf
					result.IsGetBadge = true
				}
			}
		}
		// 8. 奖励入库：如果产生了新徽章
		if result.NewBadge != nil {
			// 写入获得记录
			ub := plant.UserBadge{
				UserId:  userId,
				BadgeId: result.NewBadge.Id, // 注意这里 Id 是 string
			}
			if err := tx.Create(&ub).Error; err != nil {
				return err
			}
			// 发放徽章额外奖励阳光
			if err := tx.Model(&plant.UserProfile{}).Where("user_id = ?", userId).
				Update("current_sunlight", gorm.Expr("current_sunlight + ?", result.NewBadge.RewardSunlight)).Error; err != nil {
				return err
			}
		}
		return nil
	})
	return &result, err
}

// DeletePlants 删除植物
func (s *MyPlantService) DeletePlants(req common.IdsReq) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		var imgIds []string
		tx.Table("sundynix_my_plant_oss").Where("my_plant_id IN ?", req.Ids).Pluck("oss_id", &imgIds)
		// 2. 清理中间表记录 (解开多对多关系)
		// 使用 Exec 直接操作中间表比循环 Clear 快得多
		if err := tx.Exec("DELETE FROM sundynix_my_plant_oss WHERE my_plant_id IN ?", req.Ids).Error; err != nil {
			return err
		}
		// 3. 物理删除图片记录本身
		if len(imgIds) > 0 {
			if err := tx.Unscoped().Where("id IN ?", imgIds).Delete(&system.Oss{}).Error; err != nil {
				return err
			}
		}
		//4.批量删除养护计划 养护任务 养护记录 成长记录
		if err := tx.Unscoped().Where("plant_id in ?", req.Ids).Delete(&plant.CarePlan{}).Error; err != nil {
			return err
		}
		if err := tx.Unscoped().Where("plant_id in ?", req.Ids).Delete(&plant.CareTask{}).Error; err != nil {
			return err
		}
		if err := tx.Unscoped().Where("plant_id in ?", req.Ids).Delete(&plant.CareRecord{}).Error; err != nil {
			return err
		}
		if err := tx.Unscoped().Where("plant_id in ?", req.Ids).Delete(&plant.GrowthRecord{}).Error; err != nil {
			return err
		}
		//5.删除植物本身
		if err := tx.Unscoped().Where("id in ?", req.Ids).Delete(&plant.MyPlant{}).Error; err != nil {
			return err
		}

		return nil
	})
}

// DeletePlans 删除任务
func (s *MyPlantService) DeletePlans(req common.IdsReq) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		var plans []plant.CarePlan
		if err := tx.Where("id in ?", req.Ids).Find(&plans).Error; err != nil {
			return err
		}
		var tasks []plant.CareTask
		if err := tx.Where("plan_id in ?", req.Ids).Find(&tasks).Error; err != nil {
			return err
		}
		//1.删除计划
		err := tx.Unscoped().Delete(&plans).Error
		if err != nil {
			return err
		}
		//2.删除任务
		err = tx.Unscoped().Delete(&tasks).Error
		if err != nil {
			return err
		}
		return nil
	})
}

// AddCarePlan 添加CarePlan
func (s *MyPlantService) AddCarePlan(req plantReq.AddPlans) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		for _, plan := range req.CarePlan {
			var myPlant plant.MyPlant
			err := tx.Where("id = ?", plan.PlantId).First(&myPlant).Error
			if err != nil {
				return err
			}
			//1.新增计划
			newPlan := plant.CarePlan{
				UserId:       myPlant.UserId,
				PlantId:      myPlant.Id,
				Name:         plan.Name,
				Icon:         plan.Icon,
				Period:       plan.Period,
				TargetAction: plan.TargetAction,
			}
			err = tx.Create(&newPlan).Error
			if err != nil {
				return err
			}
			//2.新增任务
			today := timer.GetZeroTime()
			dueDate := today.AddDate(0, 0, plan.Period)
			task := plant.CareTask{
				UserId:       myPlant.UserId,
				PlantId:      myPlant.Id,
				PlanId:       newPlan.Id,
				Name:         plan.Name,
				Icon:         plan.Icon,
				TargetAction: plan.TargetAction,
				DueDate:      dueDate,
				Status:       1,
			}
			err = tx.Create(&task).Error
			if err != nil {
				return err
			}
		}
		return nil
	})
}

// DeletePlan 删除CarePlan
func (s *MyPlantService) DeletePlan(id string) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		var plan plant.CarePlan
		if err := tx.Where("id = ?", id).First(&plan).Error; err != nil {
			return err
		}
		var tasks []plant.CareTask
		if err := tx.Where("plan_id = ?", plan.Id).Find(&tasks).Error; err != nil {
			return err
		}
		err := tx.Unscoped().Delete(&plan).Error
		if err != nil {
			return err
		}
		err = tx.Unscoped().Delete(&tasks).Error
		if err != nil {
			return err
		}
		return nil
	})
}

// AddGrowthRecord 添加成长记录
func (s *MyPlantService) AddGrowthRecord(req plantReq.CreateGrowthRecord, userId string) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		//1.验证图片是否存在
		var ossList []*system.Oss
		err := tx.Where("id in ?", req.OssIds).Find(&ossList).Error
		if err != nil {
			return err
		}
		//2.保存记录
		record := plant.GrowthRecord{
			UserId:  userId,
			PlantId: req.PlantId,
			Name:    req.Name,
			Content: req.Content,
			Desc:    req.Desc,
			Tag:     req.Tag,
		}
		err = tx.Create(&record).Error
		if err != nil {
			return err
		}
		//3.保存图片关系
		if len(ossList) > 0 {
			var relations []map[string]interface{}
			for _, oss := range ossList {
				relations = append(relations, map[string]interface{}{
					"growth_record_id": record.Id,
					"oss_id":           oss.Id,
				})
			}
			err = tx.Table("sundynix_growth_record_oss").Create(relations).Error
			if err != nil {
				return err
			}
		}

		return nil
	})
}

// QuickCare 快捷养护记录（无需预设任务，直接创建养护记录）
func (s *MyPlantService) QuickCare(req plantReq.QuickCare, userId string) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		// 1.验证植物存在且属于该用户
		var myPlant plant.MyPlant
		if err := tx.Where("id = ? AND user_id = ?", req.PlantId, userId).First(&myPlant).Error; err != nil {
			return errors.New("植物不存在")
		}
		// 2.直接创建养护记录
		record := plant.CareRecord{
			UserId:  userId,
			PlantId: req.PlantId,
			Name:    req.Name,
			Icon:    req.Icon,
			Remark:  req.Remark,
		}
		if err := tx.Create(&record).Error; err != nil {
			return err
		}
		// 3.更新用户 profile 对应计数（尝试从 icon JSON 解析 targetAction）
		column := "care_count"
		if req.Icon != "" {
			// 解析 icon JSON 中的 id 字段来判断动作类型
			actionMap := map[string]string{
				"water": "water_count", "fertilize": "fertilize_count",
				"prune": "prune_count", "repot": "repot_count",
			}
			// 简单提取: 不引入 encoding/json 解析，用名称匹配
			nameMap := map[string]string{
				"浇水": "water_count", "施肥": "fertilize_count",
				"修剪": "prune_count", "换盆": "repot_count",
			}
			if col, ok := nameMap[req.Name]; ok {
				column = col
			} else {
				// 尝试从 actionMap (icon.id) 匹配
				for key, col := range actionMap {
					if len(req.Icon) > 0 && contains(req.Icon, key) {
						column = col
						break
					}
				}
			}
		}
		if err := tx.Model(&plant.UserProfile{}).Where("user_id = ?", userId).
			Update(column, gorm.Expr(column+" + 1")).Error; err != nil {
			return err
		}
		return nil
	})
}

func contains(s, substr string) bool {
	return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsStr(s, substr))
}

func containsStr(s, sub string) bool {
	for i := 0; i <= len(s)-len(sub); i++ {
		if s[i:i+len(sub)] == sub {
			return true
		}
	}
	return false
}

// 完成任务后异步执行 更新用户等级 sunlight
func (s *MyPlantService) handleCompleteTaskThenUpdateProfile(ctx context.Context, userId string) {
	//5.更新用户profile
	var profile plant.UserProfile
	if asyncErr := global.DB.Where("user_id = ?", userId).First(&profile).Error; asyncErr != nil {
		global.Logger.Error("完成任务异步操作-----查询用户profile失败", zap.Error(asyncErr))
	}
	totalSunlight := profile.TotalSunlight + 50
	updateData := map[string]interface{}{
		"care_count":       profile.CareCount + 1,
		"current_sunlight": profile.CurrentSunlight + 50,
		"total_sunlight":   totalSunlight,
	}
	//5.1 判断是否到达下个等级
	var currentLevel plant.LevelConfig
	levelErr := global.DB.Where("min_sunlight <= ?", totalSunlight).Order("min_sunlight DESC").First(&currentLevel).Error
	if levelErr != nil {
		global.Logger.Error("完成任务异步操作-----查询用户等级失败", zap.Error(levelErr))
	}
	updateData["level_id"] = currentLevel.Id
	//5.2 更新用户profile
	updateProfileErr := global.DB.Model(&plant.UserProfile{}).Where("user_id = ?", userId).Updates(updateData).Error
	if updateProfileErr != nil {
		global.Logger.Error("完成任务异步操作-----更新用户profile失败", zap.Error(updateProfileErr))
	}
}

// todo 完成任务后异步执行 处理徽章
func (s *MyPlantService) handleCompleteTaskThenHandleBadge(ctx context.Context, taskId, userId string) {
	//1.查询任务
	var task plant.CareTask
	if asyncErr := global.DB.Where("id = ?", taskId).First(&task).Error; asyncErr != nil {
		global.Logger.Error("完成任务异步操作-----查询任务失败", zap.Error(asyncErr))
	}
	//2.查询徽章
	var badges []plant.BadgeConfig
	if asyncErr := global.DB.Where("target_action = ?", task.TargetAction).Order("tier ASC").Find(&badges).Error; asyncErr != nil {
		global.Logger.Error("完成任务异步操作-----查询徽章失败", zap.Error(asyncErr))
	}
	//3.用户的徽章
	var userBadges []plant.UserBadge
	if asyncErr := global.DB.Where("user_id = ?", userId).Find(&userBadges).Error; asyncErr != nil {
		global.Logger.Error("完成任务异步操作-----查询用户徽章失败", zap.Error(asyncErr))
	}
	//4.用户个人资料

}
