// Package shop 提供店铺创建与业务员归属的简单写事务脚本。
package shop

import (
	"context"
	"strings"

	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"

	"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"
)

// CreateService 收口平台与代理创建店铺的完整事务。
type CreateService struct {
	db *gorm.DB
}

// NewCreateService 创建店铺创建事务脚本。
func NewCreateService(db *gorm.DB) *CreateService {
	return &CreateService{db: db}
}

// Create 按操作者类型执行平台显式归属或代理安全继承。
func (s *CreateService) Create(ctx context.Context, request *dto.CreateShopRequest) (*dto.ShopResponse, error) {
	userType := middleware.GetUserTypeFromContext(ctx)
	operatorID := middleware.GetUserIDFromContext(ctx)
	if operatorID == 0 {
		return nil, errors.New(errors.CodeUnauthorized)
	}
	resolver := resolvePlatformBusinessOwner
	switch userType {
	case constants.UserTypeSuperAdmin, constants.UserTypePlatform:
	case constants.UserTypeAgent:
		if request.BusinessOwnerAccountIDSet {
			return nil, errors.New(errors.CodeForbidden, "无权限设置店铺业务员")
		}
		if request.ParentID == nil {
			return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
		}
		if err := middleware.CanManageShop(ctx, *request.ParentID); err != nil {
			return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
		}
		resolver = resolveInheritedBusinessOwner
	default:
		return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
	}
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(request.InitPassword), bcrypt.DefaultCost)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "密码哈希失败")
	}

	var response *dto.ShopResponse
	err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		created, createErr := createShop(tx, request, operatorID, string(hashedPassword), resolver)
		if createErr != nil {
			return createErr
		}
		response = created
		return nil
	})
	if err != nil {
		return nil, err
	}
	return response, nil
}

type businessOwnerResolver func(*gorm.DB, *dto.CreateShopRequest, *model.Shop) (*uint, error)

func createShop(tx *gorm.DB, request *dto.CreateShopRequest, operatorID uint, hashedPassword string, resolveOwner businessOwnerResolver) (*dto.ShopResponse, error) {
	if exists, err := recordExists(tx, &model.Shop{}, "shop_code = ?", request.ShopCode); err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "校验店铺编号失败")
	} else if exists {
		return nil, errors.New(errors.CodeShopCodeExists, "店铺编号已存在")
	}
	if exists, err := recordExists(tx, &model.Account{}, "username = ?", request.InitUsername); err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "校验初始账号用户名失败")
	} else if exists {
		return nil, errors.New(errors.CodeUsernameExists, "初始账号用户名已存在")
	}
	if exists, err := recordExists(tx, &model.Account{}, "phone = ?", request.InitPhone); err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "校验初始账号手机号失败")
	} else if exists {
		return nil, errors.New(errors.CodePhoneExists, "初始账号手机号已存在")
	}

	parent, level, err := resolveParent(tx, request.ParentID)
	if err != nil {
		return nil, err
	}
	ownerID, err := resolveOwner(tx, request, parent)
	if err != nil {
		return nil, err
	}
	var role model.Role
	if err := tx.Where("id = ? AND role_type = ? AND status = ?", request.DefaultRoleID, constants.RoleTypeCustomer, constants.StatusEnabled).First(&role).Error; err != nil {
		return nil, errors.New(errors.CodeInvalidParam, "请选择启用的客户角色")
	}

	shop := &model.Shop{
		ShopName: request.ShopName, ShopCode: request.ShopCode, ParentID: request.ParentID,
		BusinessOwnerAccountID: ownerID, Level: level, ContactName: request.ContactName,
		ContactPhone: request.ContactPhone, Province: request.Province, City: request.City,
		District: request.District, Address: request.Address, Status: constants.ShopStatusEnabled,
	}
	shop.Creator = operatorID
	shop.Updater = operatorID
	if err := tx.Create(shop).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "创建店铺失败")
	}

	account := &model.Account{
		Username: request.InitUsername, Phone: request.InitPhone, Password: hashedPassword,
		UserType: constants.UserTypeAgent, ShopID: &shop.ID, Status: constants.StatusEnabled, IsPrimary: true,
	}
	account.Creator = operatorID
	account.Updater = operatorID
	if err := tx.Create(account).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "创建初始账号失败")
	}
	if err := tx.Create(&model.AccountRole{
		AccountID: account.ID, RoleID: request.DefaultRoleID, Status: constants.StatusEnabled,
		Creator: operatorID, Updater: operatorID,
	}).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "为初始账号分配角色失败")
	}
	if err := tx.Create(&model.ShopRole{
		ShopID: shop.ID, RoleID: request.DefaultRoleID, Status: constants.StatusEnabled,
		Creator: operatorID, Updater: operatorID,
	}).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "设置店铺默认角色失败")
	}
	if err := tx.Create([]*model.AgentWallet{
		{
			ShopID: shop.ID, WalletType: constants.AgentWalletTypeMain,
			CreditEnabled: role.DefaultCreditEnabled, CreditLimit: role.DefaultCreditLimit,
			Currency: "CNY", Status: constants.AgentWalletStatusNormal, ShopIDTag: shop.ID,
		},
		{
			ShopID: shop.ID, WalletType: constants.AgentWalletTypeCommission,
			CreditEnabled: false, CreditLimit: 0,
			Currency: "CNY", Status: constants.AgentWalletStatusNormal, ShopIDTag: shop.ID,
		},
	}).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "初始化店铺钱包失败")
	}

	parentName := ""
	if parent != nil {
		parentName = parent.ShopName
	}
	response := newShopResponse(shop, parentName)
	if err := fillBusinessOwnerResponse(tx, shop, response); err != nil {
		return nil, err
	}
	return response, nil
}

func resolveParent(tx *gorm.DB, parentID *uint) (*model.Shop, int, error) {
	if parentID == nil {
		return nil, 1, nil
	}
	var parent model.Shop
	if err := tx.First(&parent, *parentID).Error; err != nil {
		return nil, 0, errors.New(errors.CodeInvalidParentID, "上级店铺不存在或无效")
	}
	level := parent.Level + 1
	if level > constants.ShopMaxLevel {
		return nil, 0, errors.New(errors.CodeShopLevelExceeded, "店铺层级不能超过 7 级")
	}
	return &parent, level, nil
}

func resolvePlatformBusinessOwner(tx *gorm.DB, request *dto.CreateShopRequest, parent *model.Shop) (*uint, error) {
	if !request.BusinessOwnerAccountIDSet {
		if parent == nil || parent.BusinessOwnerAccountID == nil {
			return nil, nil
		}
		ownerID := *parent.BusinessOwnerAccountID
		return &ownerID, nil
	}
	if request.BusinessOwnerAccountID == nil {
		return nil, nil
	}
	if *request.BusinessOwnerAccountID == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "业务员账号无效")
	}
	var account model.Account
	if err := tx.Where("id = ? AND user_type = ? AND status = ?", *request.BusinessOwnerAccountID, constants.UserTypePlatform, constants.StatusEnabled).
		First(&account).Error; err != nil {
		return nil, errors.New(errors.CodeInvalidParam, "业务员账号无效或不可用")
	}
	ownerID := account.ID
	return &ownerID, nil
}

func resolveInheritedBusinessOwner(_ *gorm.DB, _ *dto.CreateShopRequest, parent *model.Shop) (*uint, error) {
	if parent == nil || parent.BusinessOwnerAccountID == nil {
		return nil, nil
	}
	ownerID := *parent.BusinessOwnerAccountID
	return &ownerID, nil
}

func recordExists(tx *gorm.DB, target any, query string, value any) (bool, error) {
	var count int64
	err := tx.Model(target).Where(query, value).Count(&count).Error
	return count > 0, err
}

func newShopResponse(shop *model.Shop, parentName string) *dto.ShopResponse {
	return &dto.ShopResponse{
		ID: shop.ID, ShopName: shop.ShopName, ShopCode: shop.ShopCode, ParentID: shop.ParentID,
		BusinessOwnerAccountID: shop.BusinessOwnerAccountID,
		ParentShopName:         parentName, Level: shop.Level, ContactName: shop.ContactName,
		ContactPhone: shop.ContactPhone, Province: shop.Province, City: shop.City,
		District: shop.District, Address: shop.Address, Status: shop.Status,
		ClientLoginDisabled: shop.ClientLoginDisabled,
		StatusName:          constants.GetStatusName(shop.Status), CreatedAt: shop.CreatedAt.Format("2006-01-02 15:04:05"),
		UpdatedAt: shop.UpdatedAt.Format("2006-01-02 15:04:05"),
	}
}

func fillBusinessOwnerResponse(tx *gorm.DB, shop *model.Shop, response *dto.ShopResponse) error {
	if shop.BusinessOwnerAccountID == nil {
		return nil
	}
	var account model.Account
	err := tx.Unscoped().Where("id = ?", *shop.BusinessOwnerAccountID).First(&account).Error
	if err == gorm.ErrRecordNotFound {
		return nil
	}
	if err != nil {
		return errors.Wrap(errors.CodeDatabaseError, err, "查询业务员摘要失败")
	}
	response.BusinessOwnerUsername = account.Username
	response.BusinessOwnerPhoneSummary = maskBusinessOwnerPhone(account.Phone)
	response.BusinessOwnerAvailable = account.UserType == constants.UserTypePlatform && account.Status == constants.StatusEnabled && !account.DeletedAt.Valid
	return nil
}

func maskBusinessOwnerPhone(phone string) string {
	phone = strings.TrimSpace(phone)
	if len(phone) < 7 {
		return ""
	}
	return phone[:3] + "****" + phone[len(phone)-4:]
}
