package db

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/jackc/pgx/v5"
)

// BackupRow is the persisted form of a backup.
type BackupRow struct {
	ID          string
	InstanceID  string
	AgentID     string
	Path        string
	SizeBytes   int64
	Description string
	CreatedAt   time.Time
}

func (db *DB) InsertBackup(ctx context.Context, r BackupRow) error {
	_, err := db.pool.Exec(ctx, `
		INSERT INTO backups (id, instance_id, agent_id, path, size_bytes, description)
		VALUES ($1, $2, $3, $4, $5, $6)
	`, r.ID, r.InstanceID, r.AgentID, r.Path, r.SizeBytes, r.Description)
	if err != nil {
		return fmt.Errorf("insert backup: %w", err)
	}
	return nil
}

func (db *DB) DeleteBackup(ctx context.Context, id string) error {
	_, err := db.pool.Exec(ctx, `DELETE FROM backups WHERE id = $1`, id)
	if err != nil {
		return fmt.Errorf("delete backup: %w", err)
	}
	return nil
}

func (db *DB) GetBackup(ctx context.Context, id string) (*BackupRow, error) {
	var r BackupRow
	err := db.pool.QueryRow(ctx, `
		SELECT id, instance_id, agent_id, path, size_bytes, description, created_at
		FROM backups WHERE id = $1
	`, id).Scan(&r.ID, &r.InstanceID, &r.AgentID, &r.Path, &r.SizeBytes, &r.Description, &r.CreatedAt)
	if errors.Is(err, pgx.ErrNoRows) {
		return nil, errors.New("backup not found")
	}
	if err != nil {
		return nil, fmt.Errorf("get backup: %w", err)
	}
	return &r, nil
}

func (db *DB) ListBackupsByInstance(ctx context.Context, instanceID string) ([]BackupRow, error) {
	rows, err := db.pool.Query(ctx, `
		SELECT id, instance_id, agent_id, path, size_bytes, description, created_at
		FROM backups WHERE instance_id = $1
		ORDER BY created_at DESC
	`, instanceID)
	if err != nil {
		return nil, fmt.Errorf("list backups: %w", err)
	}
	defer rows.Close()
	var out []BackupRow
	for rows.Next() {
		var r BackupRow
		if err := rows.Scan(&r.ID, &r.InstanceID, &r.AgentID, &r.Path, &r.SizeBytes, &r.Description, &r.CreatedAt); err != nil {
			return nil, fmt.Errorf("scan: %w", err)
		}
		out = append(out, r)
	}
	return out, rows.Err()
}
