package asset

import (
	"context"
	stderrors "errors"

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

var deactivatableAssetStatuses = []int{constants.AssetStatusInStock, constants.AssetStatusSold}

// LifecycleService 资产生命周期服务
type LifecycleService struct {
	db           *gorm.DB
	iotCardStore *postgres.IotCardStore
	deviceStore  *postgres.DeviceStore
}

// NewLifecycleService 创建资产生命周期服务
func NewLifecycleService(db *gorm.DB, iotCardStore *postgres.IotCardStore, deviceStore *postgres.DeviceStore) *LifecycleService {
	return &LifecycleService{
		db:           db,
		iotCardStore: iotCardStore,
		deviceStore:  deviceStore,
	}
}

// DeactivateIotCard 手动停用 IoT 卡
func (s *LifecycleService) DeactivateIotCard(ctx context.Context, id uint) error {
	card, err := s.iotCardStore.GetByID(ctx, id)
	if err != nil {
		if stderrors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New(errors.CodeIotCardNotFound)
		}
		return errors.Wrap(errors.CodeDatabaseError, err, "查询IoT卡失败")
	}

	if !canDeactivateAsset(card.AssetStatus) {
		return errors.New(errors.CodeForbidden, "当前状态不允许停用")
	}

	result := s.db.WithContext(ctx).Model(&model.IotCard{}).
		Where("id = ? AND asset_status IN ?", id, deactivatableAssetStatuses).
		Update("asset_status", constants.AssetStatusDeactivated)
	if result.Error != nil {
		return errors.Wrap(errors.CodeDatabaseError, result.Error, "停用IoT卡失败")
	}
	if result.RowsAffected == 0 {
		return errors.New(errors.CodeConflict, "状态已变更，请刷新后重试")
	}

	return nil
}

// DeactivateDevice 手动停用设备
func (s *LifecycleService) DeactivateDevice(ctx context.Context, id uint) error {
	device, err := s.deviceStore.GetByID(ctx, id)
	if err != nil {
		if stderrors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New(errors.CodeNotFound, "设备不存在")
		}
		return errors.Wrap(errors.CodeDatabaseError, err, "查询设备失败")
	}

	if !canDeactivateAsset(device.AssetStatus) {
		return errors.New(errors.CodeForbidden, "当前状态不允许停用")
	}

	result := s.db.WithContext(ctx).Model(&model.Device{}).
		Where("id = ? AND asset_status IN ?", id, deactivatableAssetStatuses).
		Update("asset_status", constants.AssetStatusDeactivated)
	if result.Error != nil {
		return errors.Wrap(errors.CodeDatabaseError, result.Error, "停用设备失败")
	}
	if result.RowsAffected == 0 {
		return errors.New(errors.CodeConflict, "状态已变更，请刷新后重试")
	}

	return nil
}

func canDeactivateAsset(assetStatus int) bool {
	return assetStatus == constants.AssetStatusInStock || assetStatus == constants.AssetStatusSold
}
