package postgres

import (
	"context"
	"fmt"
	"time"

	"gorm.io/gorm"

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

// AssetPackageBatchOrderTaskStore 批量订购任务数据访问层。
type AssetPackageBatchOrderTaskStore struct {
	db *gorm.DB
}

// NewAssetPackageBatchOrderTaskStore 创建批量订购任务 Store。
func NewAssetPackageBatchOrderTaskStore(db *gorm.DB) *AssetPackageBatchOrderTaskStore {
	return &AssetPackageBatchOrderTaskStore{db: db}
}

// Create 创建批量订购任务。
func (s *AssetPackageBatchOrderTaskStore) Create(ctx context.Context, task *model.AssetPackageBatchOrderTask) error {
	return s.db.WithContext(ctx).Create(task).Error
}

// GetByID 按 ID 查询批量订购任务。
func (s *AssetPackageBatchOrderTaskStore) GetByID(ctx context.Context, id uint) (*model.AssetPackageBatchOrderTask, error) {
	var task model.AssetPackageBatchOrderTask
	query := s.applyVisibleScope(ctx, s.db.WithContext(ctx).Where("id = ?", id))
	if err := query.First(&task).Error; err != nil {
		return nil, err
	}
	return &task, nil
}

// List 分页查询批量订购任务。
func (s *AssetPackageBatchOrderTaskStore) List(ctx context.Context, opts *store.QueryOptions, status *int) ([]*model.AssetPackageBatchOrderTask, int64, error) {
	query := s.applyVisibleScope(ctx, s.db.WithContext(ctx).Model(&model.AssetPackageBatchOrderTask{}))
	if status != nil {
		query = query.Where("status = ?", *status)
	}
	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if opts == nil {
		opts = &store.QueryOptions{Page: 1, PageSize: constants.DefaultPageSize}
	}
	var tasks []*model.AssetPackageBatchOrderTask
	if err := query.Order("created_at DESC").Offset((opts.Page - 1) * opts.PageSize).Limit(opts.PageSize).Find(&tasks).Error; err != nil {
		return nil, 0, err
	}
	return tasks, total, nil
}

// Claim 领取待处理或已超时的处理中任务，避免正常执行期间被重复消费。
func (s *AssetPackageBatchOrderTaskStore) Claim(ctx context.Context, id uint) (bool, error) {
	now := time.Now()
	staleBefore := now.Add(-constants.AssetPackageBatchOrderTaskTimeout)
	result := s.db.WithContext(ctx).Model(&model.AssetPackageBatchOrderTask{}).
		Where("id = ? AND (status = ? OR (status = ? AND started_at < ?))", id, asynctask.StatusPending, asynctask.StatusProcessing, staleBefore).
		Updates(map[string]any{"status": asynctask.StatusProcessing, "started_at": now, "updated_at": now})
	return result.RowsAffected == 1, result.Error
}

func (s *AssetPackageBatchOrderTaskStore) applyVisibleScope(ctx context.Context, query *gorm.DB) *gorm.DB {
	if middleware.GetUserTypeFromContext(ctx) != constants.UserTypeAgent {
		return query
	}
	shopIDs := middleware.GetSubordinateShopIDs(ctx)
	if len(shopIDs) == 0 {
		return query.Where("1 = 0")
	}
	return query.Where("creator_shop_id IN ?", shopIDs)
}

// MarkFailed 将任务标记为整体失败。
func (s *AssetPackageBatchOrderTaskStore) MarkFailed(ctx context.Context, id uint, message string) error {
	now := time.Now()
	return s.db.WithContext(ctx).Model(&model.AssetPackageBatchOrderTask{}).Where("id = ?", id).
		Updates(map[string]any{"status": asynctask.StatusFailed, "error_message": message, "completed_at": now, "updated_at": now}).Error
}

// Complete 保存逐行结果并完成任务。
func (s *AssetPackageBatchOrderTaskStore) Complete(ctx context.Context, id uint, items model.AssetPackageBatchOrderResultItems, successCount, failCount int) error {
	now := time.Now()
	return s.db.WithContext(ctx).Model(&model.AssetPackageBatchOrderTask{}).
		Where("id = ? AND status = ?", id, asynctask.StatusProcessing).
		Updates(map[string]any{
			"status": asynctask.StatusCompleted, "total_count": len(items),
			"success_count": successCount, "fail_count": failCount,
			"result_items": items, "completed_at": now, "updated_at": now,
		}).Error
}

// GenerateTaskNo 生成批量订购任务编号。
func (s *AssetPackageBatchOrderTaskStore) GenerateTaskNo() string {
	now := time.Now()
	return fmt.Sprintf("BPO-%s-%06d", now.Format("20060102"), now.UnixNano()%1000000)
}
