package user

import (
	"errors"
	logger "eta/eta_mini_ht_api/common/component/log"
	"eta/eta_mini_ht_api/common/exception"
	permissionService "eta/eta_mini_ht_api/domian/config"
	analystService "eta/eta_mini_ht_api/domian/financial_analyst"
	userService "eta/eta_mini_ht_api/domian/user"
	"eta/eta_mini_ht_api/service/config"
	"gorm.io/gorm"
	"sort"
	"sync"
	"time"
)

const (
	RiskValid   = "valid"
	RiskExpired = "expired"
	RiskUnTest  = "unTest"
)

type User struct {
	Id       int    `json:"id"`
	Username string `json:"username"`
	AreaCode string `json:"areaCode"`
	Mobile   string `json:"mobile"`
	OpenId   string `json:"openId,omitempty"`
}

type AnalystDetail struct {
	AnalystName  string `json:"AnalystName"`
	HeadImgUrl   string `json:"HeadImgUrl"`
	Introduction string `json:"Introduction"`
	Followed     string `json:"Followed"`
}

type UserProfile struct {
	Mobile          string `json:"mobile"`
	RiskLevel       string `json:"riskLevel"`
	RiskLevelStatus string `json:"riskLevelStatus"`
	UserName        string `json:"userName"`
}

func CheckUserRisk(permissionIds []int, isLogin bool, userId int) (filterPermissionIds []int, riskLevel string, err error) {
	if isLogin {
		userProfile, userErr := GetUserProfile(userId)
		if userErr != nil {
			if errors.Is(userErr, gorm.ErrRecordNotFound) {
				err = exception.New(exception.TemplateUserNotFound)
			} else {
				err = exception.New(exception.TemplateUserFoundFailed)
			}
			logger.Error("分页查询列表失败:%v", err)
			return
		}
		//获取产品风险等级
		if userProfile.RiskLevelStatus == RiskUnTest {
			logger.Warn("客户未做风险等级测评,mobile:%v", userProfile.Mobile)
		}
		if userProfile.RiskLevelStatus == RiskExpired {
			logger.Warn("客户风险等级已过期,mobile:%v", userProfile.Mobile)
		}
		var mapping permissionService.CustomerProductRiskMappingDTO
		if userProfile.RiskLevel != "" {
			mapping, err = permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel)
			if err != nil {
				logger.Error("查询产品风险等级映射失败:%v", err)
				return
			}
		}
		var permissionList []permissionService.PermissionDTO
		if len(permissionIds) == 0 {
			//获取所有设置风险等级的品种
			permissionList, err = permissionService.GetPermissionListWithRisk()
		} else {
			//更具id过滤设置了风险等级的品种
			permissionList, err = permissionService.GetPermissionListByIds(permissionIds)
		}
		permissionList = filterPermissionsByRisk(permissionList, mapping.ProductRiskLevel)
		riskLevel = mapping.ProductRiskLevel
		if len(permissionList) == 0 {
			return
		}
		for _, permission := range permissionList {
			filterPermissionIds = append(filterPermissionIds, permission.PermissionId)
		}
		return
	} else { //没有登录的时候展示所有设置了风险等级的品种报告,筛选的时候过滤传入ID中没有设置风险等级的品种
		var permissionList []permissionService.PermissionDTO
		if len(permissionIds) == 0 {
			//获取所有设置风险等级的品种
			permissionList, err = permissionService.GetPermissionListWithRisk()
		} else {
			//更具id过滤设置了风险等级的品种
			permissionList, err = permissionService.GetPermissionListByIds(permissionIds)
		}
		if err != nil {
			logger.Error("根据ID查询品种列表失败:%v", err)
		}
		for _, permission := range permissionList {
			filterPermissionIds = append(filterPermissionIds, permission.PermissionId)
		}
		//查询品种
		return
	}
}

func filterPermissionsByRisk(permissionList []permissionService.PermissionDTO, riskLevel string) (resultList []permissionService.PermissionDTO) {
	if riskLevel != "" {
		riskLevelNum, err := config.ParseRiskLevel(riskLevel)
		if err != nil {
			logger.Error("风险等级解析失败:%v", err)
			return
		}
		for _, permission := range permissionList {
			pRiskNum, riskErr := config.ParseRiskLevel(permission.RiskLevel)
			if riskErr != nil {
				logger.Error("解析品种风险等级失败 permission:%d,risk:%v", permission.PermissionId, permission.RiskLevel)
				continue
			}
			if pRiskNum <= riskLevelNum {
				resultList = append(resultList, permission)
			}
		}
	} else {
		resultList = permissionList
	}
	return
}
func convertUserDTOToProfile(dto userService.UserDTO) (profile UserProfile) {
	profile = UserProfile{
		Mobile:    dto.Mobile,
		RiskLevel: dto.RiskLevel,
		UserName:  dto.Username,
	}
	if profile.UserName == "" {
		profile.UserName = dto.Mobile
	}
	if dto.RiskLevel == "" {
		profile.RiskLevelStatus = RiskUnTest
		return
	}
	date, err := time.Parse(time.DateOnly, dto.RiskValidEndDate)
	if err != nil {
		logger.Error("解析日期失败:%v", err)
		profile.RiskLevelStatus = RiskExpired
		return
	}
	currentDate := time.Now().Truncate(24 * time.Hour)
	expiryDate := date.Truncate(24 * time.Hour)
	if expiryDate.Before(currentDate) {
		profile.RiskLevelStatus = RiskExpired
		return
	}
	profile.RiskLevelStatus = RiskValid
	return
}
func GetUserProfile(userId int) (userProfile UserProfile, err error) {
	userDTO, err := userService.GetUserById(userId)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			logger.Error("用户不存在,用户Id:%d", userId)
			err = exception.New(exception.TemplateUserNotFound)
		} else {
			logger.Error("获取用户信息失败:%v", err)
			err = exception.New(exception.TemplateUserFoundFailed)
		}
		return
	}
	userProfile = convertUserDTOToProfile(userDTO)
	return
}
func GetAnalystDetail(userId int, analystId int) (analystDetail AnalystDetail, err error) {
	analyst, err := analystService.GetAnalystById(analystId)
	if err != nil {
		logger.Error("研究员信息不存在:%v", err)
		err = exception.New(exception.AnalystNotFound)
	}
	analystDetail = convertToAnalystDetail(analyst)
	//研究员关注状态
	analystDetail.Followed = userService.GetFollowed(userId, analystId)
	return

}

func convertToAnalystDetail(dto analystService.FinancialAnalystDTO) AnalystDetail {
	return AnalystDetail{
		AnalystName:  dto.Name,
		HeadImgUrl:   dto.HeadImgUrl,
		Introduction: dto.Introduction,
	}

}
func FollowAnalystsByName(userId int, analystNames []string, followType string) (err error) {
	var followlist []userService.FollowDTO
	for _, analystName := range analystNames {
		FinancialAnalystDTO, followErr := analystService.GetAnalystByName(analystName)
		if followErr != nil {

			err = exception.New(exception.AnalystNotFound)
		}
		if FinancialAnalystDTO.Id == 0 || FinancialAnalystDTO.Name == "" {
			continue
		}
		followDTO := userService.FollowDTO{
			UserId:      userId,
			AnalystId:   FinancialAnalystDTO.Id,
			AnalystName: FinancialAnalystDTO.Name,
			FollowType:  followType,
		}
		followlist = append(followlist, followDTO)
	}
	err = userService.FollowAnalystsByName(userId, followlist, followType)
	if err != nil {
		logger.Error("批量关注研究员失败:%v", err)
		err = exception.New(exception.BatchFollowingAnalystFailed)
	}
	return
}
func CheckFollowStatusByNames(userId int, names []string) (list []userService.FollowDTO, err error) {
	list, err = userService.CheckFollowStatusByNames(userId, names)
	if err != nil {
		logger.Error("获取关注状态失败:%v", err)
		err = exception.New(exception.CheckFollowStatusByNamesFailed)
	}
	return
}
func FollowAnalyst(userId int, analystId int, followType string) (err error) {
	FinancialAnalystDTO, err := analystService.GetAnalystById(analystId)
	if err != nil {
		err = exception.New(exception.AnalystNotFound)
	}
	if FinancialAnalystDTO.Id == 0 || FinancialAnalystDTO.Name == "" {
		err = exception.New(exception.AnalystNotFound)
		return
	}
	followDTO := userService.FollowDTO{
		UserId:      userId,
		AnalystId:   analystId,
		AnalystName: FinancialAnalystDTO.Name,
		FollowType:  followType,
	}
	err = userService.FollowAnalyst(followDTO)
	if err != nil {
		logger.Error("关注研究员失败:%v", err)
		err = exception.New(exception.UserFollowAnalystFailed)
	}
	return
}
func GetFollowingAnalystList(userId int) (analysts []FollowAnalystDTO, err error) {
	logger.Info("用户ID:%d", userId)
	dtoList, err := userService.GetFollowingAnalystList(userId)
	if err != nil {
		logger.Error("获取关注列表失败:%v", err)
		err = exception.New(exception.GetFollowingAnalystListFailed)
		return
	}
	analysts, err = convertToAnalystList(dtoList)
	var wg sync.WaitGroup
	wg.Add(len(analysts))
	for i := 0; i < len(analysts); i++ {
		go func(followDTo *FollowAnalystDTO) {
			defer wg.Done()
			followDTo.NeedNotice = userService.NeedNotice(userId, followDTo.AnalystId)
			var analystsDTO analystService.FinancialAnalystDTO
			analystsDTO, err = analystService.GetAnalystById(followDTo.AnalystId)
			if err != nil {
				logger.Error("获取研究员信息失败")
			} else {
				followDTo.HeadImgUrl = analystsDTO.HeadImgUrl
			}
		}(&analysts[i])
	}
	wg.Wait()
	//排序
	sort.Slice(analysts, func(i, j int) bool {
		// 首先按 NeedNotice 排序
		if analysts[i].NeedNotice == analysts[j].NeedNotice {
			// 对于 NeedNotice 相同的情况下,进行倒序排列
			return analysts[i].FollowedTime.After(analysts[j].FollowedTime)
		}
		// NeedNotice 为 true 的排在 false 的前面
		return analysts[i].NeedNotice
	})
	//if err != nil {
	//	logger.Error("转换研究员列表失败:%v", err)
	//	err = exception.New(exception.TransferFollowingAnalystListFailed)
	//}
	return
}

func GetUnReadMessageList(userId int) (messages []userService.MyMessage, err error) {
	messages, err = userService.GetUnReadMessageList(userId)
	if err != nil {
		err = exception.New(exception.GetUserUnReadMsgFailed)
	}
	return
}
func ReadMessage(userId int, messageId int) bool {
	return userService.ReadMessage(userId, messageId)
}

func ReadMessages(userId int, analystId int) bool {
	return userService.ReadMessages(userId, analystId)
}

type FollowAnalystDTO struct {
	AnalystId    int       `json:"analystId"`
	AnalystName  string    `json:"analystName"`
	HeadImgUrl   string    `json:"headImgUrl"`
	FollowedTime time.Time `json:"followedTime"`
	NeedNotice   bool      `json:"needNotice"`
}

func convertToAnalystList(dtoList []userService.FollowDTO) (list []FollowAnalystDTO, err error) {
	for _, dto := range dtoList {
		analyst := FollowAnalystDTO{
			AnalystId:    dto.AnalystId,
			AnalystName:  dto.AnalystName,
			FollowedTime: dto.FollowedTime,
			NeedNotice:   false,
		}
		list = append(list, analyst)
	}
	return
}

func FollowAnalystByName(userId int, analystName string, followType string) (err error) {
	FinancialAnalystDTO, err := analystService.GetAnalystByName(analystName)
	if err != nil {
		err = exception.New(exception.AnalystNotFound)
	}
	if FinancialAnalystDTO.Id == 0 || FinancialAnalystDTO.Name == "" {
		err = exception.New(exception.AnalystNotFound)
		return
	}
	followDTO := userService.FollowDTO{
		UserId:      userId,
		AnalystId:   FinancialAnalystDTO.Id,
		AnalystName: FinancialAnalystDTO.Name,
		FollowType:  followType,
	}
	err = userService.FollowAnalyst(followDTO)
	if err != nil {
		logger.Error("关注研究员失败:%v", err)
		err = exception.New(exception.UserFollowAnalystFailed)
	}
	return
}
func FeedBack(userId int, mobile string, message string) (err error) {
	feedback := userService.FeedbackDTO{
		UserId:  userId,
		Mobile:  mobile,
		Message: message,
	}
	err = userService.FeedBack(feedback)
	if err != nil {
		err = exception.New(exception.FeedBackError)
	}
	return
}

func GetUserByMobile(mobile string) (user User, err error) {
	userDTO, err := userService.GetUserByMobile(mobile)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			err = exception.New(exception.TemplateUserNotFound)
		} else {
			err = exception.New(exception.TemplateUserFoundFailed)
		}
	}
	user = convertToUser(userDTO)
	return
}

func GetUserByOpenId(openId string) (user User, err error) {
	userDTO, err := userService.GetUserByOpenId(openId)
	if err != nil {
		return
	}
	user = convertToUser(userDTO)
	return
}

func convertToUser(userDTO userService.UserDTO) User {
	return User{
		Id:       userDTO.Id,
		Username: userDTO.Username,
		OpenId:   userDTO.OpenId,
		AreaCode: userDTO.AreaCode,
		Mobile:   userDTO.Mobile,
	}
}

func GetUserByTemplateUserId(templateUserId int) (officialUser userService.OfficialUserDTO, err error) {
	officialUser, err = userService.GetUserByTemplateUserId(templateUserId)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			err = exception.New(exception.OfficialUserNotFound)
			logger.Info("用户未开户:%v", templateUserId)
		} else {
			err = exception.NewWithException(exception.OfficialUserFoundError, err.Error())
			logger.Error("获取正式用户信息失败:%v", err)
		}
	}
	return
}