package restic

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os/exec"
	"time"
)

// Snapshot mirrors a single entry in `restic snapshots --json`. We
// decode only the fields we project to the server; restic's full
// shape has more (parent, tree, program version) that we don't need.
//
// Summary is only populated by restic 0.17+ (which embeds the backup
// summary inside each snapshot record). Older clients leave it nil
// and the agent reports zero size/file-count — the UI degrades to
// "—" and the column headers carry a tooltip explaining the version
// requirement (see web/templates/pages/host_detail.html).
type Snapshot struct {
	ID       string           `json:"id"`
	ShortID  string           `json:"short_id"`
	Time     time.Time        `json:"time"`
	Hostname string           `json:"hostname"`
	Paths    []string         `json:"paths"`
	Tags     []string         `json:"tags,omitempty"`
	Summary  *SnapshotSummary `json:"summary,omitempty"`
}

// SnapshotSummary mirrors the embedded summary block restic 0.16+
// writes into each snapshot record. The naming follows restic's JSON.
type SnapshotSummary struct {
	TotalFilesProcessed int64 `json:"total_files_processed"`
	TotalBytesProcessed int64 `json:"total_bytes_processed"`
}

// ListSnapshots calls `restic snapshots --json` and returns the
// parsed list. Output is a single JSON array — small even on large
// repos (each entry is ~200 bytes), so we read it all into memory.
func (e Env) ListSnapshots(ctx context.Context) ([]Snapshot, error) {
	cmd := exec.CommandContext(ctx, e.Bin, "snapshots", "--json")
	cmd.Env = e.envSlice()
	cmd.Dir = e.WorkDir

	out, err := cmd.Output()
	if err != nil {
		var ee *exec.ExitError
		if errors.As(err, &ee) {
			return nil, fmt.Errorf("restic snapshots: exit %d: %s",
				ee.ExitCode(), string(ee.Stderr))
		}
		return nil, fmt.Errorf("restic snapshots: %w", err)
	}
	var snaps []Snapshot
	if err := json.Unmarshal(out, &snaps); err != nil {
		return nil, fmt.Errorf("restic snapshots: parse json: %w", err)
	}
	return snaps, nil
}
