package pbs

import (
	"context"
	"sync"
	"time"

	"gitea.dooplex.hu/admin/felhom-agent/internal/hub"
)

// verify-state constants for the reported PBSSnapshot.
const (
	VerifyOK     = "ok"
	VerifyFailed = "failed"
	VerifyNone   = "none" // no verify has run yet (PBS omits the verification field)
)

// ToHub maps a PBS API Snapshot to the hub.PBSSnapshot wire record (slice 6 Phase B). The
// backup-time epoch becomes RFC3339; `encrypted` is derived from the data files'
// crypt-mode (any "encrypt" → encrypted); verify_state is "none" until a verify runs.
func (s Snapshot) ToHub() hub.PBSSnapshot {
	ns := s.Namespace
	if ns == "" {
		ns = "root"
	}
	out := hub.PBSSnapshot{
		Namespace:   ns,
		BackupType:  s.BackupType,
		BackupID:    s.BackupID,
		BackupTime:  time.Unix(s.BackupTime, 0).UTC().Format(time.RFC3339),
		SizeBytes:   s.Size,
		Owner:       s.Owner,
		Protected:   s.Protected,
		Encrypted:   s.encrypted(),
		VerifyState: VerifyNone,
	}
	if s.Verification != nil {
		out.VerifyState = s.Verification.State
		out.VerifyUPID = s.Verification.UPID
	}
	return out
}

// encrypted reports whether the snapshot's DATA is client-side encrypted (any data file with
// crypt-mode "encrypt"; index.json is "sign-only" and is ignored).
func (s Snapshot) encrypted() bool {
	for _, f := range s.Files {
		if f.CryptMode == "encrypt" {
			return true
		}
	}
	return false
}

// SnapshotStore holds the latest reported PBS snapshots per datastore — the point-in-time
// state the host-report surfaces. The verify loop writes it; the collector reads it via the
// hub PBSReporter seam. Mutex-guarded (concurrent collector vs loop).
type SnapshotStore struct {
	mu          sync.Mutex
	byDatastore map[string][]hub.PBSSnapshot
}

// NewSnapshotStore builds an empty store.
func NewSnapshotStore() *SnapshotStore {
	return &SnapshotStore{byDatastore: map[string][]hub.PBSSnapshot{}}
}

// Record replaces the snapshot set for a datastore.
func (s *SnapshotStore) Record(datastore string, snaps []hub.PBSSnapshot) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.byDatastore[datastore] = snaps
}

// PBSSnapshots implements hub.PBSReporter — all known snapshots across datastores.
func (s *SnapshotStore) PBSSnapshots(context.Context) []hub.PBSSnapshot {
	s.mu.Lock()
	defer s.mu.Unlock()
	out := []hub.PBSSnapshot{}
	for _, snaps := range s.byDatastore {
		out = append(out, snaps...)
	}
	return out
}
