package routers

import (
	"errors"
	"fmt"
	"ops/models"
	"path"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/mitchellh/mapstructure"
)

func ApiUserInit() {
	//用户模块初始化init
	fmt.Println("users init")

	//创建admin用户
	var user models.TabUser_
	user.Name = "admin"

	if models.DB.Where(&user).First(&user).Error == nil {

	} else {
		//fmt.Println("用户不存在")

		//对密码加盐
		user.Salt = models.RandStr32()
		user.Pass = "adminpassword"
		models.HashUserPass(&user)
		models.DB.Create(&user) // 传入指针
	}

	//创建admin group
	var usergroup models.TabUserGroups_
	usergroup.Name = "admins"
	if models.DB.Where(&usergroup).First(&usergroup).Error == nil {

	} else {
		//fmt.Println("用户组不存在")
		models.DB.Create(&usergroup) // 传入指针
	}

	//创建用户与用户组绑定
	var usergroupbind models.TabUserGroupBinds_
	usergroupbind.UserID = user.ID
	usergroupbind.GroupID = usergroup.ID

	if models.DB.Where(&usergroupbind).First(&usergroupbind).Error == nil {

	} else {
		models.DB.Create(&usergroupbind) // 传入指针
	}

}

type From_user_add struct {
	Useremail string `json:"useremail"`
	Username  string `json:"username"`
	Userpass  string `json:"userpass"`
}

type From_user_login struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Remember bool   `json:"remember"`
}

type From_user_updateinfo struct {
	Username string `json:"username"`
	Remark   string `json:"remark"`
	Birthday string `json:"birthday"`
}

type From_user_changeemail struct {
	Newemail string `json:"newemail"`
}

type From_user_changepass struct {
	Oldpass string `json:"oldpass"`
	Newpass string `json:"newpass"`
}

func AuthenticationAuthorityFromCookie(c string) (*models.TabUser_, error) {

	if c != "" {
		cookie := models.TabCookie_{
			Value: c,
		}
		if models.DB.Where(&cookie).First(&cookie).Error == nil {
			//找到cookie，验证cookie有效性，以及更新cookie
			if models.CheckCookiesAndUpdate(&cookie) {
				//cookie有效
				//载入user
				user := models.TabUser_{
					ID: cookie.UserID,
				}
				models.DB.Where(&user).First(&user)
				return &user, nil
			} else {
				return nil, errors.New("cookie  过期")
			}
		} else {
			return nil, errors.New("cookie Not Fund")
		}
	} else {
		return nil, errors.New("cookie 参数错误")
	}
}

func GetUserInfoFromUserID(userID uint) (*models.TabUserInfo_){
	//通过id获取用户info

	if(userID <=0){
		return nil
	}

	//先查询用户是否存在
	var user models.TabUser_
	user.ID = userID

	if models.DB.Where(&user).First(&user).Error==nil{
		var userinfo models.TabUserInfo_
		userinfo.UserID=user.ID
		if models.DB.Where(&userinfo).First(&userinfo).Error==nil{
			return &userinfo
		}else{
			//无记录，创建一条
			userinfo.Username=user.Name
			userinfo.FirstName=user.Email
			userinfo.Birthdate=(time.Now())
			models.DB.Create(&userinfo)
			return &userinfo
		}
	}

	return nil



	
}

func AuthenticationAuthority(ctx *gin.Context) (bool, models.TabUser_, map[string]interface{}) {

	data, cookieval := SeparateData(ctx)
	//fmt.Println("cookieis" + cookieval)
	var user models.TabUser_
	if cookieval != "" {
		user_, error := AuthenticationAuthorityFromCookie(cookieval)
		if error == nil {
			user = *user_
			return true, user, data
		} else {
			return false, user, nil
		}

	} else {
		ReturnJson(ctx, "userCookieError", nil)
		return false, user, nil
	}

}



func ApiUser(r *gin.RouterGroup) {

	r.GET("/test", func(ctx *gin.Context) {
		ReturnJson(ctx, "apiOK", nil)
	})
	r.POST("/test", func(ctx *gin.Context) {
		ReturnJson(ctx, "apiOK", nil)
	})

	//get获取用户info
	r.GET("/getuserinfo/:id",func(ctx *gin.Context) {
		idStr := ctx.Param("id")
		id, err := strconv.Atoi(idStr)
		var redata map[string]interface{} = make(map[string]interface{})
		if err == nil {
			userinfo:=GetUserInfoFromUserID(uint(id))
			if(userinfo!=nil){
				redata["userinfo"]=*userinfo
			}
			
		}

		ReturnJson(ctx, "apiOK", redata)

	})

	//修改用户密码
	r.POST("/changePassword", func(ctx *gin.Context) {
		isAuth, user, data := AuthenticationAuthority(ctx)
		if isAuth {
			var jsonData From_user_changepass
			if err := mapstructure.Decode(data, &jsonData); err == nil {
				//验证旧密码
				//fmt.Println(user)
				//转换旧密码
				olduser := models.TabUser_{
					Pass: jsonData.Oldpass,
					Salt: user.Salt,
				}
				models.HashUserPass(&olduser)
				if olduser.Pass == user.Pass {
					//旧密码正确，更新新密码
					var userupdate models.TabUser_
					userupdate.Pass = jsonData.Newpass
					userupdate.Salt = models.RandStr32()
					models.HashUserPass(&userupdate)
					models.DB.Model(&user).Updates(&userupdate)
					ReturnJson(ctx, "apiOK", nil)
				} else {
					//旧密码错误
					ReturnJson(ctx, "userPassIncorrect", nil)
				}

			} else {
				ReturnJson(ctx, "jsonErr", nil)
			}

		}
	})

	//更新用户邮箱
	r.POST("/changeEmail", func(ctx *gin.Context) {
		isAuth, user, data := AuthenticationAuthority(ctx)
		if isAuth {
			var jsonData From_user_changeemail
			if err := mapstructure.Decode(data, &jsonData); err == nil {
				//判断新邮箱格式
				if models.IsEmailValid(jsonData.Newemail) {
					var userupdate models.TabUser_
					userupdate.Email = jsonData.Newemail
					models.DB.Model(&user).Updates(&userupdate)
					ReturnJson(ctx, "apiOK", nil)
				} else {
					ReturnJson(ctx, "userEmailFormatError", nil)

				}

			} else {
				ReturnJson(ctx, "jsonErr", nil)
			}
		}
	})

	//修改用户头像
	r.POST("/updateAvatar", func(ctx *gin.Context) {
		cookie := ctx.PostForm("cookie")
		user, err := AuthenticationAuthorityFromCookie(cookie)
		if err == nil {
			file, err := ctx.FormFile("file")
			if err == nil {
				if file.Filename != "" {
					//限制文件大小
					if file.Size > 512 {
						//头像裁剪过限制1M应该差不多
						if file.Size < 1048576 {

							//判断mime
							mimeType, err := models.GetFileMime(file)
							if err == nil {

								file_extname := models.ConfigsFile.AllowImageMime[mimeType]
								if file_extname != "" {

									//haxi文件

									file_hashi_name, err := models.SHA256HashFile(file)
									if err == nil {

										dst := path.Join(models.ConfigsFile.Pahts["avatar"], file_hashi_name+file_extname)

										var is_save_ok = false
										//判断文件是否存在避免重复保存
										if models.FileExists(dst) {
											//fmt.Println("文件存在")
											is_save_ok = true
											ReturnJson(ctx, "apiOK", nil)
										} else {
											//fmt.Println("文件no存在")
											ferr := ctx.SaveUploadedFile(file, dst)
											if ferr == nil {
												//文件保存成功
												//fmt.Print("save_ok")
												is_save_ok = true
												ReturnJson(ctx, "apiOK", nil)
											} else {
												//fmt.Print(ferr)
												ReturnJson(ctx, "postErr", nil)
											}

										}
										if is_save_ok {
											//修改数据库内容
											var user_info_fund models.TabUserInfo_
											user_info_fund.UserID = user.ID

											var user_update_avatar models.TabUserInfo_
											user_update_avatar.AvatarPath = file_hashi_name + file_extname

											//先查找是否有记录
											if models.DB.Where(&user_info_fund).First(&user_info_fund).Error == nil {
												//有记录，更新
												models.DB.Model(&user_info_fund).Updates(&user_update_avatar)
											} else {
												//无记录，创建
												user_update_avatar.UserID = user.ID
												models.DB.Create(&user_update_avatar)
											}

										}

									} else {
										ReturnJson(ctx, "postErr", nil)
									}

								} else {
									ReturnJson(ctx, "file_mime_err", nil)
								}

							} else {
								ReturnJson(ctx, "postErr", nil)
							}

						} else {
							ReturnJson(ctx, "file_size_err", nil)
						}
					} else {
						ReturnJson(ctx, "file_size_err", nil)
					}
				} else {
					ReturnJson(ctx, "file_name_err", nil)
				}
			} else {
				ReturnJson(ctx, "file_get_err", nil)
			}

		} else {
			ReturnJson(ctx, "userCookieError", nil)
		}

	})

	//更新用户info
	r.POST("/updateInfo", func(ctx *gin.Context) {
		isAuth, user, data := AuthenticationAuthority(ctx)
		if isAuth {
			var jsonData From_user_updateinfo

			if err := mapstructure.Decode(data, &jsonData); err == nil {
				// fmt.Println("updateinfo data is", jsonData)
				// fmt.Println(user)
				t, err := time.Parse("2006-01-02", jsonData.Birthday)
				if err == nil {
					var userinfo models.TabUserInfo_
					userinfo.UserID = user.ID

					var userinfoupdate models.TabUserInfo_
					userinfoupdate.UserID = user.ID
					userinfoupdate.CreatedAt = time.Now()
					userinfoupdate.Username = jsonData.Username
					userinfoupdate.Birthdate = t
					userinfoupdate.FirstName = jsonData.Remark

					//先查找是否有记录
					if models.DB.Where(&userinfo).First(&userinfo).Error == nil {
						//有记录，更新
						models.DB.Model(&userinfo).Updates(&userinfoupdate)
					} else {
						//无记录，创建
						models.DB.Create(&userinfoupdate) // 传入指针

					}

					ReturnJson(ctx, "apiOK", nil)

				} else {
					ReturnJson(ctx, "jsonErr", nil)
				}

			} else {
				ReturnJson(ctx, "jsonErr", nil)
			}
		}

	})

	//通过cookie获取用户info
	r.POST("/getinfo", func(ctx *gin.Context) {
		isAuth, user, _ := AuthenticationAuthority(ctx)
		if isAuth {
			//载入用户info

			//fmt.Println(userInfo)
			var redata map[string]interface{} = make(map[string]interface{})

			info:=GetUserInfoFromUserID(user.ID)
			redata["userInfo"] = *info

			user.Pass = ""
			user.Salt = ""
			redata["user"] = user

			ReturnJson(ctx, "apiOK", redata)

		}
	})
	//用户登陆
	r.POST("/login", func(ctx *gin.Context) {
		var loginuser From_user_login
		data, _ := SeparateData(ctx)
		if data != nil {
			if err := mapstructure.Decode(data, &loginuser); err == nil {
				if loginuser.Username != "" && loginuser.Password != "" {
					//传入的数据都ok，获取用户信息

					getuser := models.TabUser_{
						Name: loginuser.Username,
					}

					if models.DB.Where(&getuser).First(&getuser).Error == nil {
						//倒入数据
						user := models.TabUser_{
							Pass: loginuser.Password, //密码明文
							Salt: getuser.Salt,       //保存的盐制
						}
						//哈希密
						models.HashUserPass(&user)
						if user.Pass == getuser.Pass {
							//用户密码正确,生成cookie
							cookie := models.TabCookie_{
								UserID:    getuser.ID,
								Name:      "login",
								Value:     models.RandStr32(),
								CreatedAt: time.Now(),
								UpdatedAt: time.Now(),
								ExpiresAt: time.Now().Add(time.Duration(models.ConfigsUser.CookieTimeout) * time.Second), //计算过期时间,
								Remember:  loginuser.Remember,
							}
							models.DB.Create(&cookie) // 传入指针

							redata := map[string]interface{}{
								"cookie": cookie,
							}

							ReturnJson(ctx, "apiOK", redata)
						} else {
							ReturnJson(ctx, "userPassIncorrect", nil)
						}

					} else {
						//用户不存在
						ReturnJson(ctx, "userNameNoFund", nil)
					}

				} else {
					ReturnJson(ctx, "jsonErr", nil)
				}
			} else {
				ReturnJson(ctx, "jsonErr", nil)
			}

		} else {
			ReturnJson(ctx, "postErr", nil)
		}
	})

	//用户注册
	r.POST("/register", func(ctx *gin.Context) {
		//转换传进来的数据
		var jsonData From_user_add

		data, _ := SeparateData(ctx)

		if data != nil {
			if err := mapstructure.Decode(data, &jsonData); err == nil {
				//转换字段
				newUser := models.TabUser_{
					Name:  jsonData.Username,
					Email: jsonData.Useremail,
					Pass:  jsonData.Userpass, // 实际应替换为哈希值
					Date:  time.Now(),
					// Date 字段无需赋值，数据库会自动填充默认值
				}
				if newUser.Name != "" && newUser.Pass != "" && newUser.Email != "" {

					//用户名是唯一的，先读取是否有这个用户名
					var user models.TabUser_
					user.Name = newUser.Name

					if models.DB.Where(&user).First(&user).Error == nil {
						//fmt.Println("找到用户:", user.ID)
						ReturnJson(ctx, "userNameDup", nil)
					} else {
						//fmt.Println("用户不存在")

						//对密码加盐
						newUser.Salt = models.RandStr32()

						//对用户的密码进行哈希替换
						models.HashUserPass(&newUser)

						models.DB.Create(&newUser) // 传入指针

						//创建用户后写一个log

						models.LogAdd(ctx, "New user id:"+strconv.Itoa(int(newUser.ID)))

						ReturnJson(ctx, "apiOK", nil)
					}

				} else {
					ReturnJson(ctx, "jsonErr", nil)
				}

			} else {
				ReturnJson(ctx, "jsonErr", nil)

			}
		} else {
			ReturnJson(ctx, "postErr", nil)

		}

	})
}
