package organization

import (
	"context"
	"fmt"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

func TestListOrganizationsForUserUsesCoreDBRuntime(t *testing.T) {
	tx := &recordingOrganizationTx{rows: &recordingRows{}}
	db := &recordingOrganizationDB{tx: tx}
	service := &Service{db: db}

	organizations, err := service.ListOrganizationsForUser(context.Background(), "usr_123")
	require.NoError(t, err)
	require.Empty(t, organizations)
	require.Equal(t, 1, db.beginTxCalls)
	require.Equal(t, 1, tx.queryCalls)
	require.Equal(t, 1, tx.commitCalls)
	require.Zero(t, tx.rollbackCalls)
	require.Contains(t, tx.lastQuery, "FROM organization_members")
	require.Equal(t, []any{"usr_123"}, tx.lastArgs)
}

type recordingOrganizationDB struct {
	tx           *recordingOrganizationTx
	beginTxCalls int
}

func (db *recordingOrganizationDB) QueryRow(context.Context, string, ...any) coredb.Row {
	return organizationErrorRow{err: fmt.Errorf("unexpected QueryRow call")}
}

func (db *recordingOrganizationDB) Query(_ context.Context, query string, args ...any) (coredb.Rows, error) {
	return nil, fmt.Errorf("unexpected Query call on db")
}

func (db *recordingOrganizationDB) Exec(context.Context, string, ...any) (coredb.Result, error) {
	return nil, fmt.Errorf("unexpected Exec call")
}

func (db *recordingOrganizationDB) BeginTx(context.Context, coredb.TxOptions) (coredb.Tx, error) {
	db.beginTxCalls++
	return db.tx, nil
}

type recordingOrganizationTx struct {
	rows          coredb.Rows
	queryCalls    int
	lastQuery     string
	lastArgs      []any
	commitCalls   int
	rollbackCalls int
}

func (tx *recordingOrganizationTx) QueryRow(context.Context, string, ...any) coredb.Row {
	return organizationErrorRow{err: fmt.Errorf("unexpected QueryRow call")}
}

func (tx *recordingOrganizationTx) Query(_ context.Context, query string, args ...any) (coredb.Rows, error) {
	tx.queryCalls++
	tx.lastQuery = query
	tx.lastArgs = append([]any(nil), args...)
	return tx.rows, nil
}

func (tx *recordingOrganizationTx) Exec(context.Context, string, ...any) (coredb.Result, error) {
	return nil, fmt.Errorf("unexpected Exec call")
}

func (tx *recordingOrganizationTx) Commit(context.Context) error {
	tx.commitCalls++
	return nil
}

func (tx *recordingOrganizationTx) Rollback(context.Context) error {
	tx.rollbackCalls++
	return nil
}

type recordingRows struct{}

func (*recordingRows) Close()            {}
func (*recordingRows) Err() error        { return nil }
func (*recordingRows) Next() bool        { return false }
func (*recordingRows) Scan(...any) error { return nil }

type organizationErrorRow struct {
	err error
}

func (row organizationErrorRow) Scan(...any) error {
	return row.err
}
