package purchase_validation

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"gorm.io/gorm"
)

type Service struct {
	db                     *gorm.DB
	iotCardStore           *postgres.IotCardStore
	deviceStore            *postgres.DeviceStore
	packageStore           *postgres.PackageStore
	packageAllocationStore *postgres.ShopPackageAllocationStore
}

func New(
	db *gorm.DB,
	iotCardStore *postgres.IotCardStore,
	deviceStore *postgres.DeviceStore,
	packageStore *postgres.PackageStore,
	packageAllocationStore *postgres.ShopPackageAllocationStore,
) *Service {
	return &Service{
		db:                     db,
		iotCardStore:           iotCardStore,
		deviceStore:            deviceStore,
		packageStore:           packageStore,
		packageAllocationStore: packageAllocationStore,
	}
}

type PurchaseValidationResult struct {
	Card       *model.IotCard
	Device     *model.Device
	Packages   []*model.Package
	TotalPrice int64
}

func (s *Service) ValidateCardPurchase(ctx context.Context, cardID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
	card, err := s.iotCardStore.GetByID(ctx, cardID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeIotCardNotFound, "IoT卡不存在")
		}
		return nil, err
	}

	if !card.IsStandalone {
		return nil, errors.New(errors.CodeInvalidParam, "该卡已绑定设备，请前往设备页面购买套餐")
	}

	if card.SeriesID == nil || *card.SeriesID == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "该卡未关联套餐系列，无法购买套餐")
	}

	// 确定卖家店铺ID：卡所属店铺即为卖家（代理渠道），平台自营时为0
	var sellerShopID uint
	if card.ShopID != nil {
		sellerShopID = *card.ShopID
	}

	packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID, sellerShopID)
	if err != nil {
		return nil, err
	}

	return &PurchaseValidationResult{
		Card:       card,
		Packages:   packages,
		TotalPrice: totalPrice,
	}, nil
}

func (s *Service) ValidateDevicePurchase(ctx context.Context, deviceID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
	device, err := s.deviceStore.GetByID(ctx, deviceID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "设备不存在")
		}
		return nil, err
	}

	if device.SeriesID == nil || *device.SeriesID == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "该设备未关联套餐系列，无法购买套餐")
	}

	// 确定卖家店铺ID：设备所属店铺即为卖家（代理渠道），平台自营时为0
	var sellerShopID uint
	if device.ShopID != nil {
		sellerShopID = *device.ShopID
	}

	packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *device.SeriesID, sellerShopID)
	if err != nil {
		return nil, err
	}

	return &PurchaseValidationResult{
		Device:     device,
		Packages:   packages,
		TotalPrice: totalPrice,
	}, nil
}

// validatePackages 验证套餐列表是否可购买
// sellerShopID > 0 表示代理渠道，校验该代理的 allocation.shelf_status；
// sellerShopID == 0 表示平台自营渠道，校验 package.shelf_status
func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, seriesID uint, sellerShopID uint) ([]*model.Package, int64, error) {
	if len(packageIDs) == 0 {
		return nil, 0, errors.New(errors.CodeInvalidParam, "请选择至少一个套餐")
	}

	var packages []*model.Package
	var totalPrice int64

	for _, pkgID := range packageIDs {
		pkg, err := s.packageStore.GetByID(ctx, pkgID)
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				return nil, 0, errors.New(errors.CodeInvalidParam, "套餐不存在")
			}
			return nil, 0, err
		}

		if pkg.SeriesID != seriesID {
			return nil, 0, errors.New(errors.CodeInvalidParam, "套餐不在可购买范围内")
		}

		// Package.status 为全局开关，任何渠道都必须检查
		if pkg.Status != constants.StatusEnabled {
			return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已禁用")
		}

		if sellerShopID > 0 {
			// 代理渠道：检查上架状态并获取分配记录，使用零售价
			allocation, allocErr := s.validateAgentAllocation(ctx, sellerShopID, pkgID)
			if allocErr != nil {
				return nil, 0, allocErr
			}
			// 零售价低于成本价时视为不可购买，防止亏损售卖
			if allocation.RetailPrice < allocation.CostPrice {
				return nil, 0, errors.New(errors.CodeInvalidParam, "套餐价格配置异常，暂不可购买")
			}
			totalPrice += allocation.RetailPrice
		} else {
			if pkg.ShelfStatus != constants.ShelfStatusOn {
				return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已下架")
			}
			totalPrice += pkg.SuggestedRetailPrice
		}

		packages = append(packages, pkg)
	}

	return packages, totalPrice, nil
}

// validateAgentAllocation 校验卖家代理的分配记录上架状态，并返回分配记录
func (s *Service) validateAgentAllocation(ctx context.Context, sellerShopID, packageID uint) (*model.ShopPackageAllocation, error) {
	allocation, err := s.packageAllocationStore.GetByShopAndPackageForSystem(ctx, sellerShopID, packageID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeInvalidParam, "套餐已下架")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询套餐分配记录失败")
	}

	if allocation.ShelfStatus != constants.ShelfStatusOn {
		return nil, errors.New(errors.CodeInvalidParam, "套餐已下架")
	}

	return allocation, nil
}

// GetPurchasePrice 获取购买价格
// 代理渠道（sellerShopID > 0）返回 allocation.RetailPrice，平台渠道返回 Package.SuggestedRetailPrice
func (s *Service) GetPurchasePrice(ctx context.Context, pkg *model.Package, sellerShopID uint) (int64, error) {
	if sellerShopID > 0 {
		allocation, err := s.packageAllocationStore.GetByShopAndPackageForSystem(ctx, sellerShopID, pkg.ID)
		if err != nil {
			return 0, errors.Wrap(errors.CodeInternalError, err, "查询套餐分配记录失败")
		}
		return allocation.RetailPrice, nil
	}
	return pkg.SuggestedRetailPrice, nil
}

// GetCostPrice 获取代理渠道的套餐成本价
// sellerShopID == 0 表示平台自营，返回 0（平台直销无成本价概念）
func (s *Service) GetCostPrice(ctx context.Context, pkg *model.Package, sellerShopID uint) (int64, error) {
	if sellerShopID == 0 {
		return 0, nil
	}
	allocation, err := s.packageAllocationStore.GetByShopAndPackageForSystem(ctx, sellerShopID, pkg.ID)
	if err != nil {
		return 0, errors.Wrap(errors.CodeInternalError, err, "查询套餐分配记录失败")
	}
	return allocation.CostPrice, nil
}

// ValidateAdminOfflineCardPurchase 后台 offline 订单专用卡验证
// 绕过代理 Allocation 上架检查，仅验证套餐全局状态
func (s *Service) ValidateAdminOfflineCardPurchase(ctx context.Context, cardID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
	card, err := s.iotCardStore.GetByID(ctx, cardID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeIotCardNotFound, "IoT卡不存在")
		}
		return nil, err
	}

	if !card.IsStandalone {
		return nil, errors.New(errors.CodeInvalidParam, "该卡已绑定设备，请前往设备页面购买套餐")
	}

	if card.SeriesID == nil || *card.SeriesID == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "该卡未关联套餐系列，无法购买套餐")
	}

	packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID, 0)
	if err != nil {
		return nil, err
	}

	return &PurchaseValidationResult{
		Card:       card,
		Packages:   packages,
		TotalPrice: totalPrice,
	}, nil
}

// ValidateAdminOfflineDevicePurchase 后台 offline 订单专用设备验证
// 绕过代理 Allocation 上架检查，仅验证套餐全局状态
func (s *Service) ValidateAdminOfflineDevicePurchase(ctx context.Context, deviceID uint, packageIDs []uint) (*PurchaseValidationResult, error) {
	device, err := s.deviceStore.GetByID(ctx, deviceID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "设备不存在")
		}
		return nil, err
	}

	if device.SeriesID == nil || *device.SeriesID == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "该设备未关联套餐系列，无法购买套餐")
	}

	packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *device.SeriesID, 0)
	if err != nil {
		return nil, err
	}

	return &PurchaseValidationResult{
		Device:     device,
		Packages:   packages,
		TotalPrice: totalPrice,
	}, nil
}
