package storage

import (
	"strings"

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

// deriveDurableID computes the DR-load-bearing durable identifier for a target (doc 03
// §7). It MUST be deterministic: the hub stores it and, on host loss, re-attaches the
// RIGHT physical target by it — the false-id failure mode is re-attaching the WRONG disk.
//
// Per type:
//   - usb / local-dir: the filesystem UUID of the backing device (survives re-cabling /
//     re-enumeration that renames /dev/sdX).
//   - nfs / cifs:       "server:export" (or "server:share") — the network identity.
//   - pbs:              "server:datastore" plus the cert fingerprint ("…#<fp>") — the repo
//     identity (the fingerprint pins WHICH PBS, so a spoofed server is a different id).
//   - lvmthin / lvm:    "vgname/thinpool" (or "vgname") — informational but stable; the VG
//     is local and not re-attached cross-host, so a stable name is enough.
//   - local (builtin):  the backing fs UUID if resolvable, else the path — informational.
//
// uuid is the already-resolved backing-device UUID ("" when unresolved); the caller
// resolves it once (it also needs it for nothing else, so we pass it in to avoid a second
// by-uuid scan).
func deriveDurableID(typ string, s proxmox.Storage, backingDevice, uuid string) string {
	switch typ {
	case hubTypeNFS:
		if s.Server != "" && s.Export != "" {
			return s.Server + ":" + s.Export
		}
	case hubTypeCIFS:
		if s.Server != "" && s.Share != "" {
			return s.Server + ":" + s.Share
		}
	case hubTypePBS:
		repo := s.Datastore
		if s.Server != "" {
			repo = s.Server + ":" + s.Datastore
		}
		if repo != "" {
			if s.Fingerprint != "" {
				return repo + "#" + strings.ToLower(s.Fingerprint)
			}
			return repo
		}
	case hubTypeLVMThin, "lvm":
		if s.VGName != "" {
			if s.ThinPool != "" {
				return s.VGName + "/" + s.ThinPool
			}
			return s.VGName
		}
	case hubTypeUSB, hubTypeLocalDir, hubTypeLocal:
		if uuid != "" {
			return "uuid:" + uuid
		}
		if backingDevice != "" {
			return "dev:" + backingDevice
		}
		if s.Path != "" {
			return "path:" + s.Path
		}
	}
	// Fallback: a stable, unambiguous id from the storage name — never empty (an empty
	// durable_id would defeat the hub's re-attach lookup).
	return "store:" + s.Storage
}

// Reported storage-type strings (mirror hub's StorageType* constants without importing
// hub here for the bare strings — the observer maps to these).
const (
	hubTypeLocalDir = "local-dir"
	hubTypeLVMThin  = "lvmthin"
	hubTypeUSB      = "usb"
	hubTypeNFS      = "nfs"
	hubTypeCIFS     = "cifs"
	hubTypePBS      = "pbs"
	hubTypeLocal    = "local"
)
