package dbsync

import (
	"database/sql"
	"fmt"
	"strings"
	"sync"
	"time"
)

// remotePool 复用线上 A 连接，避免每次 push 冷开 SQLite（Windows 上常 >3s → 旧默认超时 503）。
type remotePool struct {
	mu  sync.Mutex
	dbs map[string]*pooledDB
}

type pooledDB struct {
	db       *sql.DB
	driver   Driver
	lastUsed time.Time
}

var sharedRemotePool = &remotePool{dbs: map[string]*pooledDB{}}

func poolKey(driver Driver, dsn string) string {
	if driver == DriverSQLite {
		dsn = normalizeSQLiteDSN(dsn)
	}
	return string(driver) + "|" + dsn
}

// AcquireRemote 获取（或新建）remote 连接；调用方不要 Close。
func AcquireRemote(driver Driver, dsn string) (*sql.DB, error) {
	return sharedRemotePool.acquire(driver, dsn)
}

func (p *remotePool) acquire(driver Driver, dsn string) (*sql.DB, error) {
	key := poolKey(driver, dsn)
	p.mu.Lock()
	defer p.mu.Unlock()
	if e, ok := p.dbs[key]; ok && e.db != nil {
		if err := e.db.Ping(); err == nil {
			e.lastUsed = time.Now()
			return e.db, nil
		}
		_ = e.db.Close()
		delete(p.dbs, key)
	}
	db, err := Open(driver, dsn)
	if err != nil {
		return nil, err
	}
	p.dbs[key] = &pooledDB{db: db, driver: driver, lastUsed: time.Now()}
	return db, nil
}

// WarmRemote 通道启动时预热，把冷开成本挪出请求路径。
func WarmRemote(driver Driver, dsn string) error {
	if strings.TrimSpace(dsn) == "" {
		return fmt.Errorf("dsn required")
	}
	_, err := AcquireRemote(driver, dsn)
	return err
}

// InvalidateRemote 通道 DSN 变更或停用时丢掉缓存连接。
func InvalidateRemote(driver Driver, dsn string) {
	key := poolKey(driver, dsn)
	sharedRemotePool.mu.Lock()
	defer sharedRemotePool.mu.Unlock()
	if e, ok := sharedRemotePool.dbs[key]; ok {
		_ = e.db.Close()
		delete(sharedRemotePool.dbs, key)
	}
}

// CloseAllRemotes 测试或进程退出时关闭池内连接。
func CloseAllRemotes() {
	sharedRemotePool.mu.Lock()
	defer sharedRemotePool.mu.Unlock()
	for k, e := range sharedRemotePool.dbs {
		_ = e.db.Close()
		delete(sharedRemotePool.dbs, k)
	}
}
