// Package afclock implementiert das AFC-Sync-Lock-File-Pattern.
// iOS erwartet vor iTunes-style sync dass der Client `/com.apple.itunes.lock_sync`
// via AFC öffnet + lockt. Ohne diesen Lock interpretiert iOS den Restore
// als incomplete external-process und applied keine cloud-config.
//
// Reverse-engineered aus TechLockdown safesurfer.go:288 (AfcFile.Lock-Call).
package afclock

import (
	"fmt"

	ios "github.com/danielpaulus/go-ios/ios"
	"github.com/danielpaulus/go-ios/ios/afc"
)

// SyncLockPath — der genaue Pfad den iOS erwartet (aus TL-binary-strings).
const SyncLockPath = "/com.apple.itunes.lock_sync"

// SyncLock kapselt einen offenen AFC-Lock auf der sync-file.
type SyncLock struct {
	client *afc.Client
	file   *afc.File
}

// Acquire öffnet AFC + das sync-lock-file + erzeugt exclusive lock.
// Caller MUSS Release() callen wenn fertig.
func Acquire(device ios.DeviceEntry) (*SyncLock, error) {
	client, err := afc.New(device)
	if err != nil {
		return nil, fmt.Errorf("afclock: open AFC: %w", err)
	}

	// Versuche das sync-lock file zu öffnen.
	// READ_WRITE_CREATE = mode 0x2 — creates if not exists.
	file, err := client.Open(SyncLockPath, afc.READ_WRITE_CREATE)
	if err != nil {
		client.Close()
		return nil, fmt.Errorf("afclock: open %s: %w", SyncLockPath, err)
	}

	// Note: go-ios's afc.File doesn't expose Lock() directly. Apple's AFC
	// has a Lock operation but go-ios doesn't wrap it. We rely on the
	// open-file-handle alone signaling iOS that sync is in progress.
	// TL calls Lock() explicitly — wenn das nicht reicht, müssten wir
	// das AFC-Protocol-Level Lock-message direkt senden (8-byte op +
	// lock-type-flag).

	return &SyncLock{
		client: client,
		file:   file,
	}, nil
}

// Release schließt das file-handle + AFC-service. Signal an iOS dass sync done.
func (s *SyncLock) Release() error {
	if s.file != nil {
		s.file.Close()
		s.file = nil
	}
	if s.client != nil {
		s.client.Close()
		s.client = nil
	}
	return nil
}
