package db

import (
	"database/sql"
	"fmt"
	"log"
	"os"
	"regexp"
	"rmser/internal/domain/catalog"
	"rmser/internal/domain/invoices"
	"rmser/internal/domain/ocr"
	"rmser/internal/domain/operations"
	"rmser/internal/domain/recipes"
	"rmser/internal/domain/recommendations"
	"time"

	_ "github.com/jackc/pgx/v5/stdlib"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

func NewPostgresDB(dsn string) *gorm.DB {
	// 1. Проверка и создание БД перед основным подключением
	ensureDBExists(dsn)

	// 2. Настройка логгера GORM
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags),
		logger.Config{
			SlowThreshold:             time.Second,
			LogLevel:                  logger.Warn,
			IgnoreRecordNotFoundError: true,
			Colorful:                  true,
		},
	)

	// 3. Основное подключение
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(fmt.Sprintf("не удалось подключиться к БД: %v", err))
	}

	// 4. Автомиграция
	err = db.AutoMigrate(
		&catalog.Product{},
		&recipes.Recipe{},
		&recipes.RecipeItem{},
		&invoices.Invoice{},
		&invoices.InvoiceItem{},
		&operations.StoreOperation{},
		&recommendations.Recommendation{},
		&ocr.ProductMatch{},
	)
	if err != nil {
		panic(fmt.Sprintf("ошибка миграции БД: %v", err))
	}

	return db
}

// ensureDBExists подключается к системной БД 'postgres' и создает целевую, если её нет
func ensureDBExists(fullDSN string) {
	// Регулярка для извлечения имени базы из DSN (ищем dbname=... )
	re := regexp.MustCompile(`dbname=([^\s]+)`)
	matches := re.FindStringSubmatch(fullDSN)

	if len(matches) < 2 {
		// Если не нашли dbname, возможно формат URL (postgres://...),
		// пропускаем авто-создание, полагаемся на ошибку драйвера
		return
	}

	targetDB := matches[1]

	// Заменяем целевую БД на системную 'postgres' для подключения
	maintenanceDSN := re.ReplaceAllString(fullDSN, "dbname=postgres")

	// Используем стандартный sql драйвер через pgx (который под капотом у gorm/postgres)
	// Важно: нам не нужен GORM здесь, нужен чистый SQL для CREATE DATABASE
	db, err := sql.Open("pgx", maintenanceDSN)
	if err != nil {
		// Если не вышло подключиться к postgres, просто выходим,
		// основная ошибка вылетит при попытке gorm.Open
		log.Printf("[WARN] Не удалось подключиться к системной БД для проверки: %v", err)
		return
	}
	defer db.Close()

	// Проверяем существование базы
	var exists bool
	checkSQL := fmt.Sprintf("SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = '%s')", targetDB)
	err = db.QueryRow(checkSQL).Scan(&exists)
	if err != nil {
		log.Printf("[WARN] Ошибка проверки существования БД: %v", err)
		return
	}

	if !exists {
		log.Printf("[INFO] База данных '%s' не найдена. Создаю...", targetDB)
		// CREATE DATABASE не может быть выполнен в транзакции, поэтому Exec
		_, err = db.Exec(fmt.Sprintf("CREATE DATABASE \"%s\"", targetDB))
		if err != nil {
			panic(fmt.Sprintf("не удалось создать базу данных %s: %v", targetDB, err))
		}
		log.Printf("[INFO] База данных '%s' успешно создана", targetDB)
	}
}
