package main

import (
	"database/sql"
	"errors"
	"os"
	"path/filepath"
	"testing"
)

// TestFileStore menguji FileStore secara table-driven.
// Setiap kasus memakai berkas sendiri di t.TempDir() sehingga
// test tidak berbagi data dan gagal karena bentrok.
func TestFileStore(t *testing.T) {
	tests := []struct {
		nama     string
		jalankan func(t *testing.T)
	}{
		{
			nama: "Create lalu Get mengembalikan pelanggan sama",
			jalankan: func(t *testing.T) {
				store := NewFileStore(filepath.Join(t.TempDir(), "pelanggan.json"))
				dibuat, err := store.Create("Budi", "budi@example.com")
				if err != nil {
					t.Fatalf("Create gagal: %v", err)
				}
				diambil, err := store.Get(dibuat.ID)
				if err != nil {
					t.Fatalf("Get gagal: %v", err)
				}
				if diambil != dibuat {
					t.Errorf("Get = %+v; ingin %+v", diambil, dibuat)
				}
			},
		},
		{
			nama: "Get ID yang tidak ada mengembalikan ErrNotFound",
			jalankan: func(t *testing.T) {
				store := NewFileStore(filepath.Join(t.TempDir(), "pelanggan.json"))
				_, err := store.Get(99)
				if !errors.Is(err, ErrNotFound) {
					t.Errorf("err = %v; ingin ErrNotFound", err)
				}
			},
		},
		{
			nama: "List terurut naik berdasarkan ID",
			jalankan: func(t *testing.T) {
				store := NewFileStore(filepath.Join(t.TempDir(), "pelanggan.json"))
				store.Create("Budi", "budi@example.com")
				store.Create("Siti", "siti@example.com")
				store.Create("Ayu", "ayu@example.com")
				daftar, err := store.List()
				if err != nil {
					t.Fatalf("List gagal: %v", err)
				}
				for i, p := range daftar {
					if p.ID != i+1 {
						t.Errorf("daftar[%d].ID = %d; ingin %d", i, p.ID, i+1)
					}
				}
			},
		},
		{
			nama: "Delete menghapus data dari penyimpanan",
			jalankan: func(t *testing.T) {
				store := NewFileStore(filepath.Join(t.TempDir(), "pelanggan.json"))
				dibuat, _ := store.Create("Budi", "budi@example.com")
				if err := store.Delete(dibuat.ID); err != nil {
					t.Fatalf("Delete gagal: %v", err)
				}
				if _, err := store.Get(dibuat.ID); !errors.Is(err, ErrNotFound) {
					t.Errorf("Get setelah Delete = %v; ingin ErrNotFound", err)
				}
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.nama, func(t *testing.T) {
			tt.jalankan(t)
		})
	}
}

// TestPostgresIntegration hanya berjalan bila TEST_DATABASE_URL diisi.
// Tanpa variabel tersebut, test ini melompat (SKIP) — bukan gagal —
// sehingga `go test` tetap hijau di lingkungan tanpa database.
func TestPostgresIntegration(t *testing.T) {
	url := os.Getenv("TEST_DATABASE_URL")
	if url == "" {
		t.Skip("TEST_DATABASE_URL kosong — lewati uji integrasi PostgreSQL")
	}

	// Driver "pgx" teregistrasi lewat blank import di proyek nyata
	// (lihat proyek rest-api-postgresql); materi ini membiarkannya
	// stdlib-only sehingga test dijalankan hanya di lingkungan lengkap.
	db, err := sql.Open("pgx", url)
	if err != nil {
		t.Fatalf("buka database uji: %v", err)
	}
	defer db.Close()

	var satu int
	if err := db.QueryRow("SELECT 1").Scan(&satu); err != nil {
		t.Fatalf("query pemanasan: %v", err)
	}
}
