package user

import (
	"encoding/json"
	"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/application/userAuth"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/constant"
	"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/log"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol"
	protocolx "gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol/auth"
	userx "gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol/user"
	"strconv"
	"strings"
)

func UserInfo(header *protocol.RequestHeader, request *protocol.UserInfoRequest) (rsp *protocol.UserInfoResponse, err error) {
	var (
		partnerInfo           *domain.PartnerInfo
		transactionContext, _ = factory.CreateTransactionContext(nil)
		CompanyRepository, _  = 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 = CompanyRepository.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 = CompanyRepository.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,
			},
		}
	}
	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 {
		err = protocol.NewCustomMessage(1, err.Error())
		return
	}

	err = transactionContext.CommitTransaction()
	return
}

// ChangePhoneAllCompany 修改手机号,强制退出登录
func ChangePhoneAllCompany(header *protocol.RequestHeader, request *protocol.ChangePhoneAllCompanyRequest) (rsp *protocol.ChangePhoneAllCompanyResponse, 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 request.Module == "employee" && request.Action == "changePhoneAllCompany" {
		var oldPhone string
		var newPhone string
		var data map[string]interface{}

		err := json.Unmarshal([]byte(request.Data), &data)
		if err != nil {
			return nil, err
		}

		if value, ok := data["old_phone"]; ok {
			oldPhone = value.(string)
		}
		if value, ok := data["new_phone"]; ok {
			newPhone = value.(string)
		}

		if err = UserAuthService.ChangeUserPhone(header.UserId, newPhone, oldPhone); err != nil {
			err = protocol.NewCustomMessage(1, err.Error())
			return nil, err
		}

		//注销凭证
		errRemoveAuth := userAuth.NewRedisUserCredential(oldPhone).RemoveAuth()
		if errRemoveAuth != nil {
			log.Error(err)
			return nil, err
		}

		//注销token
		id, _ := strconv.Atoi(oldPhone)
		uAuth := userAuth.NewRedisUserAuth(userAuth.WithUserId(int64(id)))
		if !uAuth.Exist() {
			return nil, nil
		}
		if err = uAuth.RemoveAuth(); err != nil {
			log.Error(err)
			return nil, err
		}
	}

	err = transactionContext.CommitTransaction()
	return nil, err
}

//重置密码
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, request.Phone, request.NewPwd); err != nil {
		err = protocol.NewCustomMessage(1, err.Error())
		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, request.Phone); 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)
		CompanyRepository, _  = factory.CreateCompanyRepository(transactionContext)
		PartnerInfoService, _ = factory.CreatePartnerInfoRepositoryIn(transactionContext)
		UsersRepository, _    = factory.CreateUsersRepository(transactionContext)
		company               *domain.Company
		user                  *domain.Users
		//loginSvr              = domain_service.NewPgLoginService(transactionContext)
	)

	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}

	defer func() {
		transactionContext.RollbackTransaction()
	}()

	rsp = &protocol.UserInfoResponse{}
	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 = CompanyRepository.FindOne(map[string]interface{}{"id": header.CompanyId}); err != nil {
			return
		}

		var miniProgram map[string]interface{}

		if len(company.Applets) > 0 {
			if company.Applets[0].Valid() {
				miniProgram = make(map[string]interface{})
				miniProgram["webpageUrl"] = "www.baidu.com"
				miniProgram["userName"] = company.Applets[0].Id
				miniProgram["path"] = fmt.Sprintf("%v?inviter_id=%v&company_id=%v", company.Applets[0].URL, partnerInfo.Id, partnerInfo.CompanyId)
				miniProgram["hdImageUrl"] = constant.SHARE_SHOP_PREVIEW_IMADGE
				if len(company.Applets[0].ImageUrl) > 0 {
					miniProgram["hdImageUrl"] = company.Applets[0].ImageUrl
				}
				miniProgram["title"] = company.Applets[0].Name
			}
		}

		u := userx.User{
			Id:          partnerInfo.Id,
			PartnerName: partnerInfo.PartnerName,
			Phone:       partnerInfo.Account,
			CooperateCompany: userx.Company{
				Id:               company.Id,
				Name:             company.Name,
				Phone:            company.Phone,
				SerialNo:         partnerInfo.Id,
				CareerSerialNo:   "",
				BusinessSerialNo: "",
				DevelopSerialNo:  "",
				AppSerialNo:      "",
				CooperateTime:    partnerInfo.CooperateTime.Unix() * 1000,
				MiniProgram:      miniProgram,
				District:         map[string]interface{}{"id": partnerInfo.RegionInfo.RegionId, "name": partnerInfo.RegionInfo.RegionName},
			},
		}

		// 获取编号
		for _, partnerCategoryInfo := range partnerInfo.PartnerCategoryInfos {
			if partnerCategoryInfo.Id == 1 {
				u.CooperateCompany.CareerSerialNo = partnerCategoryInfo.Code
			} else if partnerCategoryInfo.Id == 2 {
				u.CooperateCompany.BusinessSerialNo = partnerCategoryInfo.Code
			} else if partnerCategoryInfo.Id == 3 {
				u.CooperateCompany.DevelopSerialNo = partnerCategoryInfo.Code
			} else if partnerCategoryInfo.Id == 4 {
				u.CooperateCompany.AppSerialNo = partnerCategoryInfo.Code
			}
		}

		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 = CompanyRepository.FindOne(map[string]interface{}{"id": header.CompanyId}); err != nil {
			return
		}

		rspMap["user"] = userx.User{
			Id:          user.Id,
			PartnerName: user.Name,
			Phone:       user.Phone,
			CooperateCompany: userx.Company{
				Id:          company.Id,
				Name:        company.Name,
				Phone:       company.Phone,
				MiniProgram: nil,
			},
		}

		rsp = rspMap
	}

	//判断是否高管
	//phone := strconv.Itoa(header.SimNum)
	//ok, _ := loginSvr.CheckIsSenior(phone, header.CompanyId)

	switch header.AdminType {
	case int(protocolx.AdminTypePartner):
		funcPartnerInfo()
		break
	case int(protocolx.AdminTypeManager):
		funcManagerInfo()
		break
	default:
		funcPartnerInfo()
		break
	}

	err = transactionContext.CommitTransaction()
	return
}

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