package lockfile_test

import (
	"os"
	"path/filepath"
	"testing"
	"time"

	"ekdns/lockfile"
)

// T006-1: Acquire succeeds and lock file exists on disk.
func TestAcquireSucceeds(t *testing.T) {
	dir := t.TempDir()
	lock, err := lockfile.Acquire(dir)
	if err != nil {
		t.Fatalf("Acquire returned unexpected error: %v", err)
	}
	defer lock.Release()

	lockPath := filepath.Join(dir, ".ekdns.lock")
	if _, err := os.Stat(lockPath); os.IsNotExist(err) {
		t.Error("lock file does not exist after Acquire")
	}
}

// T006-2: Release deletes the lock file.
func TestReleaseDeletesLockFile(t *testing.T) {
	dir := t.TempDir()
	lock, err := lockfile.Acquire(dir)
	if err != nil {
		t.Fatalf("Acquire returned unexpected error: %v", err)
	}

	if err := lock.Release(); err != nil {
		t.Fatalf("Release returned unexpected error: %v", err)
	}

	lockPath := filepath.Join(dir, ".ekdns.lock")
	if _, err := os.Stat(lockPath); !os.IsNotExist(err) {
		t.Error("lock file still exists after Release")
	}
}

// T006-3: Double acquire fails with timeout error.
func TestDoubleAcquireFails(t *testing.T) {
	dir := t.TempDir()
	lock, err := lockfile.Acquire(dir)
	if err != nil {
		t.Fatalf("first Acquire returned unexpected error: %v", err)
	}
	defer lock.Release()

	_, err = lockfile.Acquire(dir)
	if err == nil {
		t.Fatal("second Acquire expected to fail, but it succeeded")
	}
}

// T006-4: Stale lock file (>2 minutes old) is broken and Acquire succeeds.
func TestStaleLockBroken(t *testing.T) {
	dir := t.TempDir()
	lockPath := filepath.Join(dir, ".ekdns.lock")

	// Manually create a lock file with a stale modification time.
	if err := os.WriteFile(lockPath, []byte("99999\n"), 0644); err != nil {
		t.Fatalf("failed to create stale lock file: %v", err)
	}
	staleTime := time.Now().Add(-3 * time.Minute)
	if err := os.Chtimes(lockPath, staleTime, staleTime); err != nil {
		t.Fatalf("failed to set stale mtime: %v", err)
	}

	lock, err := lockfile.Acquire(dir)
	if err != nil {
		t.Fatalf("Acquire over stale lock returned unexpected error: %v", err)
	}
	lock.Release()
}

// T006-5: Release is idempotent — calling twice does not return an error.
func TestReleaseIsIdempotent(t *testing.T) {
	dir := t.TempDir()
	lock, err := lockfile.Acquire(dir)
	if err != nil {
		t.Fatalf("Acquire returned unexpected error: %v", err)
	}

	if err := lock.Release(); err != nil {
		t.Fatalf("first Release returned unexpected error: %v", err)
	}
	if err := lock.Release(); err != nil {
		t.Fatalf("second Release returned unexpected error: %v", err)
	}
}
