/*
 * @description:登陆相关数据操作
 * @Author: CP
 * @Date: 2020-09-02 09:56:28
 * @FilePath: \construction_management\services\login_service.go
 */
package services

import (
	"errors"
	"log"
	"net/http"
	"net/url"
	"strconv"

	"github.com/kataras/iris/v12"
	"go.mod/comm"
	"go.mod/conf"
	"go.mod/dao"
	"go.mod/datasource"
	"go.mod/lib"
	"go.mod/web/viewmodels"
)

//定义项目用户Service接口
type LoginService interface {
	ValidRule(ctx iris.Context) (viewmodels.Login, error)
	ValidProjectAccount(viewmodels.Login, http.ResponseWriter) (*viewmodels.ProjectAccount, error)
	Out(ctx iris.Context) error
}

//返回service操作类
type loginService struct {
	projectAccountDao *dao.ProjectAccountDao
	projectDao        *dao.ProjectDao
}

//创建项目用户service
func NewLoginService() LoginService {
	return &loginService{
		projectAccountDao: dao.NewProjectAccountDao(datasource.InstanceDbMaster()),
		projectDao:        dao.NewProjectDao(datasource.InstanceDbMaster()),
	}
}

// 登陆验证
func (s *loginService) ValidRule(ctx iris.Context) (viewmodels.Login, error) {
	loginVaild := viewmodels.Login{}
	err := ctx.ReadJSON(&loginVaild)
	if err != nil {
		log.Println("ReadForm转换异常, error=", err)
		return loginVaild, err
	}

	err = loginVaild.Validate()
	if err != nil {
		log.Println("登录验证, error=", err)
		return loginVaild, err
	}
	return loginVaild, nil
}

// 验证项目用户登陆相关
func (s *loginService) ValidProjectAccount(loginData viewmodels.Login, writer http.ResponseWriter) (*viewmodels.ProjectAccount, error) {

	// 1-1.工程项目是否存在
	projectInfo := s.projectDao.GetCode(loginData.Code)
	if projectInfo.Id == 0 {
		return nil, errors.New("工程建设管理员还未创建项目，禁止登录")
	}
	// 1-2.获得项目管理员
	projectAdminInfo := s.projectAccountDao.Get(projectInfo.UserId, projectInfo.Id)
	if projectAdminInfo.Id == 0 {
		return nil, errors.New("工程建设管理员不存在，禁止登录")
	}

	// 2.验证登陆-临时
	projectAccountInfo := s.projectAccountDao.GetAccount(loginData.Account)

	// 验证密码-TODO
	Jlzf := lib.NewJlzf()
	err := Jlzf.LoginValid(loginData)
	if err != nil {
		return nil, err
	}

	// 加密用户标识
	identity, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.Id), conf.CookieSecret)
	if err != nil {
		return nil, err
	}
	// 加密项目标识
	projectId, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.ProjectId), conf.CookieSecret)
	if err != nil {
		return nil, err
	}

	digitalToken := comm.CreateSign(conf.CookieSecret + strconv.Itoa(projectAccountInfo.Id))

	// 设置cookie
	maxAge := 60 * 60 * 24 * 7
	params := url.Values{}
	params.Add("identity", identity)
	params.Add("attachedIdentity", projectId)
	params.Add("digitalToken", digitalToken)
	c := &http.Cookie{
		Name:     "cm",
		Value:    params.Encode(),
		Path:     "/",
		MaxAge:   maxAge,
		HttpOnly: true,
	}
	http.SetCookie(writer, c)

	// TODO--分布式会话--后续需要在加入

	viewAccountData := comm.MakeProjectAccountVM(projectAccountInfo)
	return &viewAccountData, nil
}

// TODO -替换jwt
// 验证项目用户登陆相关
// func (s *loginService) ValidProjectAccount(loginData viewmodels.Login, writer http.ResponseWriter) error {
// 	projectInfo := models.CmProject{}
// 	// 工程项目是否存在
// 	projectInfo.Code = loginData.Code
// 	s.projectDao.Get(&projectInfo)
// 	if projectInfo.Id == 0 {
// 		return errors.New("工程建设管理员还未创建项目，禁止登录")
// 	}
// 	// 获得项目用户
// 	projectAccountInfo := s.projectAccountDao.Get(projectInfo.UserId, projectInfo.Id)
// 	if projectAccountInfo.Id == 0 {
// 		return errors.New("工程建设管理员不存在，禁止登录")
// 	}
// 	// 验证密码-TODO
// 	Jlzf := lib.NewJlzf()
// 	err := Jlzf.LoginValid(loginData)
// 	if err != nil {
// 		return err
// 	}

// 	// 加密用户标识
// 	identity, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.Id), conf.CookieSecret)
// 	if err != nil {
// 		return err
// 	}
// 	// 加密项目标识
// 	projectId, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.ProjectId), conf.CookieSecret)
// 	if err != nil {
// 		return err
// 	}
// 	// jwt token
// 	token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
// 		// 根据需求，可以存一些必要的数据
// 		"identity": identity,
// 		"project":  projectId,
// 		// 签发人
// 		"iss": "cm",
// 		// 签发时间
// 		"iat": time.Now().Unix(),
// 		// 设定过期时间，便于测试，设置7天过期
// 		"exp": time.Now().Add(72 * time.Hour * time.Duration(1)).Unix(),
// 	})

// 	// 使用设置的秘钥，签名生成jwt字符串
// 	tokenString, _ := token.SignedString([]byte(conf.SignSecret))
// 	fmt.Println(tokenString)
// 	maxAge := 60 * 60 * 24 * 7
// 	// params := url.Values{}
// 	// params.Add("token", tokenString)
// 	c := &http.Cookie{
// 		Name:   "cm",
// 		Value:  tokenString, //params.Encode(),
// 		Path:   "/",
// 		MaxAge: maxAge,
// 		//HttpOnly: true,
// 	}
// 	http.SetCookie(writer, c)

// 	// TODO--分布式会话--后续需要在加入

// 	return nil
// }

// 登出
func (s *loginService) Out(ctx iris.Context) error {
	// 作废jwt token

	// 移除cookie
	ctx.RemoveCookie("cm")
	return nil
}

//fmt.Println(ctx.FormValues())

// list := ctx.FormValues()
// loginVaild := viewmodels.Login{}
// v := reflect.ValueOf(&loginVaild).Elem()
// for path, values := range list {
// 	//fmt.Println(path)
// 	//fmt.Println(values)
// 	if path != "csrf.Token" {

// 		v.FieldByName(Ucfirst(path)).Set(reflect.ValueOf(values[0]))

// 	}
// }
//fmt.Println(loginVaild)
// loginVaild := viewmodels.Login{
// 	Code:     ctx.FormValue("code"),
// 	Account:  ctx.FormValue("account"),
// 	Password: ctx.FormValue("password"),
// }

// // 加密用户标识 生成数字证书
// identity, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.Id), conf.CookieSecret)
// if err != nil {
// 	return err
// }
// digitalToken := comm.CreateSign(conf.CookieSecret + strconv.Itoa(projectAccountInfo.Id))

// // 设置cookie
// maxAge := 60 * 60 * 24 * 7
// params := url.Values{}
// params.Add("identity", identity)
// params.Add("digitalToken", digitalToken)
// c := &http.Cookie{
// 	Name:   "cm",
// 	Value:  params.Encode(),
// 	Path:   "/",
// 	MaxAge: maxAge,
// }
// http.SetCookie(writer, c)
