package precheck

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
)

type FileRouterTestSuite struct {
	suite.Suite
}

func (suite *FileRouterTestSuite) TestNewFileRouter() {
	assert := require.New(suite.T())
	ctx := context.Background()
	// Test case 1: Valid configuration
	cfg := []*FileRouteRule{
		{
			Pattern: `^(?P<schema>\w+)\.(?P<table>\w+)\.sql$`,
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TypeSQL,
		},
	}
	router, err := NewFileRouter(ctx, cfg)
	assert.NoError(err)
	assert.NotNil(router)

	// Test case 2: Empty pattern
	invalidCfg := []*FileRouteRule{
		{
			Pattern: "",
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TypeSQL,
		},
	}
	router, err = NewFileRouter(ctx, invalidCfg)
	assert.Error(err)
	assert.Nil(router)

	// Test case 3: Invalid regex pattern
	invalidCfg = []*FileRouteRule{
		{
			Pattern: "[invalid",
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TypeSQL,
		},
	}
	router, err = NewFileRouter(ctx, invalidCfg)
	assert.Error(err)
	assert.Nil(router)
}

func (suite *FileRouterTestSuite) TestRegexRouterRoute() {
	assert := require.New(suite.T())
	ctx := context.Background()
	// Create a router with SQL file pattern
	cfg := []*FileRouteRule{
		{
			Pattern: `^(?P<schema>\w+)\.(?P<table>\w+)\.sql$`,
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TypeSQL,
		},
	}
	router, bizErr := NewFileRouter(ctx, cfg)
	assert.NoError(bizErr)

	// Test case 1: Valid SQL file path
	result, err := router.Route("test.users.sql")
	assert.NoError(err)
	assert.NotNil(result)
	assert.Equal("test", result.Schema)
	assert.Equal("users", result.Name)
	assert.Equal(TypeSQL, result.Type)
	assert.Equal("test.users.sql", result.FilePath)

	// Test case 2: Non-matching path
	result, err = router.Route("invalid_path.txt")
	assert.NoError(err)
	assert.Nil(result)
}

func (suite *FileRouterTestSuite) TestMultiplePatterns() {
	assert := require.New(suite.T())
	ctx := context.Background()
	// Create a router with multiple patterns
	cfg := []*FileRouteRule{
		{
			Pattern: `^(?P<schema>\w+)-schema-create\.sql$`,
			Schema:  "${schema}",
			Type:    SchemaSchema,
		},
		{
			Pattern: `^(?P<schema>\w+)\.(?P<table>\w+)-schema\.sql$`,
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TableSchema,
		},
		{
			Pattern: `^(?P<schema>\w+)\.(?P<table>\w+)\.sql$`,
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TypeSQL,
		},
	}
	router, bizErr := NewFileRouter(ctx, cfg)
	assert.NoError(bizErr)

	// Test case 1: Schema file
	result, err := router.Route("test-schema-create.sql")
	assert.NoError(err)
	assert.NotNil(result)
	assert.Equal("test", result.Schema)
	assert.Equal("", result.Name)
	assert.Equal(SchemaSchema, result.Type)

	// Test case 2: Table schema file
	result, err = router.Route("test.users-schema.sql")
	assert.NoError(err)
	assert.NotNil(result)
	assert.Equal("test", result.Schema)
	assert.Equal("users", result.Name)
	assert.Equal(TableSchema, result.Type)

	// Test case 3: SQL data file
	result, err = router.Route("test.users.sql")
	assert.NoError(err)
	assert.NotNil(result)
	assert.Equal("test", result.Schema)
	assert.Equal("users", result.Name)
	assert.Equal(TypeSQL, result.Type)
}

func (suite *FileRouterTestSuite) TestCaseSensitivity() {
	assert := require.New(suite.T())
	ctx := context.Background()

	cfg := []*FileRouteRule{
		{
			Pattern: `^(?P<schema>\w+)\.(?P<table>\w+)\.sql$`,
			Schema:  "${schema}",
			Table:   "${table}",
			Type:    TypeSQL,
		},
	}
	router, bizErr := NewFileRouter(ctx, cfg)
	assert.NoError(bizErr)

	// Test case: Mixed case input should result in lowercase schema and table
	result, err := router.Route("TEST.Users.sql")
	assert.NoError(err)
	assert.NotNil(result)
	assert.Equal("test", result.Schema)
	assert.Equal("users", result.Name)
	assert.Equal(TypeSQL, result.Type)
}

func (suite *FileRouterTestSuite) TestExactMatchRoute() {
	assert := require.New(suite.T())
	ctx := context.Background()

	cfg := []*FileRouteRule{
		{
			Pattern: "50_row.csv",
			Schema:  "test",
			Table:   "table",
			Type:    TypeCSV,
		},
	}
	router, bizErr := NewFileRouter(ctx, cfg)
	assert.NoError(bizErr)

	// Test case: file name exactly matches the pattern;
	// router should correctly extract schema, table, and type
	result, err := router.Route("50_row.csv")
	assert.NoError(err)
	assert.NotNil(result)
	assert.Equal("test", result.Schema)
	assert.Equal("table", result.Name)
	assert.Equal(TypeCSV, result.Type)
}

func TestFileRouterTestSuite(t *testing.T) {
	suite.Run(t, new(FileRouterTestSuite))
}
