package domain

import (
	"context"
	"fmt"
	"github.com/samber/lo"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool"
	"time"
)

type User struct {
	Id           int64   `json:"id,omitempty"`           // 用户ID
	CompanyId    int64   `json:"companyId,omitempty"`    // 公司ID
	DepartmentId int64   `json:"departmentId,omitempty"` // 部门ID
	Roles        []int64 `json:"roleId,omitempty"`       // 角色
	Flag         int     `json:"flag,omitempty"`         // 标识 1:管理员 2:普通用户 (有绑定角色是管理员)
	Name         string  `json:"name,omitempty"`         // 名称
	PinYinName   string  `json:"pin_yin_name"`           // 拼音名
	Avatar       string  `json:"avatar,omitempty"`       // 头像
	Phone        string  `json:"phone,omitempty"`        // 手机号 唯一
	Position     string  `json:"position,omitempty"`     // 职位
	Enable       int     `json:"enable,omitempty"`       // 启用状态 1:启用 2:禁用
	AuditStatus  int     `json:"auditStatus,omitempty"`  // 审核状态 0:待审核 1:审核通过 2:拒绝
	AuditAt      int64   `json:"auditAt,omitempty"`      // 审核时间
	Follower     []int64 `json:"followers,omitempty"`    // 关注我的人 (冗余)
	Following    []int64 `json:"following,omitempty"`    // 我关注的人 (冗余)
	Departments  []int64 `json:"departments,omitempty"`  // 所属部门
	AccountFrom  string  `json:"accountFrom,omitempty"`  // 账号来源 后台新增、扫码注册
	CreatedAt    int64   `json:"createdAt,omitempty"`
	UpdatedAt    int64   `json:"updatedAt,omitempty"`
	DeletedAt    int64   `json:"deletedAt,omitempty"`
	Version      int     `json:"version,omitempty"`
}

type UserRepository interface {
	Insert(ctx context.Context, conn transaction.Conn, dm *User) (*User, error)
	Update(ctx context.Context, conn transaction.Conn, dm *User) (*User, error)
	UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *User) (*User, error)
	Delete(ctx context.Context, conn transaction.Conn, dm *User) (*User, error)
	FindOne(ctx context.Context, conn transaction.Conn, id int64) (*User, error)
	FindOneByCompanyIdAndPhone(ctx context.Context, conn transaction.Conn, companyId int64, phone string, status []int) (*User, error)
	Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*User, error)
	FindByCompanyRoles(ctx context.Context, conn transaction.Conn, companyId int64, roles []int64, queryOptions map[string]interface{}) (int64, []*User, error)
	FindDepartmentUsers(ctx context.Context, conn transaction.Conn, companyId int64, queryOptions map[string]interface{}) (int64, []*User, error)
	FindCompanyPositions(ctx context.Context, conn transaction.Conn, companyId int64, queryOptions map[string]interface{}) (int64, []*User, error)
}

func (m *User) Identify() interface{} {
	if m.Id == 0 {
		return nil
	}
	return m.Id
}

const (
	UserAuditStatusWait   = 0 // 审核中
	UserAuditStatusPassed = 1 // 审核通过
	UserAuditStatusReject = 2 // 审核拒绝
)

const (
	LoginTypeWechatLogin        string = "wechat-login"         // 微信登录
	LoginTypeWechatPhoneLogin   string = "wechat-phone-login"   // 微信手机号登录
	LoginTypePhonePasswordLogin string = "phone-password-login" // 手机密码登录
	LoginTypePhoneSmsCodeLogin  string = "phone-sms-code-login" // 手机验证码登录
)

const (
	UserEnable  = 1
	UserDisable = 2
)

const (
	AccountFromSearchJoin = "搜索添加"
	AccountFromQr         = "扫码注册"
	AccountFromMr         = "后台新增"
)

const (
	UserAdmin  = 1
	UserCommon = 2
)

func (m *User) Audit(status int) error {
	if !lo.Contains([]int{UserAuditStatusWait, UserAuditStatusPassed, UserAuditStatusReject}, status) {
		return fmt.Errorf("unknown status:%d", status)
	}
	if m.AuditStatus != UserAuditStatusWait {
		return fmt.Errorf("用户不是在待审核状态")
	}
	m.AuditStatus = status
	m.AuditAt = time.Now().Unix()
	return nil
}

// Follow 关注
func (m *User) Follow(targetUser *User) error {
	if lo.Contains(m.Following, targetUser.Id) {
		return fmt.Errorf("已关注用户%v", targetUser.Name)
	}
	m.Following = append(m.Following, targetUser.Id)
	if !lo.Contains(targetUser.Follower, m.Id) {
		targetUser.Follower = append(targetUser.Follower, m.Id)
	}
	return nil
}

// Unfollow 取消关注
func (m *User) Unfollow(targetUser *User) error {
	m.Following = lo.Without(m.Following, targetUser.Id)
	targetUser.Follower = lo.Without(targetUser.Follower, m.Id)
	return nil
}

// AddRole 添加角色
func (m *User) AddRole(roleId int64) {
	if lo.Contains(m.Roles, roleId) {
		return
	}
	m.Roles = append(m.Roles, roleId)
	m.Flag = lo.Ternary(len(m.Roles) > 0, UserAdmin, UserCommon)
}

// RemoveRole 移除角色
func (m *User) RemoveRole(roleId int64) {
	if !lo.Contains(m.Roles, roleId) {
		return
	}
	m.Roles = lo.Without(m.Roles, roleId)
}

func (m *User) WithName(name string) *User {
	m.Name = name
	m.PinYinName = tool.ToPinYin(name, " ")
	return m
}

func (m *User) IsFollowed(userId int64) bool {
	return lo.Contains(m.Following, userId)
}

// IsFriend 如果是好友,为互相关注
func (m *User) IsFriend(userId int64) bool {
	return lo.Contains(m.Following, userId) && lo.Contains(m.Follower, userId)
}

type (
	LoginCreator interface {
		WechatLogin(r WechatLoginRequest) (*LoginInfo, error)
		PhonePasswordLogin(phone string, password string) (*LoginInfo, error)
		PhoneSmsCodeLogin(phone string, code string) (*LoginInfo, error)
		WechatPhoneLogin(r WechatLoginRequest) (*LoginInfo, error)
	}
	WechatLoginRequest struct {
		Code          string // 授权码
		EncryptedData string // 包括敏感数据在内的完整用户信息的加密数据
		IV            string // 加密算法的初始向量
	}
	LoginInfo struct {
		User    *User
		Phone   string
		Message string
		OpenId  string
	}
)