package user

import (
	"bufio"
	"eta/eta_mini_ht_api/common/component/config"
	logger "eta/eta_mini_ht_api/common/component/log"
	"eta/eta_mini_ht_api/common/contants"
	"eta/eta_mini_ht_api/common/exception"
	authUtils "eta/eta_mini_ht_api/common/utils/auth"
	"eta/eta_mini_ht_api/controllers"
	"eta/eta_mini_ht_api/service/auth"
	"eta/eta_mini_ht_api/service/user"
	"fmt"
	"os"
	"strings"
)

type AuthController struct {
	controllers.BaseController
}

const ChinaAreaCode = "86"

// LoginReq  获取验证码请求
type LoginReq struct {
	VerifyCode string `json:"verifyCode"`
	Mobile     string `json:"mobile"`
	AreaCode   string `json:"areaCode"`
}

// Login 小程序登录接口
// @Summary 小程序用户登录
// @Description 用户通过微信小程序登录
// @Param   mobile     body    LoginReq  true        "登录请求体"
// @Success 200 {object} controllers.BaseResponse
// @router /login [post]
func (a *AuthController) Login() {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("登录失败")
		loginReq := new(LoginReq)
		a.GetPostParams(loginReq)
		if loginReq.AreaCode == "" || !checkValidAreaCode(loginReq.AreaCode) {
			a.FailedResult("登录失败", result)
			err = exception.New(exception.IllegalAreaCode)
			return
		}
		if loginReq.AreaCode == ChinaAreaCode && !authUtils.IsValidMobile(loginReq.Mobile) {
			a.FailedResult("登录失败", result)
			err = exception.New(exception.IllegalPhoneNumber)
			return
		}
		err = auth.CheckUser(loginReq.Mobile, loginReq.VerifyCode)
		if err != nil {
			a.FailedResult("登录失败", result)
			logger.Warn("验证码校验失败:%v", err)
			return
		}

		userInfo := a.Ctx.Input.GetData("user").(user.User)
		//注册用户或者登录
		var token string
		err = auth.BindMobile(userInfo.Id, loginReq.Mobile, loginReq.AreaCode)
		fmt.Println(token)
		if err != nil {
			a.FailedResult("登录失败", result)
			return
		}
		a.SuccessResult("登录成功", &LoginResp{
			//Token: token,
		}, result)
		return
	})
}

type LoginResp struct {
	Token string
}

// SmsCodeReq 获取验证码请求
type SmsCodeReq struct {
	Mobile   string `json:"mobile"`
	AreaCode string `json:"areaCode"`
}

// SMSCode 小程序手机验证码接口
// @Summary 获取手机验证码
// @Param   mobile   body    SmsCodeReq  true        "小程序手机验证码接口"
// @Success 200 {object} controllers.BaseResponse
// @Description 用户发送手机验证码
// @router /sendCode [post]
func (a *AuthController) SMSCode() {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("发送短信失败")
		mobile := new(SmsCodeReq)
		a.GetPostParams(mobile)
		if mobile.AreaCode == "" || !checkValidAreaCode(mobile.AreaCode) {
			a.FailedResult("登录失败", result)
			err = exception.New(exception.IllegalAreaCode)
			return
		}
		phoneNum := mobile.Mobile
		if mobile.AreaCode == ChinaAreaCode && !authUtils.IsValidMobile(phoneNum) {
			return result, exception.New(exception.IllegalPhoneNumber)
		}
		//发送短息
		err = auth.SendSMSCode(phoneNum)
		if err != nil {
			logger.Warn("发送短信失败:%v", err)
			return result, err
		}
		if err != nil {
			return result, err
		}
		result = &controllers.WrapData{Msg: "验证码发送成功"}
		return result, nil
	})
}

type RefreshTokenRes struct {
	Token        string `json:"token"`
	IsBindMobile int    `json:"isBindMobile"`
}

// RefreshToken 更新token
// @Summary 更新token
// @Success 200 {object} controllers.BaseResponse
// @Description 更新token
// @router /refreshToken [get]
func (a *AuthController) RefreshToken(code string) {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("刷新token失败")
		if code == "" {
			logger.Error("code不能为空")
			return result, exception.New(exception.WeChatCodeEmpty)
		}
		//刷新token
		token, isBindMobile, err := auth.RefreshToken(code)
		if err != nil {
			logger.Error("刷新token失败:%v", err)
			a.FailedResult("刷新token失败", result)
			return
		}
		a.SuccessResult("刷新token成功", RefreshTokenRes{
			Token:        token,
			IsBindMobile: isBindMobile,
		}, result)
		return
	})
}

// AreaCodes 小程序手机验证码接口
// @Summary 获取手机验证码
// @Param   mobile   body    SmsCodeReq  true        "小程序手机验证码接口"
// @Success 200 {object} controllers.BaseResponse
// @Description 用户发送手机验证码
// @router /areaCodes [get]
func (a *AuthController) AreaCodes() {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("获取区号失败")
		list, err := auth.GetAreaCodes()
		if err != nil {
			a.FailedResult("获取区号失败", result)
		}
		a.SuccessResult("获取区号成功", list, result)
		return
	})
}

type WXAppidResp struct {
	AppId string
}

// WXAppid 获取APPID
// @Summary 获取APPID
// @Success 200 {object} controllers.BaseResponse
// @Description 获取APPID
// @router /wxAppid [get]
func (a *AuthController) WXAppid() {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("获取AppId失败")
		appid := config.GetConfig(contants.WECHAT).(*config.WechatConfig).GetAppid()
		if err != nil {
			a.FailedResult("获取AppId失败", result)
		}
		a.SuccessResult("获取AppId成功", WXAppidResp{
			AppId: appid,
		}, result)
		return
	})
}

type FileResp struct {
	Content string
}

// Notice 获取注册须知
// @Summary 获取注册须知
// @Success 200 {object} controllers.BaseResponse
// @Description 获取注册须知
// @router /notice [get]
func (a *AuthController) Notice() {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("获取注册须知失败")
		fileConfig := config.GetConfig(contants.FILE).(*config.FileConfig)
		//publicKey := config.GetConfig(contants.FILE).(*config.FileConfig).GetPublicKey()
		noticeFile := fileConfig.GetNotice()
		content, err := readTextConfig(noticeFile)
		if err != nil {
			err = exception.New(exception.GetNoticeFileError)
			a.FailedResult("获取注册须知失败", result)
		}
		a.SuccessResult("获取注册须知成功", FileResp{
			Content: content,
		}, result)
		return
	})
}

// Disclaimer 获取免责声明
// @Summary 获取免责声明
// @Success 200 {object} controllers.BaseResponse
// @Description 获取免责声明
// @router /disclaimer [get]
func (a *AuthController) Disclaimer() {
	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
		result = a.InitWrapData("获取免责声明失败")
		fileConfig := config.GetConfig(contants.FILE).(*config.FileConfig)
		//publicKey := config.GetConfig(contants.FILE).(*config.FileConfig).GetPublicKey()
		disclaimerFile := fileConfig.GetDisclaimer()
		content, err := readTextConfig(disclaimerFile)
		if err != nil {
			a.FailedResult("获取免责声明失败", result)
		}
		a.SuccessResult("获取免责声明成功", FileResp{
			Content: content,
		}, result)
		return
	})
}

// 读取纯文本文件
func readTextConfig(filename string) (content string, err error) {
	file, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanLines)
	var lines []string
	for scanner.Scan() {
		line := scanner.Text()
		lines = append(lines, line)
	}
	err = scanner.Err()
	return strings.Join(lines, "\n"), nil
}

func checkValidAreaCode(areaCode string) bool {
	list := auth.GetValidAreaCodes()
	if areaCode == "" || len(list) == 0 {
		return false
	}
	for _, code := range list {
		if areaCode == code {
			return true
		}
	}
	return false
}
