package sqlite

import (
	"context"
	"fmt"
	"strings"
)

type ImportRunItemEvent struct {
	EventID     string
	RunID       string
	ItemID      string
	EventType   string
	Stage       string
	Attempt     int
	Message     string
	PayloadJSON string
	CreatedAt   string
}

type ImportRunItemEventsRepo struct {
	db execQuerier
}

func newImportRunItemEventsRepo(db execQuerier) *ImportRunItemEventsRepo {
	return &ImportRunItemEventsRepo{db: db}
}

func (r *ImportRunItemEventsRepo) Create(ctx context.Context, event ImportRunItemEvent) error {
	return r.Append(ctx, event)
}

func (r *ImportRunItemEventsRepo) Append(ctx context.Context, event ImportRunItemEvent) error {
	eventID := strings.TrimSpace(event.EventID)
	runID := strings.TrimSpace(event.RunID)
	itemID := strings.TrimSpace(event.ItemID)
	eventType := strings.TrimSpace(event.EventType)
	stage := strings.TrimSpace(event.Stage)
	message := strings.TrimSpace(event.Message)
	payloadJSON := defaultJSON(event.PayloadJSON, "{}")

	switch {
	case eventID == "":
		return fmt.Errorf("event_id is required")
	case runID == "":
		return fmt.Errorf("run_id is required")
	case itemID == "":
		return fmt.Errorf("item_id is required")
	case eventType == "":
		return fmt.Errorf("event_type is required")
	case stage == "":
		return fmt.Errorf("stage is required")
	case message == "":
		return fmt.Errorf("message is required")
	}

	if _, err := r.db.ExecContext(ctx, `INSERT INTO import_run_item_events (event_id, run_id, item_id, event_type, stage, attempt, message, payload_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
		eventID, runID, itemID, eventType, stage, event.Attempt, message, payloadJSON); err != nil {
		return fmt.Errorf("insert import run item event %q: %w", eventID, err)
	}
	return nil
}

func (r *ImportRunItemEventsRepo) ListByItemID(ctx context.Context, itemID string) ([]ImportRunItemEvent, error) {
	itemID = strings.TrimSpace(itemID)
	if itemID == "" {
		return nil, fmt.Errorf("item_id is required")
	}

	rows, err := r.db.QueryContext(ctx, `SELECT event_id, run_id, item_id, event_type, stage, attempt, message, payload_json, created_at FROM import_run_item_events WHERE item_id = ? ORDER BY created_at, event_id`, itemID)
	if err != nil {
		return nil, fmt.Errorf("list import run item events by item_id %q: %w", itemID, err)
	}
	defer rows.Close()

	events := make([]ImportRunItemEvent, 0)
	for rows.Next() {
		var event ImportRunItemEvent
		if err := rows.Scan(&event.EventID, &event.RunID, &event.ItemID, &event.EventType, &event.Stage, &event.Attempt, &event.Message, &event.PayloadJSON, &event.CreatedAt); err != nil {
			return nil, fmt.Errorf("scan import run item event: %w", err)
		}
		events = append(events, event)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate import run item events by item_id %q: %w", itemID, err)
	}
	return events, nil
}
