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
	seriesAllocationStore *postgres.ShopSeriesAllocationStore
}

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

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

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

	packages, totalPrice, err := s.validatePackages(ctx, packageIDs, *card.SeriesID)
	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, "该设备未关联套餐系列，无法购买套餐")
	}

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

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

func (s *Service) validatePackages(ctx context.Context, packageIDs []uint, seriesID 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, "套餐不在可购买范围内")
		}

		if pkg.Status != constants.StatusEnabled {
			return nil, 0, errors.New(errors.CodeInvalidParam, "套餐已禁用")
		}

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

		packages = append(packages, pkg)
		totalPrice += pkg.SuggestedRetailPrice
	}

	return packages, totalPrice, nil
}

func (s *Service) GetPurchasePrice(ctx context.Context, pkg *model.Package, buyerType string) int64 {
	return pkg.SuggestedRetailPrice
}
