// migrate/main.go — SQLite → MySQL one-api data migration tool
// Usage: go run tools/migrate/main.go
package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"

	_ "github.com/go-sql-driver/mysql"
	_ "github.com/mattn/go-sqlite3"
)

const (
	sqlitePath = "one-api.db"
	mysqlDSN   = "root:123456@tcp(localhost:3306)/oneapi?charset=utf8mb4&parseTime=True&loc=Local"
)

func main() {
	if _, err := os.Stat(sqlitePath); os.IsNotExist(err) {
		log.Fatalf("SQLite file not found: %s", sqlitePath)
	}

	sqlite, err := sql.Open("sqlite3", sqlitePath)
	if err != nil {
		log.Fatalf("open sqlite: %v", err)
	}
	defer sqlite.Close()

	mysql, err := sql.Open("mysql", mysqlDSN)
	if err != nil {
		log.Fatalf("open mysql: %v", err)
	}
	defer mysql.Close()

	if err = mysql.Ping(); err != nil {
		log.Fatalf("mysql ping failed: %v\nCheck if MySQL is running and DSN is correct.", err)
	}

	fmt.Println("Connected to both databases. Starting migration...")

	tables := []string{"users", "channels", "tokens", "options", "redemptions", "logs", "abilities"}
	for _, table := range tables {
		if err := migrateTable(sqlite, mysql, table); err != nil {
			fmt.Printf("[WARN] table %s: %v\n", table, err)
		}
	}

	fmt.Println("\nMigration complete!")
}

func migrateTable(src, dst *sql.DB, table string) error {
	// Check table exists in SQLite
	var count int
	err := src.QueryRow(fmt.Sprintf("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='%s'", table)).Scan(&count)
	if err != nil || count == 0 {
		fmt.Printf("[SKIP] table %s not found in SQLite\n", table)
		return nil
	}

	// Get row count
	var total int
	_ = src.QueryRow(fmt.Sprintf("SELECT COUNT(*) FROM `%s`", table)).Scan(&total)
	if total == 0 {
		fmt.Printf("[SKIP] table %s is empty\n", table)
		return nil
	}

	// Read all rows
	rows, err := src.Query(fmt.Sprintf("SELECT * FROM `%s`", table))
	if err != nil {
		return fmt.Errorf("select from sqlite: %w", err)
	}
	defer rows.Close()

	cols, err := rows.Columns()
	if err != nil {
		return err
	}

	// Build INSERT statement with placeholders
	placeholders := ""
	colNames := ""
	for i, col := range cols {
		if i > 0 {
			placeholders += ","
			colNames += ","
		}
		placeholders += "?"
		colNames += fmt.Sprintf("`%s`", col)
	}
	insertSQL := fmt.Sprintf("INSERT IGNORE INTO `%s` (%s) VALUES (%s)", table, colNames, placeholders)

	stmt, err := dst.Prepare(insertSQL)
	if err != nil {
		return fmt.Errorf("prepare insert for %s: %w", table, err)
	}
	defer stmt.Close()

	inserted := 0
	vals := make([]interface{}, len(cols))
	valPtrs := make([]interface{}, len(cols))
	for i := range vals {
		valPtrs[i] = &vals[i]
	}

	for rows.Next() {
		if err := rows.Scan(valPtrs...); err != nil {
			return fmt.Errorf("scan: %w", err)
		}
		// Convert []byte to string for MySQL compatibility
		args := make([]interface{}, len(vals))
		for i, v := range vals {
			if b, ok := v.([]byte); ok {
				args[i] = string(b)
			} else {
				args[i] = v
			}
		}
		if _, err := stmt.Exec(args...); err != nil {
			fmt.Printf("[WARN] insert row in %s: %v\n", table, err)
			continue
		}
		inserted++
	}

	fmt.Printf("[OK] %s: %d/%d rows migrated\n", table, inserted, total)
	return nil
}
