package postgres

import (
	"context"
	"maps"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"gorm.io/gorm"
)

type ExchangeOrderStore struct {
	db *gorm.DB
}

func NewExchangeOrderStore(db *gorm.DB) *ExchangeOrderStore {
	return &ExchangeOrderStore{db: db}
}

func (s *ExchangeOrderStore) Create(ctx context.Context, order *model.ExchangeOrder) error {
	return s.db.WithContext(ctx).Create(order).Error
}

func (s *ExchangeOrderStore) GetByID(ctx context.Context, id uint) (*model.ExchangeOrder, error) {
	var order model.ExchangeOrder
	query := s.db.WithContext(ctx).Where("id = ?", id)
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.First(&order).Error; err != nil {
		return nil, err
	}
	return &order, nil
}

func (s *ExchangeOrderStore) UpdateStatus(ctx context.Context, id uint, fromStatus, toStatus int, updates map[string]any) error {
	values := make(map[string]any, len(updates)+1)
	maps.Copy(values, updates)
	values["status"] = toStatus

	result := s.db.WithContext(ctx).Model(&model.ExchangeOrder{}).
		Where("id = ? AND status = ?", id, fromStatus).
		Updates(values)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}

// FindByNewAssetID 通过新资产类型和ID查询已完成换货来源记录
// 用于换货链追溯：找到将当前资产作为换货结果的已完成换货单，从而得到前代资产信息
// 若未找到则返回 nil, nil 表示该资产无前代
func (s *ExchangeOrderStore) FindByNewAssetID(ctx context.Context, assetType string, assetID uint) (*model.ExchangeOrder, error) {
	var order model.ExchangeOrder
	err := s.db.WithContext(ctx).
		Where("new_asset_id = ? AND new_asset_type = ?", assetID, assetType).
		Where("status = ?", constants.ExchangeStatusCompleted).
		Order("id DESC").
		First(&order).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}
	return &order, nil
}

// FindShippingPendingByOldAsset 查询客户端可见的物流换货待处理单
// 历史 flow_type 为空时按 shipping 兼容处理。
func (s *ExchangeOrderStore) FindShippingPendingByOldAsset(ctx context.Context, assetType string, assetID uint) (*model.ExchangeOrder, error) {
	var order model.ExchangeOrder
	query := s.db.WithContext(ctx).
		Where("old_asset_type = ? AND old_asset_id = ?", assetType, assetID).
		Where("status IN ?", []int{constants.ExchangeStatusPendingInfo, constants.ExchangeStatusPendingShip, constants.ExchangeStatusShipped}).
		Where("COALESCE(NULLIF(flow_type, ''), ?) = ?", constants.ExchangeFlowTypeShipping, constants.ExchangeFlowTypeShipping)
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.Order("id DESC").First(&order).Error; err != nil {
		return nil, err
	}
	return &order, nil
}

func (s *ExchangeOrderStore) FindActiveByOldAsset(ctx context.Context, assetType string, assetID uint) (*model.ExchangeOrder, error) {
	var order model.ExchangeOrder
	query := s.db.WithContext(ctx).
		Where("old_asset_type = ? AND old_asset_id = ?", assetType, assetID).
		Where("status IN ?", []int{constants.ExchangeStatusPendingInfo, constants.ExchangeStatusPendingShip, constants.ExchangeStatusShipped})
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.Order("id DESC").First(&order).Error; err != nil {
		return nil, err
	}
	return &order, nil
}
