package postgres

import (
	"context"

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

// RefundListFilters 退款列表筛选条件
type RefundListFilters struct {
	Status          *int   `json:"status"`
	OrderID         *uint  `json:"order_id"`
	ShopID          *uint  `json:"shop_id"`
	AssetIdentifier string `json:"asset_identifier"`
}

// RefundStore 退款申请数据访问层
type RefundStore struct {
	db *gorm.DB
}

// NewRefundStore 创建退款申请 Store 实例
func NewRefundStore(db *gorm.DB) *RefundStore {
	return &RefundStore{db: db}
}

// Create 创建退款申请记录
func (s *RefundStore) Create(ctx context.Context, req *model.RefundRequest) error {
	return s.db.WithContext(ctx).Create(req).Error
}

// GetByID 根据 ID 查询退款申请（含数据权限过滤）
func (s *RefundStore) GetByID(ctx context.Context, id uint) (*model.RefundRequest, error) {
	var req model.RefundRequest
	query := s.db.WithContext(ctx).
		Model(&model.RefundRequest{}).
		Select("tb_refund_request.*, tb_shop.shop_name AS shop_name").
		Joins("LEFT JOIN tb_shop ON tb_shop.id = tb_refund_request.shop_id AND tb_shop.deleted_at IS NULL").
		Where("tb_refund_request.id = ?", id)
	query = applyRefundScope(ctx, query)
	if err := query.First(&req).Error; err != nil {
		return nil, err
	}
	return &req, nil
}

// Update 更新退款申请记录（全字段保存）
func (s *RefundStore) Update(ctx context.Context, req *model.RefundRequest) error {
	return s.db.WithContext(ctx).Save(req).Error
}

// UpdateFields 按字段更新退款申请（用于条件更新场景）
func (s *RefundStore) UpdateFields(ctx context.Context, id uint, updates map[string]any) error {
	return s.db.WithContext(ctx).
		Model(&model.RefundRequest{}).
		Where("id = ?", id).
		Updates(updates).Error
}

// List 分页查询退款申请列表（含数据权限过滤和筛选条件）
func (s *RefundStore) List(ctx context.Context, opts *store.QueryOptions, filters *RefundListFilters) ([]*model.RefundRequest, int64, error) {
	var requests []*model.RefundRequest
	var total int64

	query := s.db.WithContext(ctx).
		Model(&model.RefundRequest{}).
		Select("tb_refund_request.*, tb_shop.shop_name AS shop_name").
		Joins("LEFT JOIN tb_shop ON tb_shop.id = tb_refund_request.shop_id AND tb_shop.deleted_at IS NULL")
	query = applyRefundScope(ctx, query)

	if filters != nil {
		if filters.Status != nil {
			query = query.Where("tb_refund_request.status = ?", *filters.Status)
		}
		if filters.OrderID != nil {
			query = query.Where("tb_refund_request.order_id = ?", *filters.OrderID)
		}
		if filters.ShopID != nil {
			query = query.Where("tb_refund_request.shop_id = ?", *filters.ShopID)
		}
		if filters.AssetIdentifier != "" {
			query = query.Where("tb_refund_request.asset_identifier = ?", filters.AssetIdentifier)
		}
	}

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	if opts == nil {
		opts = &store.QueryOptions{
			Page:     1,
			PageSize: constants.DefaultPageSize,
		}
	}
	offset := (opts.Page - 1) * opts.PageSize
	query = query.Offset(offset).Limit(opts.PageSize)

	if opts.OrderBy != "" {
		query = query.Order(opts.OrderBy)
	} else {
		query = query.Order("tb_refund_request.created_at DESC")
	}

	if err := query.Find(&requests).Error; err != nil {
		return nil, 0, err
	}

	return requests, total, nil
}

// applyRefundScope 应用退款单专属数据权限。
// 退款申请对代理按创建人隔离，避免上级代理通过店铺层级看到下级申请。
func applyRefundScope(ctx context.Context, query *gorm.DB) *gorm.DB {
	switch middleware.GetUserTypeFromContext(ctx) {
	case constants.UserTypeSuperAdmin, constants.UserTypePlatform:
		return query
	case constants.UserTypeAgent:
		userID := middleware.GetUserIDFromContext(ctx)
		if userID == 0 {
			return query.Where("1 = 0")
		}
		return query.Where("tb_refund_request.creator = ?", userID)
	default:
		return query.Where("1 = 0")
	}
}

// FindActiveByOrderID 查找订单关联的活跃退款申请（状态为待审批、已通过）
func (s *RefundStore) FindActiveByOrderID(ctx context.Context, orderID uint) (*model.RefundRequest, error) {
	var req model.RefundRequest
	err := s.db.WithContext(ctx).
		Where("order_id = ? AND status IN ?", orderID, []int{
			model.RefundStatusPending,
			model.RefundStatusApproved,
		}).
		First(&req).Error
	if err != nil {
		return nil, err
	}
	return &req, nil
}

// HasUnfinishedByAsset 检查资产是否存在仍会影响资产状态的退款申请。
// 待审批、已退回，以及已通过但退款后资产处理尚未完成的申请均视为未终结。
func (s *RefundStore) HasUnfinishedByAsset(ctx context.Context, assetType string, assetID uint) (bool, error) {
	var assetColumn string
	switch assetType {
	case constants.ExchangeAssetTypeIotCard:
		assetColumn = "iot_card_id"
	case constants.ExchangeAssetTypeDevice:
		assetColumn = "device_id"
	default:
		return false, gorm.ErrInvalidData
	}

	var count int64
	err := s.db.WithContext(ctx).
		Model(&model.RefundRequest{}).
		Where(assetColumn+" = ?", assetID).
		Where("status IN ? OR (status = ? AND asset_reset = ?)",
			[]int{model.RefundStatusPending, model.RefundStatusReturned},
			model.RefundStatusApproved,
			false,
		).
		Count(&count).Error
	return count > 0, err
}
