package gmodel

import (
	"context"
	"encoding/json"
	"fmt"

	"fusenapi/utils/auth"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"
)

// TODO: 使用model的属性做你想做的

type UserBasicInfoForSave struct {
	ID                   uint   `gorm:"primary_key" json:"id"`
	FirstName            string `gorm:"-" json:"first_name"`
	LastName             string `gorm:"-" json:"last_name"`
	Mobile               string `gorm:"-" json:"mobile"`
	Company              string `gorm:"-" json:"company"`
	IsOrderStatusEmail   int64  `gorm:"-" json:"is_order_status_email"`
	IsEmailAdvertisement int64  `gorm:"-" json:"is_email_advertisement"`
	IsOrderStatusPhone   int64  `gorm:"-" json:"is_order_status_phone"`
	IsPhoneAdvertisement int64  `gorm:"-" json:"is_phone_advertisement"`
	Type                 int64  `gorm:"-" json:"type"`
	IsOpenRender         int64  `gorm:"-" json:"is_open_render"`
	IsLowRendering       int64  `gorm:"-" json:"is_low_rendering"`
	IsRemoveBg           int64  `gorm:"-" json:"is_remove_bg"`
}

func (u *FsUserModel) FindUserByEmail(ctx context.Context, emailname string) (resp FsUser, err error) {
	err = u.db.WithContext(ctx).Model(&FsUser{}).Where("`email` = ? and is_del = ?", emailname, 0).Take(&resp).Error
	return resp, err
}

func (u *FsUserModel) FindUserById(ctx context.Context, Id int64) (resp FsUser, err error) {
	err = u.db.WithContext(ctx).Model(&FsUser{}).Where("`id` = ? and is_del = ?", Id, 0).Take(&resp).Error
	return resp, err
}

func (u *FsUserModel) FindUserByGoogleId(ctx context.Context, Id int64) (resp FsUser, err error) {
	err = u.db.WithContext(ctx).Model(&FsUser{}).Where("`google_id` = ? and is_del = ?", Id, 0).Take(&resp).Error
	return resp, err
}

func (u *FsUserModel) Transaction(ctx context.Context, fc func(tx *gorm.DB) error) (err error) {
	return u.db.Model(&FsUser{}).WithContext(ctx).Transaction(fc)
}

// 继承guest_id的资源表
func InheritGuestIdResource(tx *gorm.DB, userId, guestId int64, afterDo func(txResouce *gorm.DB, txUserMaterial *gorm.DB, txUserInfo *gorm.DB) error) error {
	var err error
	txRes := tx.Model(&FsResource{})
	txUserMaterial := tx.Model(&FsUserMaterial{})
	txUserInfo := tx.Model(&FsUserInfo{})
	if guestId != 0 {
		// 继承guest_id的资源表
		err = txRes.
			Where("guest_id = ?", guestId).
			UpdateColumn("user_id", userId).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			return err
		}

		err = txUserMaterial.
			Where("guest_id = ?", guestId).
			UpdateColumn("user_id", userId).Error

		if err != nil && err != gorm.ErrRecordNotFound {
			return err
		}

		err = txUserInfo.
			Where("guest_id = ?", guestId).
			UpdateColumn("user_id", userId).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			return err
		}
	}

	if afterDo != nil {
		if txRes.Error != nil {
			txRes = tx.Model(&FsResource{})
		}
		if txUserMaterial.Error != nil {
			txUserMaterial = tx.Model(&FsUserMaterial{})
		}
		if txUserInfo.Error != nil {
			txUserInfo = tx.Model(&FsUserInfo{})
		}
		return afterDo(txRes, txUserMaterial, txUserInfo)
	}
	return fmt.Errorf("guest_id must not be 0")
}

// 谷歌平台的注册流程
func (u *FsUserModel) RegisterByGoogleOAuth(ctx context.Context, token *auth.RegisterToken) (*FsUser, error) {
	user := &FsUser{}

	err := u.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		googleId := token.Extend["google_id"].(int64)

		err := tx.Model(&FsUser{}).Where("email = ?", token.Email).Take(user).Error
		if err != nil {
			// 没有找到在数据库就创建注册
			if err == gorm.ErrRecordNotFound {
				createAt := time.Now().UTC().Unix()
				user.Email = &token.Email
				user.CreatedAt = &createAt
				user.GoogleId = &googleId
				user.PasswordHash = &token.Password
				err = tx.Model(&FsUser{}).Create(user).Error
				if err != nil {
					return err
				}
				// 继承guest_id的资源表
				return InheritGuestIdResource(tx, user.Id, token.GuestId, nil)
			}

			return err
		}

		// 如果已经存在,把谷歌id 加入到用户信息里
		user.GoogleId = &googleId
		return tx.Model(&FsUser{}).Update("google_id", user).Error
	})

	if err != nil {
		return nil, err
	}

	return user, nil
}

type UserProfile struct {
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
	Resetaurant string `json:"resetaurant"`
}

// 自平台的注册流程
func (u *FsUserModel) RegisterByFusen(ctx context.Context, token *auth.RegisterToken) (user *FsUser, err error) {

	err = u.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {

		user = &FsUser{}
		var err error

		err = tx.Model(&FsUser{}).Where("email = ?", token.Email).Take(user).Error
		if err == gorm.ErrRecordNotFound {

			FirstName := token.Extend["first_name"].(string)
			LastName := token.Extend["last_name"].(string)
			Resetaurant := token.Extend["resetaurant"].(string)

			createAt := time.Now().UTC().Unix()

			user.Email = &token.Email
			user.CreatedAt = &createAt
			user.PasswordHash = &token.Password
			user.FirstName = &FirstName
			user.LastName = &LastName

			err = tx.Model(&FsUser{}).Create(user).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				logx.Error(err)
				return err
			}

			// 继承guest_id的资源表
			err = InheritGuestIdResource(tx, user.Id, token.GuestId, func(txResouce, txUserMaterial, txUserInfo *gorm.DB) error {
				userProfile := &UserProfile{
					FirstName:   FirstName,
					LastName:    LastName,
					Resetaurant: Resetaurant,
				}
				metadata, err := json.Marshal(userProfile)
				if err != nil {
					return err
				}
				now := time.Now()
				uinfo := &FsUserInfo{
					Module:   FsString("profile"),
					UserId:   &user.Id,
					GuestId:  &token.GuestId,
					Metadata: &metadata,
					Ctime:    &now,
					Utime:    &now,
				}

				err = txUserInfo.Create(uinfo).Error
				if err == gorm.ErrRecordNotFound {
					return nil
				}
				return err
			})

			if err == gorm.ErrRecordNotFound {
				return nil
			}
			return err
		}

		return fmt.Errorf("the email had registered")
	})

	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return
}

func (u *FsUserModel) UpdateUserBasicInfoById(ctx context.Context, Id int64, user *UserBasicInfoForSave) (err error) {

	err = u.db.WithContext(ctx).Model(&FsUser{}).
		Where("`id` = ? and is_del = ? and status = ?", Id, 0, 1).
		Updates(map[string]interface{}{
			"first_name":             user.FirstName,
			"last_name":              user.LastName,
			"mobile":                 user.Mobile,
			"company":                user.Company,
			"is_order_status_email":  user.IsOrderStatusEmail,
			"is_email_advertisement": user.IsEmailAdvertisement,
			"is_order_status_phone":  user.IsOrderStatusPhone,
			"is_phone_advertisement": user.IsPhoneAdvertisement,
			"type":                   user.Type,
			"is_open_render":         user.IsOpenRender,
			"is_low_rendering":       user.IsLowRendering,
			"is_remove_bg":           user.IsRemoveBg,
		}).Error
	return err
}

func (u *FsUserModel) DebugAuthDelete(ctx context.Context, email string) (err error) {

	err = u.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		user := &FsUser{}

		txUser := tx.Model(&FsUser{})
		err = txUser.Where("email = ?", email).Take(user).Error
		if err == nil {
			err = txUser.Where("email = ?", email).Delete(user).Error
			if err != nil {
				return err
			}
			txRes := tx.Model(&FsResource{})
			txUserMaterial := tx.Model(&FsUserMaterial{})
			txUserInfo := tx.Model(&FsUserInfo{})

			// 继承guest_id的资源表
			err = txRes.
				Where("user_id = ?", user.Id).Delete(&FsResource{}).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}

			err = txUserMaterial.
				Where("user_id = ?", user.Id).
				Delete(&FsUserMaterial{}).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}

			err = txUserInfo.
				Where("user_id = ?", user.Id).
				Delete(&FsResource{}).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}
		}

		return err
	})

	return err
}