package service

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
	"youngee_b_api/consts"
	"youngee_b_api/db"
	"youngee_b_api/model/gorm_model"
	"youngee_b_api/model/http_model"
	"youngee_b_api/model/redis_model"
	"youngee_b_api/model/system_model"
	"youngee_b_api/redis"
	"youngee_b_api/util"

	"github.com/sirupsen/logrus"
)

var LoginAuth *loginAuth

func LoginAuthInit(config *system_model.Session) {
	auth := new(loginAuth)
	auth.sessionTTL = time.Duration(config.TTL) * time.Minute
	LoginAuth = auth
}

type loginAuth struct {
	sessionTTL time.Duration
}

func (l *loginAuth) AuthToken(ctx context.Context, token string) (*redis_model.Auth, error) {
	phone, err := l.parseToken(ctx, token)
	if err != nil {
		logrus.Debug("token格式错误:%+v", token)
		return nil, err
	}
	auth, err := l.getSessionAuth(ctx, phone)
	if err != nil {
		logrus.Debug("获取session redis错误: token:%+v,err:%+v", token, err)
		return nil, err
	}
	if auth.Token != token {
		logrus.Debug("获取session time过期错误: token:%+v", token)
		return nil, errors.New("auth failed")
	}
	return auth, nil
}

// AuthCode 判断此手机号是否有账号存在 鉴定验证码 用户信息存入redis 并返回Token
func (l *loginAuth) AuthCode(ctx context.Context, phone string, code string) (int, *http_model.CodeLoginData, error) {

	// 1. 验证码校验
	vcode, err := l.getSessionCode(ctx, phone)
	if err != nil {
		return 0, nil, err
	}
	fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, code)
	if vcode != code {
		// 验证码错误
		logrus.Debugf("[AuthCode] auth fail,phone:%+v", phone)
		return 1, nil, nil
	}

	// 2. 查询是否存在用户信息，存在则取出，不存在则注册并取出
	var userData *gorm_model.YounggeeUser
	userInfo, err := db.GetUserByPhone(ctx, phone)
	// fmt.Println("login_auth", user, err)
	if err != nil {
		// 数据库操作错误
		return 0, nil, err
	}
	if userInfo == nil {
		subUserInfo, subUserErr := db.GetSubUserByPhone(ctx, phone)
		if subUserErr != nil {
			return 0, nil, subUserErr
		}
		if subUserInfo == nil {
			// fmt.Println("子账号也不存在")
			// 账号不存在，则默认注册商家账号
			_, createEnterpriseErr := Enterprise.CreateEnterprise(ctx, phone)
			if createEnterpriseErr != nil {
				return 0, nil, createEnterpriseErr
			}
			enterpriseUserInfo, enterpriseUserErr := db.GetUserByPhone(ctx, phone)
			if enterpriseUserErr != nil {
				return 0, nil, enterpriseUserErr
			}
			userData = enterpriseUserInfo
			// fmt.Println("login_auth", user, err)
		} else {
			userData = subUserInfo
		}
	} else {
		userData = userInfo
	}

	token := l.getToken(ctx, phone)
	var jobData gorm_model.YounggeeJob
	var accountData gorm_model.YounggeeSubAccount
	var enterpriseUser gorm_model.Enterprise
	var loginUserData http_model.CodeLoginData
	var ifEnterprise int = 0

	// 3. 根据用户类型的不同补充信息
	// 若为商家用户
	if string(userData.Role) == consts.BRole {
		ifEnterprise = 1
		// fmt.Println("商家主账号")
		enterpriseUserInfo, enterpriseUserErr := db.GetEnterpriseByUID(ctx, userData.ID)
		if enterpriseUserErr != nil {
			return 0, nil, enterpriseUserErr
		}
		if enterpriseUserInfo != nil {
			enterpriseUser = *enterpriseUserInfo
			auth := &redis_model.Auth{
				Phone:        phone,
				ID:           userData.ID,
				User:         userData.User,
				Username:     userData.Username,
				RealName:     userData.RealName,
				Role:         userData.Role,
				Email:        userData.Email,
				Token:        token,
				EnterpriseID: enterpriseUserInfo.EnterpriseID,
			}
			if sessionErr := l.setSession(ctx, phone, auth); sessionErr != nil {
				fmt.Printf("setSession error\n")
				return 0, nil, sessionErr
			}
		}
	} else {
		// 若为商家子账号
		fmt.Printf("商家子账号")
		subAccountUserInfo, subAccountUserErr := db.FindSubAccountByPhone(ctx, phone)
		if subAccountUserErr != nil {
			return 0, nil, subAccountUserErr
		}
		if subAccountUserInfo != nil {
			accountData = *subAccountUserInfo
			auth := &redis_model.Auth{
				Phone:        phone,
				ID:           userData.ID,
				User:         userData.User,
				Username:     userData.Username,
				RealName:     userData.RealName,
				Role:         userData.Role,
				Email:        userData.Email,
				Token:        token,
				EnterpriseID: subAccountUserInfo.EnterpriseId,
			}

			jobInfo, jobErr := db.FindJobByJobId(ctx, subAccountUserInfo.JobId)
			if jobErr != nil {
				return 0, nil, jobErr
			}
			if jobInfo != nil {
				jobData = *jobInfo
				if sessionErr := l.setSession(ctx, phone, auth); sessionErr != nil {
					fmt.Printf("setSession error\n")
					return 0, nil, sessionErr
				}
			}

		}
	}

	if ifEnterprise == 1 {
		loginUserData = http_model.CodeLoginData{
			UserId:               userData.ID,
			Token:                token,
			Role:                 userData.Role,
			SubAccountId:         0,
			JobName:              "主账号无岗位",
			EnterpriseId:         enterpriseUser.EnterpriseID,
			WorkshopPermission:   "1",
			CooperatePermission:  "1",
			FinancialPermission:  "1",
			TaskcenterPermission: "1",
		}
	} else {
		loginUserData = http_model.CodeLoginData{
			UserId:               userData.ID,
			Token:                token,
			Role:                 userData.Role,
			SubAccountId:         accountData.SubAccountId,
			JobName:              jobData.JobName,
			EnterpriseId:         accountData.EnterpriseId,
			WorkshopPermission:   jobData.WorkshopPermission,
			CooperatePermission:  jobData.CooperatePermission,
			FinancialPermission:  jobData.FinancialPermission,
			TaskcenterPermission: jobData.TaskcenterPermission,
		}
	}

	return 0, &loginUserData, nil
}

// func (l *loginAuth) AuthPassword(ctx context.Context, phone string, password string) (string, error) {
// 	// 验证是否存在
// 	user, err := db.GetUserByPhone(ctx, phone)
// 	if err != nil {
// 		return "", err
// 	}
// 	// 验证正确性
// 	if user == nil || user.Role != consts.BRole || user.Password != l.encryptPassword(password) {
// 		// 登录失败
// 		logrus.Debugf("[AuthPassword] auth fail,phone:%+v", phone)
// 		return "", errors.New("auth fail")
// 	}
// 	token := l.getToken(ctx, phone)
// 	auth := &redis_model.Auth{
// 		Phone:    phone,
// 		ID:       user.ID,
// 		User:     user.User,
// 		Username: user.Username,
// 		RealName: user.RealName,
// 		Role:     user.Role,
// 		Email:    user.Email,
// 		Token:    token,
// 	}
// 	if err := l.setSession(ctx, phone, auth); err != nil {
// 		return "", err
// 	}
// 	return token, nil
// }

func (l *loginAuth) setSession(ctx context.Context, phone string, auth *redis_model.Auth) error {
	if authJson, err := json.Marshal(auth); err == nil {
		err = redis.Set(ctx, l.getRedisKey(phone), string(authJson), l.sessionTTL)
		if err == nil {
			return err
		}
	}
	return nil
}

func (l *loginAuth) getSessionCode(ctx context.Context, phone string) (string, error) {
	value, err := redis.Get(ctx, l.getRedisKey(phone))
	if err != nil {
		if err == consts.RedisNil {
			return "", fmt.Errorf("not found in redis,phone:%+v", phone)
		}
		return "", err
	}
	return value, nil
}

func (l *loginAuth) getSessionAuth(ctx context.Context, phone string) (*redis_model.Auth, error) {
	value, err := redis.Get(ctx, l.getRedisKey(phone))
	if err != nil {
		if err == consts.RedisNil {
			return nil, fmt.Errorf("not found in redis,phone:%+v", phone)
		}
		return nil, err
	}
	auth := new(redis_model.Auth)
	if err = json.Unmarshal([]byte(value), auth); err != nil {
		return nil, err
	}
	return auth, nil
}

func (l *loginAuth) getToken(ctx context.Context, phone string) string {
	timeSeed := strconv.FormatInt(time.Now().Unix(), 10)
	token := phone + "." + timeSeed + "." + util.MD5(phone, timeSeed, consts.AuthSalt)
	return token
}

func (l *loginAuth) parseToken(ctx context.Context, token string) (string, error) {
	parts := strings.Split(token, ".")
	if len(parts) == 3 {
		phone := parts[0]
		timeSeed := parts[1]
		if parts[2] == util.MD5(phone, timeSeed, consts.AuthSalt) {
			return phone, nil
		}
	}
	return "", errors.New("token invalid")
}

func (l *loginAuth) encryptPassword(password string) string {
	return util.MD5(password)
}

func (l *loginAuth) getRedisKey(key string) string {
	return fmt.Sprintf("%s%s", consts.SessionRedisPrefix, key)
}

func (l *loginAuth) SubAccountAuthCode(ctx context.Context, req *http_model.AddNewSubAccountRequest) (int, error) {

	// 验证码校验
	phoneNumber := req.PhoneNumber
	vCode, err := l.getSessionCode(ctx, phoneNumber)
	if err != nil {
		return 0, err
	}
	fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vCode, req.Code)
	if vCode != req.Code {
		// 验证码错误
		logrus.Debugf("[AuthCode] auth fail,phone:%+v", phoneNumber)
		return 1, nil
	}

	subAccountUserInfo, subAccountUserErr := db.FindSubAccountByPhone(ctx, phoneNumber)
	if subAccountUserErr != nil {
		return 0, subAccountUserErr
	}
	if subAccountUserInfo == nil {
		// 子账号不存在，则判断此手机号码是否被商家主账号注册
		bUser, bUserErr := db.GetUserByPhone(ctx, phoneNumber)
		if bUserErr != nil {
			return 0, bUserErr
		}
		if bUser == nil {
			createSubAccountErr := SubAccount.CreateSubAccount(ctx, req)
			if createSubAccountErr != nil {
				return 0, createSubAccountErr
			}
		} else {
			if bUser.AuthStatus != 1 {
				// 被商家主账户注册，未认证，则可以注册
				createSubAccountErr := SubAccount.CreateSubAccount(ctx, req)
				if createSubAccountErr != nil {
					return 0, createSubAccountErr
				}
			} else {
				return 2, nil
			}
		}
	} else {
		// 子账号存在，则无法注册
		logrus.Debugf("[AuthCode] subAccountExist,phone:%+v", phoneNumber)
		return 3, nil
	}
	return 0, nil
}

// UpdateEnterpriseAccountInfo 更新商家账号信息
func (l *loginAuth) UpdateEnterpriseAccountInfo(ctx context.Context, req *http_model.UpdateAccountInfoRequest) (*http_model.UpdateAccountInfoData, int, error) {

	var supplierUserInfo *http_model.UpdateAccountInfoData
	supplierUserInfo = &http_model.UpdateAccountInfoData{}
	supplierUserInfo.EnterpriseName = req.EnterpriseName
	supplierUserInfo.Avatar = req.Avatar
	supplierUserInfo.Phone = req.Phone
	supplierUserInfo.SubAccountName = req.SubAccountName

	if req.SubAccountId == 0 {
		// 商家主账号
		// 1. 若修改绑定手机号
		if req.Phone != "" {
			// 1.1. 校验验证码
			vCode, err := l.getSessionCode(ctx, req.Phone)
			if err != nil {
				return nil, 0, err
			}
			if vCode != req.Code {
				return nil, 1, nil
			}
			// 1.2. 手机号是否已经被其他主账号绑定
			enterpriseNum, enterpriseNumErr := db.CountEnterpriseUserByPhone(ctx, req.Phone)
			if enterpriseNumErr != nil {
				// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", supplierNumErr)
				return nil, 0, enterpriseNumErr
			}
			if enterpriseNum != 0 {
				return nil, 2, nil
			}
			// 1.3. 手机号是否被子账号绑定
			subAccountNum, SubAccountErr := db.CountSubAccountUserByPhone(ctx, req.Phone)
			if SubAccountErr != nil {
				// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", SubAccountErr)
				return nil, 0, SubAccountErr
			}
			if subAccountNum != 0 {
				return nil, 3, nil
			}
			// 1.4. 修改Enterprise信息
			var enterpriseInfo *gorm_model.Enterprise
			enterpriseInfo = &gorm_model.Enterprise{}
			enterpriseInfo.EnterpriseID = req.EnterpriseId
			enterpriseInfo.EnterpriseName = req.EnterpriseName
			enterpriseInfo.Avatar = req.Avatar
			enterpriseInfo.Phone = req.Phone
			updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo)
			if updateEnterpriseErr != nil {
				// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateEnterpriseErr)
				return nil, 0, updateEnterpriseErr
			}
			// 1.5. 修改User表信息
			enterpriseInfoQuery, enterpriseInfoQueryErr := db.GetEnterpriseByEnterpriseID(ctx, enterpriseInfo.EnterpriseID)
			if enterpriseInfoQueryErr != nil {
				// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", supplierInfoQueryErr)
				return nil, 0, enterpriseInfoQueryErr
			}
			if enterpriseInfoQuery != nil {
				var userInfo *gorm_model.YounggeeUser
				userInfo = &gorm_model.YounggeeUser{}
				userInfo.ID = enterpriseInfoQuery.UserID
				userInfo.Phone = enterpriseInfoQuery.Phone
				userInfo.Username = enterpriseInfoQuery.Phone
				updateUserInfoErr := db.UpdateUserById(ctx, userInfo)
				if updateUserInfoErr != nil {
					// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateUserInfoErr)
					return nil, 0, updateUserInfoErr
				}
			}

		} else {
			var enterpriseInfo *gorm_model.Enterprise
			enterpriseInfo = &gorm_model.Enterprise{}
			enterpriseInfo.EnterpriseID = req.EnterpriseId
			enterpriseInfo.EnterpriseName = req.EnterpriseName
			enterpriseInfo.Avatar = req.Avatar
			enterpriseInfo.Phone = req.Phone
			updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo)
			if updateEnterpriseErr != nil {
				// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateEnterpriseErr)
				return nil, 0, updateEnterpriseErr
			}
		}
	} else {
		// 商家子账号
		var subAccountInfo *gorm_model.YounggeeSubAccount
		subAccountInfo = &gorm_model.YounggeeSubAccount{}
		subAccountInfo.SubAccountType = 3
		subAccountInfo.EnterpriseId = req.EnterpriseId
		subAccountInfo.SubAccountId = req.SubAccountId
		subAccountInfo.SubAccountName = req.SubAccountName
		subAccountInfo.Avatar = req.Avatar
		subAccountInfo.PhoneNumber = req.Phone
		updateSubAccountErr := db.UpdateSubAccount(ctx, subAccountInfo)
		if updateSubAccountErr != nil {
			// log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateSubAccountErr)
			return nil, 0, updateSubAccountErr
		}
	}
	return supplierUserInfo, 0, nil
}

// UpdateEnterpriseContactInfo 更新商家联系方式
func (l *loginAuth) UpdateEnterpriseContactInfo(ctx context.Context, req *http_model.UpdateContactInfoRequest) (*http_model.UpdateContactInfoData, bool, error) {

	var contactInfo *http_model.UpdateContactInfoData
	contactInfo = &http_model.UpdateContactInfoData{}

	// 主账号
	if req.SubAccountId == 0 {
		// 1. 若更新联系电话则需要验证码校验
		if req.ContactPhone != "" {
			vcode, err := l.getSessionCode(ctx, req.ContactPhone)
			if err != nil {
				return nil, false, err
			}
			// fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, req.Code)
			if vcode != req.Code {
				// 验证码错误
				return nil, true, err
			}
			var enterpriseInfo *gorm_model.Enterprise
			enterpriseInfo = &gorm_model.Enterprise{}
			enterpriseInfo.ContactPhone = req.ContactPhone
			enterpriseInfo.EnterpriseID = req.EnterpriseId
			updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo)
			if updateEnterpriseErr != nil {
				// log.Infof("[updateEnterpriseErr] fail,err:%+v", updateEnterpriseErr)
				return nil, false, updateEnterpriseErr
			}
			contactInfo.ContactPhone = req.ContactPhone
		}

		// 2. 微信二维码更新
		if req.WechatQRCode != "" {
			var enterpriseInfo *gorm_model.Enterprise
			enterpriseInfo = &gorm_model.Enterprise{}
			enterpriseInfo.WechatQrCode = req.WechatQRCode
			enterpriseInfo.EnterpriseID = req.EnterpriseId
			updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo)
			if updateEnterpriseErr != nil {
				// log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateEnterpriseErr)
				return nil, false, updateEnterpriseErr
			}
			contactInfo.WechatQRCode = req.WechatQRCode

		}

		// 2. 微信号码更新
		if req.WechatNumber != "" {
			var enterpriseInfo *gorm_model.Enterprise
			enterpriseInfo = &gorm_model.Enterprise{}
			enterpriseInfo.WechatNumber = req.WechatNumber
			enterpriseInfo.EnterpriseID = req.EnterpriseId
			updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo)
			if updateEnterpriseErr != nil {
				// log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateEnterpriseErr)
				return nil, false, updateEnterpriseErr
			}
			contactInfo.WechatNumber = req.WechatNumber
		}
	} else {
		// 子账号
		// 1. 若更新联系电话则需要验证码校验
		if req.ContactPhone != "" {
			vcode, err := l.getSessionCode(ctx, req.ContactPhone)
			if err != nil {
				return nil, false, err
			}
			// fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, req.Code)
			if vcode != req.Code {
				// 验证码错误
				return nil, true, err
			}
			var subAccountInfo *gorm_model.YounggeeSubAccount
			subAccountInfo = &gorm_model.YounggeeSubAccount{}
			subAccountInfo.ContactPhone = req.ContactPhone
			subAccountInfo.SubAccountId = req.SubAccountId
			updateSupplierErr := db.UpdateSubAccount(ctx, subAccountInfo)
			if updateSupplierErr != nil {
				// log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateSupplierErr)
				return nil, false, updateSupplierErr
			}
			contactInfo.ContactPhone = req.ContactPhone
		}

		// 2. 微信二维码更新
		if req.WechatQRCode != "" {
			var subAccountInfo *gorm_model.YounggeeSubAccount
			subAccountInfo = &gorm_model.YounggeeSubAccount{}
			subAccountInfo.WechatQRCode = req.WechatQRCode
			subAccountInfo.SubAccountId = req.SubAccountId
			updateSupplierErr := db.UpdateSubAccount(ctx, subAccountInfo)
			if updateSupplierErr != nil {
				// log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateSupplierErr)
				return nil, false, updateSupplierErr
			}
			contactInfo.WechatQRCode = req.WechatQRCode

		}

		// 2. 微信号码更新
		if req.WechatNumber != "" {
			var subAccountInfo *gorm_model.YounggeeSubAccount
			subAccountInfo = &gorm_model.YounggeeSubAccount{}
			subAccountInfo.WechatNumber = req.WechatNumber
			subAccountInfo.SubAccountId = req.SubAccountId
			updateSupplierErr := db.UpdateSubAccount(ctx, subAccountInfo)
			if updateSupplierErr != nil {
				// log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateSupplierErr)
				return nil, false, updateSupplierErr
			}
			contactInfo.WechatNumber = req.WechatNumber
		}
	}
	return contactInfo, true, nil
}
