// Package db 提供数据库相关的基础设施工具，包括 golang-migrate 迁移运行器。
package db

import (
	"context"
	"errors"
	"fmt"

	"github.com/golang-migrate/migrate/v4"
	// 注册 postgres 数据库驱动（database://postgres）。
	_ "github.com/golang-migrate/migrate/v4/database/postgres"
	// 注册 file:// 迁移源驱动。
	_ "github.com/golang-migrate/migrate/v4/source/file"
)

// Migrate 跑指定路径下的迁移到最新版本。ctx 取消可让本函数提前返回 ctx.Err()，
// 但底层 golang-migrate 不接 ctx，已经 in-flight 的 Up() 会继续在后台 goroutine
// 中执行直到自然完成（或外部 statement_timeout 触发）。
// migrationsPath 形如 "file://migrations"，dsn 为 postgres 连接串。
// 当无新迁移可应用时（migrate.ErrNoChange）视为成功，返回 nil。
func Migrate(ctx context.Context, dsn, migrationsPath string) error {
	m, err := migrate.New(migrationsPath, dsn)
	if err != nil {
		return fmt.Errorf("init migrate: %w", err)
	}
	errCh := make(chan error, 1)
	go func() {
		if err := m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
			errCh <- err
			return
		}
		errCh <- nil
	}()
	select {
	case err := <-errCh:
		_, _ = m.Close()
		if err != nil {
			return fmt.Errorf("migrate up: %w", err)
		}
		return nil
	case <-ctx.Done():
		// 注意：m.Close 不能在这里调，会与正在跑的 Up() 竞态。让 goroutine 自然结束。
		return ctx.Err()
	}
}
