//go:build integration

package store_test

import (
	"context"
	"testing"

	mysqlmodule "github.com/testcontainers/testcontainers-go/modules/mysql"

	"github.com/wangjia/pangolin/server/internal/config"
	"github.com/wangjia/pangolin/server/internal/store"
)

// TestIntegration_TimeZoneAssertionAndMigrateUp starts a real MySQL 8 container
// and verifies:
//  1. store.Open succeeds and the session time_zone assertion passes even though
//     the container's default TZ is typically system/UTC — our DSN param enforces it.
//  2. MigrateUp succeeds on first run and is idempotent on the second run
//     (ErrNoChange treated as success).
//  3. MigrateDown succeeds and returns the schema to baseline.
func TestIntegration_TimeZoneAssertionAndMigrateUp(t *testing.T) {
	ctx := context.Background()

	ctr, err := mysqlmodule.Run(ctx,
		"mysql:8",
		mysqlmodule.WithDatabase("pangolin"),
		mysqlmodule.WithUsername("root"),
		mysqlmodule.WithPassword("secret"),
	)
	if err != nil {
		t.Fatalf("start mysql container: %v", err)
	}
	t.Cleanup(func() {
		if err := ctr.Terminate(ctx); err != nil {
			t.Logf("terminate container: %v", err)
		}
	})

	// ConnectionString returns e.g. root:secret@tcp(localhost:PORT)/pangolin
	dsn, err := ctr.ConnectionString(ctx)
	if err != nil {
		t.Fatalf("connection string: %v", err)
	}

	cfg := &config.Config{DSN: dsn}

	// ── 1. Open (includes UTC assertion) ─────────────────────────────────────
	db, err := store.Open(cfg)
	if err != nil {
		t.Fatalf("store.Open: %v", err)
	}
	defer db.Close()

	// ── 2. First MigrateUp ───────────────────────────────────────────────────
	if err := store.MigrateUp(db, "mysql"); err != nil {
		t.Fatalf("MigrateUp (first): %v", err)
	}

	v, dirty, err := store.MigrateVersion(db, "mysql")
	if err != nil {
		t.Fatalf("MigrateVersion after up: %v", err)
	}
	if dirty {
		t.Errorf("schema is dirty after MigrateUp")
	}
	if v == 0 {
		t.Errorf("version is still 0 after MigrateUp — no migrations applied?")
	}
	t.Logf("after MigrateUp: version=%d dirty=%v", v, dirty)

	// ── 3. Idempotent second MigrateUp ───────────────────────────────────────
	if err := store.MigrateUp(db, "mysql"); err != nil {
		t.Fatalf("MigrateUp (idempotent): %v", err)
	}

	// ── 4. MigrateDown ───────────────────────────────────────────────────────
	if err := store.MigrateDown(db, "mysql"); err != nil {
		t.Fatalf("MigrateDown: %v", err)
	}

	v2, _, err := store.MigrateVersion(db, "mysql")
	if err != nil {
		t.Fatalf("MigrateVersion after down: %v", err)
	}
	t.Logf("after MigrateDown: version=%d", v2)
}

// TestIntegration_NonUTCContainerStillPasses verifies that even when the
// MySQL server's global time_zone is left at its default, our DSN-level
// override forces the session to +00:00 and the assertion in store.Open passes.
func TestIntegration_NonUTCContainerStillPasses(t *testing.T) {
	ctx := context.Background()

	ctr, err := mysqlmodule.Run(ctx,
		"mysql:8",
		mysqlmodule.WithDatabase("pangolin"),
		mysqlmodule.WithUsername("root"),
		mysqlmodule.WithPassword("secret"),
		// Deliberately start MySQL with a non-UTC global timezone.
		mysqlmodule.WithConfigFile(""),
	)
	if err != nil {
		t.Fatalf("start mysql container: %v", err)
	}
	t.Cleanup(func() { _ = ctr.Terminate(ctx) })

	dsn, err := ctr.ConnectionString(ctx)
	if err != nil {
		t.Fatalf("connection string: %v", err)
	}

	cfg := &config.Config{DSN: dsn}
	db, err := store.Open(cfg)
	if err != nil {
		t.Fatalf("store.Open with default container TZ: %v", err)
	}
	db.Close()
}
