package stacks

import (
	"path"
	"reflect"
	"testing"

	"gitea.dooplex.hu/admin/felhom-controller/internal/appbackup"
)

// absSet returns the sorted Abs slice of a CaptureSet's Paths (helper for exact assertions).
func absSet(cs appbackup.CaptureSet) []string {
	out := make([]string, 0, len(cs.Paths))
	for _, p := range cs.Paths {
		out = append(out, p.Abs)
	}
	return out
}

// TestCaptureSet_Wiring (Scenario G, F-S3 no-seam): a real .felhom.yml backup block + real compose,
// loaded through a REAL stacks.Manager, must produce the exact per-tier capture sets end-to-end —
// ClassifiedBinds → ComputeCaptureSet — with no fake between the parser, validator, classifier, and
// the capture computation (the wiring is where a class-constant typo would otherwise hide).
func TestCaptureSet_Wiring(t *testing.T) {
	felhom := `display_name: Wiretest
backup:
  userdata:
    - path: media/photos
      class: optional
`
	// appdata/wiretest is UNLISTED + writable → default mandatory; media/photos is :ro but EXPLICIT
	// optional (explicit beats the :ro reader-default).
	compose := `services:
  wiretest:
    volumes:
      - ${HDD_PATH}/appdata/wiretest:/data
      - ${USERDATA_PATH}/media/photos:/external/photos:ro
`
	m := newClassifyManager(t, felhom, compose)
	cbs, has := m.ClassifiedBinds("app")
	if !has {
		t.Fatal("valid block must classify end-to-end (hasClassification=true)")
	}

	const hddPath = "/mnt/drv"
	wantWiretest := path.Join(hddPath, "appdata/wiretest")
	wantPhotos := path.Join(hddPath, "userdata", "media/photos")

	// Secondary: mandatory + optional, sorted by Abs.
	sec := appbackup.ComputeCaptureSet(cbs, has, appbackup.TierSecondary, hddPath)
	if got, want := absSet(sec), []string{wantWiretest, wantPhotos}; !reflect.DeepEqual(got, want) {
		t.Errorf("secondary Paths = %v, want %v", got, want)
	}
	// Offsite: mandatory only — the explicit-optional :ro library must NOT appear.
	off := appbackup.ComputeCaptureSet(cbs, has, appbackup.TierOffsite, hddPath)
	if got, want := absSet(off), []string{wantWiretest}; !reflect.DeepEqual(got, want) {
		t.Errorf("offsite Paths = %v, want %v (optional :ro must not ship offsite)", got, want)
	}
	// classes ride through end-to-end
	for _, p := range sec.Paths {
		if p.Abs == wantPhotos && p.Class != appbackup.ClassOptional {
			t.Errorf("media/photos class = %q, want optional (explicit beats :ro default, through the real Manager)", p.Class)
		}
		if p.Abs == wantWiretest && p.Class != appbackup.ClassMandatory {
			t.Errorf("appdata/wiretest class = %q, want mandatory (unlisted writable default)", p.Class)
		}
	}
}
