package user

import (
	"fmt"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/application/auth"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/application/factory"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/application/partnerInfo/query"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/application/partnerInfo/service"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/domain"
	domain_service_i "gitlab.fjmaimaimai.com/mmm-go/partner/pkg/domain/service"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/infrastructure/domain_service"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/infrastructure/pg/transaction"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/infrastructure/svr"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/log"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol"
	protocolx "gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol/auth"
	"strconv"
	"strings"
)

//用户信息
func UserInfo(header *protocol.RequestHeader, request *protocol.UserInfoRequest) (rsp *protocol.UserInfoResponse, err error) {
	var (
		partnerInfo            *domain.PartnerInfo
		transactionContext, _  = factory.CreateTransactionContext(nil)
		CompanyResponsitory, _ = factory.CreateCompanyRepository(transactionContext)
		PartnerInfoService, _  = factory.CreatePartnerInfoRepositoryIn(transactionContext)
		UsersRepository, _     = factory.CreateUsersRepository(transactionContext)
		ImInfoRepository, _    = factory.CreateImInfoRepository(transactionContext)
		company                *domain.Company
		user                   *domain.Users
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	rsp = &protocol.UserInfoResponse{}

	funcPartnerInfo := func() {
		if partnerInfo, err = PartnerInfoService.FindOne(map[string]interface{}{"id": header.UserId}); err != nil {
			err = protocol.NewErrWithMessage(502, err) //账号不存在
			return
		}
		if company, err = CompanyResponsitory.FindOne(map[string]interface{}{"id": header.CompanyId}); err != nil {
			return
		}
		rsp.User = protocol.User{
			Id:          partnerInfo.Id,
			PartnerName: partnerInfo.PartnerName,
			Phone:       partnerInfo.Account,
			CooperateCompany: protocol.Company{
				Id:    company.Id,
				Name:  company.Name,
				Phone: company.Phone,
			},
			JoinWay:       partnerInfo.PartnerCategoryInfo(),
			District:      map[string]interface{}{"id": partnerInfo.RegionInfo.RegionId, "name": partnerInfo.RegionInfo.RegionName},
			SerialNo:      partnerInfo.Id,
			CooperateTime: partnerInfo.CooperateTime.Unix() * 1000,
		}
		if len(partnerInfo.Salesman) > 0 {
			rsp.User.Salesman = map[string]interface{}{"uname": partnerInfo.Salesman[0].Name, "phone": partnerInfo.Salesman[0].Telephone}
		} else {
			rsp.User.Salesman = map[string]interface{}{}
		}
	}
	funcManagerInfo := func() {
		if user, err = UsersRepository.FindOne(map[string]interface{}{"id": header.UserId}); err != nil {
			err = protocol.NewErrWithMessage(502, err) //账号不存在
			return
		}
		if company, err = CompanyResponsitory.FindOne(map[string]interface{}{"id": header.CompanyId}); err != nil {
			return
		}
		rsp.User = protocol.User{
			Id:          user.Id,
			PartnerName: user.Name,
			Phone:       user.Phone,
			CooperateCompany: protocol.Company{
				Id:    company.Id,
				Name:  company.Name,
				Phone: company.Phone,
			},
			//JoinWay:       partnerInfo.PartnerCategoryInfo(),
			//District:      map[string]interface{}{"id": partnerInfo.RegionInfo.RegionId, "name": partnerInfo.RegionInfo.RegionName},
			//SerialNo:      partnerInfo.Id,
			//CooperateTime: partnerInfo.CooperateTime.Unix() * 1000,
		}
	}
	switch header.AdminType {
	case int(protocolx.AdminTypePartner):
		funcPartnerInfo()
		break
	case int(protocolx.AdminTypeManager):
		funcManagerInfo()
		break
	default:
		funcPartnerInfo()
		break
	}

	if imInfo, e := ImInfoRepository.FindOne(map[string]interface{}{"user_id": header.SimNum}); e == nil && imInfo != nil {
		rsp.User.ImToken = imInfo.ImToken
		rsp.User.AccountID, _ = strconv.ParseInt(imInfo.ImId, 10, 64)
		rsp.User.CsAccountID = fmt.Sprintf("%v", imInfo.CustomerImId)
	}
	err = transactionContext.CommitTransaction()
	return
}

//验证smscode
func CheckSmsCode(header *protocol.RequestHeader, request *protocol.CheckSmsCodeRequest) (rsp *protocol.CheckSmsCodeResponse, err error) {
	var (
		PartnerInfoService = service.NewPartnerInfoService(nil)
		partnerInfo        *domain.PartnerInfo
	)
	if partnerInfo, err = PartnerInfoService.GetPartnerInfo(&query.GetPartnerInfoQuery{Id: int(header.UserId)}); err != nil {
		err = protocol.NewErrWithMessage(502, err) //账号不存在
		return
	}
	if _, err = auth.CheckSmsCode(strings.TrimSpace(partnerInfo.Account), request.Captcha); err != nil {
		log.Error(err, partnerInfo.Account, request.Captcha)
		return
	}
	return
}

//修改手机号
func ChangePhone(header *protocol.RequestHeader, request *protocol.ChangePhoneRequest) (rsp *protocol.ChangePhoneResponse, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		UserAuthService       = CreateUserAuthService(header.AdminType, transactionContext)
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	if err = UserAuthService.ChangeUserPhone(header.UserId, request.Phone, request.OldPhone); err != nil {
		return
	}
	//TODO:修改完手机号 ,token失效,清理缓存
	err = transactionContext.CommitTransaction()
	return
}

//重置密码
func ResetPassword(header *protocol.RequestHeader, request *protocol.ResetPasswordRequest) (rsp *protocol.ResetPasswordResponse, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		UserAuthService       = CreateUserAuthService(header.AdminType, transactionContext)
	)
	rsp = &protocol.ResetPasswordResponse{}
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	if err = UserAuthService.ResetUserPassword(header.UserId, fmt.Sprintf("%v", header.SimNum), request.NewPwd); err != nil {
		return
	}
	err = transactionContext.CommitTransaction()
	return
}

//修改密码
func ChangePassword(header *protocol.RequestHeader, request *protocol.ChangePasswordRequest) (rsp *protocol.ChangePasswordResponse, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		UserAuthService       = CreateUserAuthService(header.AdminType, transactionContext)
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	rsp = &protocol.ChangePasswordResponse{}
	if err = UserAuthService.ChangeUserPassword(header.UserId, request.NewPwd, request.OldPwd, fmt.Sprintf("%v", header.SimNum)); err != nil {
		err = protocol.NewCustomMessage(1, err.Error())
		return
	}
	err = transactionContext.CommitTransaction()
	return
}

func UserInfoV2(header *protocol.RequestHeader, request *protocol.UserInfoRequest) (rsp interface{}, err error) {
	var (
		partnerInfo            *domain.PartnerInfo
		transactionContext, _  = factory.CreateTransactionContext(nil)
		CompanyResponsitory, _ = factory.CreateCompanyRepository(transactionContext)
		PartnerInfoService, _  = factory.CreatePartnerInfoRepositoryIn(transactionContext)
		UsersRepository, _     = factory.CreateUsersRepository(transactionContext)
		company                *domain.Company
		user                   *domain.Users
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	rsp = &protocol.UserInfoResponse{}

	type xcompany struct {
		Id    int64  `json:"id"`
		Name  string `json:"name"`
		Phone string `json:"phone"`
		//合作区域
		District interface{} `json:"district"`
		//合作编码
		SerialNo int64 `json:"serialNo"`
		//合作时间
		CooperateTime int64       `json:"cooperationTime"`
		Salesman      interface{} `json:"salesman"`
	}
	type xuser struct {
		Id int64 `json:"uid"`
		//用户名称
		PartnerName string `json:"uname"`
		//手机号
		Phone string `json:"phone"`
		//合作公司
		CooperateCompany xcompany `json:"company"`
	}
	rspMap := make(map[string]interface{})
	funcPartnerInfo := func() {
		if partnerInfo, err = PartnerInfoService.FindOne(map[string]interface{}{"id": header.UserId}); err != nil {
			err = protocol.NewErrWithMessage(502, err) //账号不存在
			return
		}
		if company, err = CompanyResponsitory.FindOne(map[string]interface{}{"id": header.CompanyId}); err != nil {
			return
		}

		u := xuser{
			Id:          partnerInfo.Id,
			PartnerName: partnerInfo.PartnerName,
			Phone:       partnerInfo.Account,
			CooperateCompany: xcompany{
				Id:            company.Id,
				Name:          company.Name,
				Phone:         company.Phone,
				SerialNo:      partnerInfo.Id,
				CooperateTime: partnerInfo.CooperateTime.Unix() * 1000,
				//JoinWay:       partnerInfo.PartnerCategoryInfo(),
				District: map[string]interface{}{"id": partnerInfo.RegionInfo.RegionId, "name": partnerInfo.RegionInfo.RegionName},
			},
		}
		if len(partnerInfo.Salesman) > 0 {
			u.CooperateCompany.Salesman = map[string]interface{}{"uname": partnerInfo.Salesman[0].Name, "phone": partnerInfo.Salesman[0].Telephone}
		} else {
			u.CooperateCompany.Salesman = map[string]interface{}{}
		}
		rspMap["user"] = u
		rsp = rspMap
	}
	funcManagerInfo := func() {
		if user, err = UsersRepository.FindOne(map[string]interface{}{"id": header.UserId}); err != nil {
			err = protocol.NewErrWithMessage(502, err) //账号不存在
			return
		}
		if company, err = CompanyResponsitory.FindOne(map[string]interface{}{"id": header.CompanyId}); err != nil {
			return
		}
		rspMap["user"] = xuser{
			Id:          user.Id,
			PartnerName: user.Name,
			Phone:       user.Phone,
			CooperateCompany: xcompany{
				Id:    company.Id,
				Name:  company.Name,
				Phone: company.Phone,
			},
		}
		rsp = rspMap
	}
	switch header.AdminType {
	case int(protocolx.AdminTypePartner):
		funcPartnerInfo()
		break
	case int(protocolx.AdminTypeManager):
		funcManagerInfo()
		break
	default:
		funcPartnerInfo()
		break
	}
	err = transactionContext.CommitTransaction()
	return
}

func changeUserInfo(userId int64, phone, password string, transactionContext *transaction.TransactionContext) (err error) {
	var (
		ucenterApiGateway  = svr.NewHttplibUCenterApiServiceGateway()
		UsersRepository, _ = factory.CreateUsersRepository(transactionContext)
		user               *domain.Users
	)
	if user, err = UsersRepository.FindOne(map[string]interface{}{"id": userId}); err != nil || user == nil {
		log.Error(err)
		err = fmt.Errorf("用户不存在")
		return
	}
	_, err = ucenterApiGateway.UpdateUser(user.OpenId, phone, password)
	return
}
func changeUserPhone(userId int64, phone, oldPhone string, transactionContext *transaction.TransactionContext) (err error) {
	var (
		ucenterApiGateway  = svr.NewHttplibUCenterApiServiceGateway()
		UsersRepository, _ = factory.CreateUsersRepository(transactionContext)
		user               *domain.Users
	)
	if user, err = UsersRepository.FindOne(map[string]interface{}{"id": userId}); err != nil || user == nil {
		log.Error(err)
		err = fmt.Errorf("用户不存在")
		return
	}
	if newUser, e := UsersRepository.FindOne(map[string]interface{}{"phone": phone}); e == nil || newUser != nil {
		err = protocol.NewErrWithMessage(2029, err)
		return
	}
	_, err = ucenterApiGateway.ChangePhone(phone, oldPhone)
	//if err != nil {
	//	_, err = transactionContext.PgTx.Exec("update users set phone=? where id=?", phone, userId)
	//}
	return
}
func changeUserPassword(userId int64, newPwd, oldPwd, phone string, transactionContext *transaction.TransactionContext) (err error) {
	var (
		ucenterApiGateway  = svr.NewHttplibUCenterApiServiceGateway()
		UsersRepository, _ = factory.CreateUsersRepository(transactionContext)
		user               *domain.Users
	)
	if user, err = UsersRepository.FindOne(map[string]interface{}{"id": userId}); err != nil || user == nil {
		log.Error(err)
		err = fmt.Errorf("用户不存在")
		return
	}
	_, err = ucenterApiGateway.ChangePassword(phone, newPwd, oldPwd)
	return
}

func CreateUserAuthService(adminType int, transactionContext *transaction.TransactionContext) domain_service_i.UserAuthService {
	if adminType == int(protocolx.AdminTypeManager) {
		return domain_service.NewPgManagerAuthService(transactionContext)
	}
	return domain_service.NewPgPartnerAuthService(transactionContext)
}

//TODO:修改密码/重置密码 清除uer_auth 缓存
//清除auth token
//auth := userAuth.NewRedisUserAuth(userAuth.WithUserId(header.UserId))
//if !auth.Exist() {
//	return
//}
//if err = auth.RemoveAuth(); err != nil {
//	log.Error(err)
//	err = protocol.NewErrWithMessage(4140, err)
//	return
//}