package model

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	account "github.com/fonchain_enterprise/micro-account/api/accountFiee"
	"github.com/fonchain_enterprise/micro-account/pkg/cache"
	"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
	"github.com/fonchain_enterprise/micro-account/pkg/common/utils"
	"github.com/fonchain_enterprise/micro-account/pkg/common/verifica"
	"github.com/fonchain_enterprise/micro-account/pkg/domain"
	"github.com/fonchain_enterprise/micro-account/pkg/m"
	"github.com/mozillazg/go-pinyin"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/plugin/soft_delete"
)

type Extend struct {
	JumpTo          string
	Lang            string
	CanScan         bool //是否可以扫码
	ResolutionRatio bool //是否固定分辨率
}

type Operator struct {
	ID   uint32 `json:"ID"`
	Name string `json:"name"`
}

// User 用户模型
type User struct {
	ID                uint `gorm:"primarykey"`
	CreatedAt         time.Time
	UpdatedAt         time.Time
	DeletedAt         soft_delete.DeletedAt `gorm:"column:deleted_at;type:int(11)" json:"deletedAt"`
	Domain            *string               `gorm:"size:50"`
	SubNum            string                `gorm:"column:sub_num;comment:用户编号" json:"subNum"`
	TelNum            string                `gorm:"column:tel_num;comment:" json:"telNum"`
	TelAreaCode       string                `gorm:"column:tel_area_code;comment:手机区号" json:"telAreaCode"`
	Status            int                   `gorm:"column:status;comment:状态 1:未实名 2:审核中 3:审核失败 4:审核通过" json:"status"`
	RegistrationTime  string                `gorm:"column:registration_time;comment:注册时间" json:"registrationTime"`
	AuditTime         string                `gorm:"column:audit_time;comment:审核时间" json:"auditTime"`
	RealNameID        *uint
	RealName          *RealName `gorm:"foreignKey:RealNameID" json:"RealName"`
	PasswordDigest    string
	NotPassRemarks    string `gorm:"column:not_pass_remarks;comment:不通过备注" json:"notPassRemarks"`
	Nickname          string `gorm:"column:nickname;comment:昵称" json:"nickname"`
	Language          string `gorm:"column:language;comment:语言" json:"language"`
	SubscriberNumber  string `gorm:"column:subscriber_number;comment:用户id" json:"subscriberNumber"`
	Email             string `gorm:"column:email;comment:邮箱" json:"email"`
	AbroadTel         string `gorm:"column:abroad_tel;comment:国外手机号" json:"abroadTel"`
	AbroadTelAreaCode string `gorm:"column:abroad_tel_area_code;comment:国外手机区号" json:"abroadTelAreaCode"`
}

const (
	PassWordCost        = 12          //密码加密难度
	Active       string = "active"    //激活用户
	NOTActive    string = "notactive" //未激活用户
	USERLEFT     string = "left"      //离职
)

var SendPhoneNum = map[string]string{}

func SetSendPhoneNUm(IsProd bool) {

	if IsProd == true {
		SendPhoneNum["13788998899"] = "15895559080"
	} else {
		SendPhoneNum["13788998899"] = "18362666451"
	}

	fmt.Println("是否是线上，同时手机号如何翻译", IsProd, SendPhoneNum)
}

func (j *Operator) Scan(src interface{}) error {
	return json.Unmarshal(src.([]byte), j)
}

func (j Operator) Value() (driver.Value, error) {
	v, err := json.Marshal(j)
	return string(v), err
}

func (j *Extend) Scan(src interface{}) error {
	return json.Unmarshal(src.([]byte), j)
}

func (j Extend) Value() (driver.Value, error) {
	v, err := json.Marshal(j)
	return string(v), err
}

func FormatExtend(extend *account.Extend) Extend {
	var res Extend
	res.JumpTo = extend.JumpTo
	res.Lang = extend.Lang
	res.ResolutionRatio = extend.ResolutionRatio
	res.CanScan = extend.CanScan
	return res
}

func FormatOperator(extend *account.Operator) Operator {
	var res Operator
	res.ID = extend.ID
	res.Name = extend.Name
	return res
}

// SetPassword 设置密码
//func (user *User) SetPassword(password string) error {
//	bytes, err := bcrypt.GenerateFromPassword([]byte(password), PassWordCost)
//	if err != nil {
//		return err
//	}
//	user.PasswordDigest = string(bytes)
//	return nil
//}
//
//// GetWorkYear 获取工作时间长度
//func (user *User) GetWorkYear() float32 {
//	if user.EnterDate == "" {
//		return 0
//	}
//
//	t, err := time.ParseInLocation("2006-01-02", user.EnterDate, time.Local)
//	if err != nil {
//		return 0
//	}
//
//	//if user.LeftDate != "" {
//	//
//	//	end, err := time.ParseInLocation("2006-01-02", user.LeftDate, time.Local)
//	//	if err == nil {
//	//		return utils.SubYearFromStartAndEnd(t, end)
//	//	}
//	//}
//
//	return utils.SubYearFromNowBefore(t)
//}

// ChangeNewTel 修改手机号
func (user *User) ChangeNewTel(code string) error {
	nowNewTelKey := redis_key.GetNowNewTelById(*user.Domain, strconv.Itoa(int(user.ID)))

	//0 校验当前修改到的手机号 以及账号唯一性
	newTelNumObj := cache.RedisClient.Get(nowNewTelKey)
	newTelNum := newTelNumObj.Val()

	if newTelNum == "" {
		return errors.New(m.Mobile_Wrong)
	}

	var count int64
	DB.Model(&User{}).Where(&User{TelNum: newTelNum, Domain: user.Domain}).Count(&count)

	if count > 0 {
		return errors.New(m.ACCOUNT_EXIST)
	}

	if newTelNum == user.TelNum {
		return nil
	}

	//检测验证码
	str := cache.RedisClient.Get(redis_key.GetChangeTelKey(*user.Domain, newTelNum, strconv.Itoa(int(user.ID))))

	if str.Val() == "" {
		return errors.New(m.Mobile_Not_Send)
	}

	if str.Val() != code {
		return errors.New(m.Mobile_Wrong_Code)
	}

	//修改完毕之后删除
	domain.DelRecordTelMsgCodeLogin(*user.Domain, newTelNum, strconv.Itoa(int(user.ID)))

	err := DB.Model(&user).Updates(&User{TelNum: newTelNum}).Error

	return err
}

func (user *User) NowNewTelNum() (string, error) {

	str := cache.RedisClient.Get(redis_key.GetNowNewTelById(*user.Domain, strconv.Itoa(int(user.ID))))
	if str.Val() == "" {
		return "", errors.New(m.Mobile_New_Tel_Over)
	}

	return str.Val(), nil

}

// SendNewTelMsg 给新手机号发送验证码
func (user *User) SendNewTelMsg(newTelNum, project string, signNo uint) error {
	telTodayNum := redis_key.GetAccountKeyCountToday(*user.Domain, newTelNum)
	if newTelNum == "" {
		return errors.New("新手机号不能为空")
	}

	if user.TelNum == newTelNum {
		return errors.New(m.Mobile_Not_Change)
	}

	if utils.CheckMobile(newTelNum) == false {
		return errors.New(m.Mobile_Wrong)
	}

	//0 限制频率 (一个账号一分钟少于一次 同一一天最多10条)
	fmt.Println(redis_key.GetOneMinuteKey(*user.Domain, newTelNum, strconv.Itoa(int(user.ID))))
	str := cache.RedisClient.Get(redis_key.GetOneMinuteKey(*user.Domain, newTelNum, strconv.Itoa(int(user.ID))))
	fmt.Println(str)

	if str.Val() != "" {
		return errors.New(m.Mobile_Sended)
	}

	if err := domain.CheckMsg(telTodayNum); err != nil {
		return errors.New(m.Mobile_Send_Over)
	}

	//1 执行发送 并且记录code
	code, err := verifica.SendMsgV2(newTelNum, project, signNo)

	if err != nil {
		return err
	}

	//2 记录发送
	err = domain.SetRecordTelMsgCodeLogin(*user.Domain, newTelNum, code, strconv.Itoa(int(user.ID)))

	return err
}

// CheckPassword 校验密码
func (user *User) CheckPassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(user.PasswordDigest), []byte(password))
	return err == nil
}

func DomainCount(domain string) int64 {

	var count int64

	//获取自己领导的部门
	DB.Model(&User{}).
		Where(&User{Domain: &domain}).Count(&count)

	return count
}

func RandList(domain string, limit int) ([]*User, int64) {

	var list []*User
	var count int64
	var departmentIds []uint

	//获取自己领导的部门
	searchObj := DB.Preload("RealName").
		Where(&User{Domain: &domain}).
		Limit(limit).
		Order("rand()")

	searchObj.Find(&list, departmentIds)

	DB.Model(&User{}).Where(&User{Domain: &domain}).Count(&count)

	return list, count
}

func SynInvitationCode(userId uint) error {

	//保存实名信息
	var user *User

	if err := DB.Model(&User{}).First(user, userId).Error; err != nil {
		return err
	}

	updateMap := map[string]interface{}{"invitation_code": utils.DecimalToAny(int(userId))}
	return DB.Model(&User{}).Where(&User{ID: userId}).Updates(updateMap).Error

}

func GetEnglishNameByName(nickName string) string {

	fmt.Println(strings.ReplaceAll("hello word", " ", ""))
	pinyinObj := pinyin.NewArgs()
	pinyinObj.Style = pinyin.Normal
	pinyinObj.Separator = ""
	result := pinyin.Pinyin(strings.ReplaceAll(nickName, " ", ""), pinyinObj)
	pinyinStr := ""
	for _, s := range result {
		fmt.Println(s)
		pinyinStr += s[0]
	}

	return strings.ReplaceAll(pinyinStr, " ", "")
}
