package shop

import (
	"context"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
)

// UpdateService 收口店铺资料与业务员归属的简单写事务脚本。
type UpdateService struct {
	db *gorm.DB
}

// NewUpdateService 创建店铺更新事务脚本。
func NewUpdateService(db *gorm.DB) *UpdateService {
	return &UpdateService{db: db}
}

// Update 更新单个店铺；业务员归属变化不会传播到其他店铺。
func (s *UpdateService) Update(ctx context.Context, shopID uint, request *dto.UpdateShopRequest) (*dto.ShopResponse, error) {
	if shopID == 0 {
		return nil, errors.New(errors.CodeInvalidParam)
	}
	userType := middleware.GetUserTypeFromContext(ctx)
	if userType == constants.UserTypeEnterprise {
		return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
	}
	if err := middleware.CanManageShop(ctx, shopID); err != nil {
		return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
	}
	if userType == constants.UserTypeAgent && request.BusinessOwnerAccountIDSet {
		return nil, errors.New(errors.CodeForbidden, "无权限设置店铺业务员")
	}
	if userType == constants.UserTypeAgent && request.ClientLoginDisabled != nil && middleware.GetShopIDFromContext(ctx) != shopID {
		return nil, errors.New(errors.CodeForbidden, "无权限修改其他店铺的C端登录限制")
	}
	if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform && userType != constants.UserTypeAgent {
		return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
	}

	operatorID := middleware.GetUserIDFromContext(ctx)
	if operatorID == 0 {
		return nil, errors.New(errors.CodeUnauthorized)
	}
	var response *dto.ShopResponse
	err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var shop model.Shop
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&shop, shopID).Error; err != nil {
			return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
		}
		if request.BusinessOwnerAccountIDSet {
			ownerID, err := validateUpdatedBusinessOwner(tx, request.BusinessOwnerAccountID)
			if err != nil {
				return err
			}
			shop.BusinessOwnerAccountID = ownerID
		}
		if request.ClientLoginDisabled != nil {
			shop.ClientLoginDisabled = *request.ClientLoginDisabled
		}
		shop.ShopName = request.ShopName
		shop.ContactName = request.ContactName
		shop.ContactPhone = request.ContactPhone
		shop.Province = request.Province
		shop.City = request.City
		shop.District = request.District
		shop.Address = request.Address
		shop.Status = request.Status
		shop.Updater = operatorID
		if err := tx.Save(&shop).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "更新店铺失败")
		}
		parentName := ""
		if shop.ParentID != nil {
			var parent model.Shop
			if err := tx.Select("shop_name").First(&parent, *shop.ParentID).Error; err == nil {
				parentName = parent.ShopName
			}
		}
		response = newShopResponse(&shop, parentName)
		if err := fillBusinessOwnerResponse(tx, &shop, response); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return response, nil
}

func validateUpdatedBusinessOwner(tx *gorm.DB, requestedID *uint) (*uint, error) {
	if requestedID == nil {
		return nil, nil
	}
	if *requestedID == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "业务员账号无效")
	}
	var account model.Account
	if err := tx.Clauses(clause.Locking{Strength: "SHARE"}).
		Where("id = ? AND user_type = ? AND status = ?", *requestedID, constants.UserTypePlatform, constants.StatusEnabled).
		First(&account).Error; err != nil {
		return nil, errors.New(errors.CodeInvalidParam, "业务员账号无效或不可用")
	}
	ownerID := account.ID
	return &ownerID, nil
}
