package backup

import (
	"context"
	"sync/atomic"
	"testing"
	"time"

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

// 8B.2: in snapshot mode, the runner fires onSnapshot when the storage-snapshot marker appears in
// the task log — mid-backup, before completion.
func TestBackupWithSnapshotHook_FiresOnMarker(t *testing.T) {
	old := snapshotWatchInterval
	snapshotWatchInterval = 2 * time.Millisecond
	defer func() { snapshotWatchInterval = old }()

	api := &fakeBackupAPI{
		vzdumpUPID: "UPID:backup",
		waitGate:   make(chan struct{}), // hold the backup open so the watcher gets to poll
		logLines:   []string{"INFO: backup mode: snapshot", "INFO: create storage snapshot 'vzdump'"},
		content:    []proxmox.StorageContent{{VolID: "local:backup/vzdump-lxc-9001-x", Content: "backup", VMID: 9001, Size: 100, CTime: 1}},
	}
	r := NewBackupRunner(api, "local", "", "", quiet())

	var fired int32
	done := make(chan struct{})
	go func() {
		_, _ = r.BackupWithSnapshotHook(context.Background(), 9001, func() { atomic.StoreInt32(&fired, 1) })
		close(done)
	}()

	// the watcher should fire onSnapshot well before we release the backup
	deadline := time.Now().Add(time.Second)
	for time.Now().Before(deadline) && atomic.LoadInt32(&fired) == 0 {
		time.Sleep(2 * time.Millisecond)
	}
	if atomic.LoadInt32(&fired) != 1 {
		t.Fatal("onSnapshot did not fire on the storage-snapshot marker")
	}
	close(api.waitGate) // let the backup complete
	<-done
}

// Stop/downgraded mode → no storage-snapshot marker → onSnapshot never fires (the 8B.2 fallback).
func TestBackupWithSnapshotHook_StopMode_NeverFires(t *testing.T) {
	old := snapshotWatchInterval
	snapshotWatchInterval = 2 * time.Millisecond
	defer func() { snapshotWatchInterval = old }()

	api := &fakeBackupAPI{
		vzdumpUPID: "UPID:backup",
		waitGate:   make(chan struct{}),
		logLines:   []string{"INFO: backup mode: stop"}, // downgraded; no snapshot marker
		content:    []proxmox.StorageContent{{VolID: "local:backup/vzdump-lxc-9001-x", Content: "backup", VMID: 9001, Size: 100, CTime: 1}},
	}
	r := NewBackupRunner(api, "local", "", "", quiet())

	var fired int32
	done := make(chan struct{})
	go func() {
		_, _ = r.BackupWithSnapshotHook(context.Background(), 9001, func() { atomic.StoreInt32(&fired, 1) })
		close(done)
	}()
	time.Sleep(40 * time.Millisecond) // the watcher polls several times + sees stop mode → returns
	if atomic.LoadInt32(&fired) != 0 {
		t.Fatal("onSnapshot fired in stop mode (must not)")
	}
	close(api.waitGate)
	<-done
}
