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) (string, *http_model.CodeLoginData, error) {

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

	// 2. 若无用户信息则注册
	var userData *gorm_model.YounggeeUser
	user, err := db.GetUserByPhone(ctx, phone)
	fmt.Println("login_auth", user, err)
	if err != nil {
		// 数据库操作错误
		return "", nil, err
	} else if user == nil {
		user, err := db.GetSubUserByPhone(ctx, phone)
		if user == nil {
			fmt.Println("子账号也不存在")
			// 账号不存在，则注册服务商与YG账号
			_, err = Supplier.CreateSupplier(ctx, phone)
			if err != nil {
				return "服务商账号创建失败", nil, err
			}
			user, err = db.GetUserByPhone(ctx, phone)
			userData = user
			fmt.Println("login_auth", user, err)
			if err != nil {
				return "", nil, err
			}
		} else {
			userData = user
		}
	} else if user != nil {
		fmt.Println("是服务商主账号")
		userData = user
	}

	token := l.getToken(ctx, phone)

	var jobData gorm_model.YounggeeJob
	var accountData gorm_model.YounggeeSubAccount
	var supplierUser gorm_model.YoungeeSupplier
	var ifsuppplier int = 0
	var ifsubaccount int = 0

	// 3. 根据用户类型的不同追加信息返回前端
	// 若为服务商用户
	if string(userData.Role) == "6" {
		fmt.Println("服务商主账号")
		supplier, err := db.GetSupplierByUserID(ctx, userData.ID)
		supplierUser = *supplier
		ifsuppplier = 1
		// fmt.Println(supplier)
		if err != nil {
			return "", nil, err
		}
		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: "32123",
			SupplierId:   supplier.SupplierId,
		}
		if err := l.setSession(ctx, phone, auth); err != nil {
			fmt.Printf("setSession error\n")
			return "", nil, err
		}
	} else {
		// 若为服务商子账号
		fmt.Printf("服务商子账号")
		subaccount, err := db.FindSubAccountByPhone(ctx, phone)
		accountData = *subaccount
		if err != nil {
			return "", nil, err
		}
		ifsubaccount = 1
		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,
			SupplierId:   subaccount.SupplierId,
			EnterpriseID: "32123",
		}

		job, err := db.FindJobByJobId(ctx, subaccount.JobId)
		jobData = *job
		if err := l.setSession(ctx, phone, auth); err != nil {
			fmt.Printf("setSession error\n")
			return "", nil, err
		}
	}

	var loginUserData http_model.CodeLoginData

	if ifsuppplier == 1 {
		loginUserData = http_model.CodeLoginData{
			UserId:               userData.ID,
			Token:                token,
			Role:                 userData.Role,
			SubAccountId:         -1,
			SupplierId:           supplierUser.SupplierId,
			JobName:              "-1",
			EnterpriseId:         "-1",
			CommercialCenter:     "-1",
			CooperatePermission:  "-1",
			FinancialPermission:  "-1",
			CommercialManagement: "-1",
		}
	} else if ifsubaccount == 1 {
		loginUserData = http_model.CodeLoginData{
			UserId:               userData.ID,
			Token:                token,
			Role:                 userData.Role,
			SubAccountId:         accountData.SubAccountId,
			JobName:              jobData.JobName,
			SupplierId:           accountData.SupplierId,
			EnterpriseId:         accountData.EnterpriseId,
			CommercialCenter:     jobData.CommercialCenter,
			CooperatePermission:  jobData.CooperatePermission,
			FinancialPermission:  jobData.FinancialPermission,
			CommercialManagement: jobData.CommercialManagement,
		}
	}
	fmt.Println("finish: ", loginUserData)
	return "", &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, phone string, code string) (string, error) {
	user, err := db.FindSubAccountByPhone(ctx, phone)
	phoneNumber := phone
	fmt.Println("login_auth", user, err)
	if err != nil {
		// 数据库错误
		return "数据库错误", err
	} else if user == nil {
		// 账号不存在，则判断此手机号码是否被服务商主账号注册
		user, err := db.GetUserByPhone(ctx, phoneNumber)
		if err != nil {
			// 数据库操作错误
			return "", err
		} else if user == nil {
			// 没有被服务商主账户注册，则可以注册
			vcode, err := l.getSessionCode(ctx, phoneNumber)
			if err != nil {
				return "session err", err
			}
			fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, code)
			if vcode != code {
				// 验证码错误
				logrus.Debugf("[AuthCode] auth fail,phone:%+v", phone)
				return "验证码有误", errors.New("auth fail")
			}
			return "1", err
		} else if string(user.Role) == "6" {
			if user.AuthStatus == 1 {
				// 被服务商主账户注册，未认证，则可以注册
				vcode, err := l.getSessionCode(ctx, phoneNumber)
				if err != nil {
					return "session err", err
				}
				fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, code)
				if vcode != code {
					// 验证码错误
					logrus.Debugf("[AuthCode] auth fail,phone:%+v", phone)
					return "验证码有误", errors.New("auth fail")
				}
				return "1", err
			} else {
				return "已认证的主账号存在", errors.New("auth fail")
			}
		}
	} else if user != nil {
		// 子账号存在，则无法注册
		logrus.Debugf("[AuthCode] auth fail,phone:%+v", phone)
		return "子账号存在", errors.New("auth fail")
	}
	return "", nil

}
