package sqlite

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

type ReconcileRun struct {
	ID          int64
	BatchID     int64
	HostID      int64
	ProviderID  int64
	Status      string
	SummaryJSON string
	CreatedAt   string
}

type ReconcileRunsRepo struct {
	db execQuerier
}

func newReconcileRunsRepo(db execQuerier) *ReconcileRunsRepo {
	return &ReconcileRunsRepo{db: db}
}

func (r *ReconcileRunsRepo) Create(ctx context.Context, run ReconcileRun) (int64, error) {
	status := strings.TrimSpace(run.Status)
	summaryJSON := strings.TrimSpace(run.SummaryJSON)
	if summaryJSON == "" {
		summaryJSON = "{}"
	}

	switch {
	case run.BatchID <= 0:
		return 0, fmt.Errorf("batch_id is required")
	case run.HostID <= 0:
		return 0, fmt.Errorf("host_id is required")
	case run.ProviderID <= 0:
		return 0, fmt.Errorf("provider_id is required")
	case status == "":
		return 0, fmt.Errorf("status is required")
	}

	result, err := r.db.ExecContext(ctx, `INSERT INTO reconcile_runs (batch_id, host_id, provider_id, status, summary_json) VALUES (?, ?, ?, ?, ?)`, run.BatchID, run.HostID, run.ProviderID, status, summaryJSON)
	if err != nil {
		return 0, fmt.Errorf("insert reconcile run: %w", err)
	}

	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("read inserted reconcile run id: %w", err)
	}
	return id, nil
}

func (r *ReconcileRunsRepo) GetByBatchID(ctx context.Context, batchID int64) ([]ReconcileRun, error) {
	if batchID <= 0 {
		return nil, fmt.Errorf("batch_id is required")
	}

	rows, err := r.db.QueryContext(ctx, `SELECT id, batch_id, host_id, provider_id, status, summary_json, created_at FROM reconcile_runs WHERE batch_id = ? ORDER BY id DESC`, batchID)
	if err != nil {
		return nil, fmt.Errorf("query reconcile runs by batch_id: %w", err)
	}
	defer rows.Close()

	runs := make([]ReconcileRun, 0)
	for rows.Next() {
		var run ReconcileRun
		if err := rows.Scan(&run.ID, &run.BatchID, &run.HostID, &run.ProviderID, &run.Status, &run.SummaryJSON, &run.CreatedAt); err != nil {
			return nil, fmt.Errorf("scan reconcile run by batch_id: %w", err)
		}
		runs = append(runs, run)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate reconcile runs by batch_id: %w", err)
	}
	return runs, nil
}

func (r *ReconcileRunsRepo) GetByProviderIDAndHostID(ctx context.Context, providerID, hostID int64) ([]ReconcileRun, error) {
	if providerID <= 0 {
		return nil, fmt.Errorf("provider_id is required")
	}
	if hostID <= 0 {
		return nil, fmt.Errorf("host_id is required")
	}

	rows, err := r.db.QueryContext(ctx, `SELECT id, batch_id, host_id, provider_id, status, summary_json, created_at FROM reconcile_runs WHERE provider_id = ? AND host_id = ? ORDER BY id DESC`, providerID, hostID)
	if err != nil {
		return nil, fmt.Errorf("query reconcile runs: %w", err)
	}
	defer rows.Close()

	runs := make([]ReconcileRun, 0)
	for rows.Next() {
		var run ReconcileRun
		if err := rows.Scan(&run.ID, &run.BatchID, &run.HostID, &run.ProviderID, &run.Status, &run.SummaryJSON, &run.CreatedAt); err != nil {
			return nil, fmt.Errorf("scan reconcile run: %w", err)
		}
		runs = append(runs, run)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate reconcile runs: %w", err)
	}
	return runs, nil
}
