package dbsync

import (
	"context"
	"path/filepath"
	"testing"
)

func TestEnsureTableFromColumnsEmpty(t *testing.T) {
	dir := t.TempDir()
	dsn := "file:" + filepath.ToSlash(filepath.Join(dir, "empty.db")) + "?_pragma=busy_timeout(5000)"
	db, err := Open(DriverSQLite, dsn)
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	ctx := context.Background()
	cols := []string{"id", "username", "password", "email"}
	if err := EnsureTableFromColumns(ctx, db, DriverSQLite, "accounts", "id", cols); err != nil {
		t.Fatal(err)
	}
	var n int64
	if err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM accounts`).Scan(&n); err != nil || n != 0 {
		t.Fatalf("want empty table n=%d err=%v", n, err)
	}
	// idempotent
	if err := EnsureTableFromColumns(ctx, db, DriverSQLite, "accounts", "id", cols); err != nil {
		t.Fatal(err)
	}
}

func TestEnsureSchemasOnRemoteCreatesEmpty(t *testing.T) {
	dir := t.TempDir()
	dsn := "file:" + filepath.ToSlash(filepath.Join(dir, "remote.db")) + "?_pragma=busy_timeout(5000)"
	ch := &Channel{
		ID: "ch1",
		Remote: Endpoint{
			Driver: DriverSQLite,
			DSN:    dsn,
		},
	}
	ctx := context.Background()
	defer InvalidateRemote(DriverSQLite, dsn)
	res, err := EnsureSchemasOnRemote(ctx, ch, SchemaEnsureRequest{
		Tables: []SchemaTableSpec{{
			Table:    "accounts",
			PKColumn: "id",
			Columns:  []string{"id", "username", "email"},
		}},
	})
	if err != nil {
		t.Fatal(err)
	}
	if !res.OK || len(res.Results) != 1 || !res.Results[0].Created {
		t.Fatalf("unexpected: %+v", res)
	}
	desc, err := DescribeSchemasFromRemote(ctx, ch, SchemaDescribeRequest{})
	if err != nil {
		t.Fatal(err)
	}
	if len(desc.Tables) != 1 || desc.Tables[0].Name != "accounts" || desc.Tables[0].RowCount != 0 {
		t.Fatalf("describe: %+v", desc)
	}
	if len(desc.Tables[0].Columns) < 2 {
		t.Fatalf("columns: %v", desc.Tables[0].Columns)
	}
}

func TestPullEmptyTableReturnsColumns(t *testing.T) {
	dir := t.TempDir()
	dsn := "file:" + filepath.ToSlash(filepath.Join(dir, "pull.db")) + "?_pragma=busy_timeout(5000)"
	db, err := Open(DriverSQLite, dsn)
	if err != nil {
		t.Fatal(err)
	}
	ctx := context.Background()
	if err := EnsureTableFromColumns(ctx, db, DriverSQLite, "accounts", "id", []string{"id", "username"}); err != nil {
		t.Fatal(err)
	}
	_ = db.Close()

	ch := &Channel{ID: "ch1", Remote: Endpoint{Driver: DriverSQLite, DSN: dsn}}
	defer InvalidateRemote(DriverSQLite, dsn)
	res, err := PullFromRemote(ctx, ch, nil, PullRequest{Mode: PullModeBootstrap, Table: "accounts"})
	if err != nil {
		t.Fatal(err)
	}
	if len(res.Items) != 0 {
		t.Fatalf("want empty items: %+v", res.Items)
	}
	if len(res.Columns) < 2 {
		t.Fatalf("want columns for empty table: %+v", res)
	}
}
