package postgres

import (
	"database/sql"
	"fmt"

	"counter/internal/infrastructure/config"
	"counter/internal/infrastructure/logging"

	_ "github.com/lib/pq"
)

// Connection manages the database connection
type Connection struct {
	db *sql.DB
}

// NewConnection creates a new database connection
func NewConnection(cfg *config.Config, logger logging.Logger) (*Connection, error) {
	db, err := sql.Open("postgres", cfg.DatabaseURL)
	if err != nil {
		return nil, fmt.Errorf("failed to open database: %w", err)
	}

	// Test the connection
	if err = db.Ping(); err != nil {
		return nil, fmt.Errorf("failed to ping database: %w", err)
	}

	logger.Info("✅ Database connection established successfully")

	conn := &Connection{db: db}

	// Create tables
	if err := conn.CreateTables(); err != nil {
		return nil, fmt.Errorf("failed to create tables: %w", err)
	}

	return conn, nil
}

// GetDB returns the database connection
func (c *Connection) GetDB() *sql.DB {
	return c.db
}

// Close closes the database connection
func (c *Connection) Close() error {
	return c.db.Close()
}

// CreateTables creates the necessary database tables
func (c *Connection) CreateTables() error {
	queries := []string{
		`CREATE TABLE IF NOT EXISTS users (
			id SERIAL PRIMARY KEY,
			username VARCHAR(50) UNIQUE NOT NULL,
			email VARCHAR(255) UNIQUE NOT NULL,
			password VARCHAR(255) NOT NULL,
			created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
			updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
		)`,
		`CREATE TABLE IF NOT EXISTS counters (
			id SERIAL PRIMARY KEY,
			user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
			name VARCHAR(100) NOT NULL,
			description TEXT,
			created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
			updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
		)`,
		`CREATE TABLE IF NOT EXISTS counter_entries (
			id SERIAL PRIMARY KEY,
			counter_id INTEGER REFERENCES counters(id) ON DELETE CASCADE,
			value INTEGER NOT NULL,
			date DATE NOT NULL,
			created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
		)`,
		`CREATE INDEX IF NOT EXISTS idx_counters_user_id ON counters(user_id)`,
		`CREATE INDEX IF NOT EXISTS idx_counter_entries_counter_id ON counter_entries(counter_id)`,
		`CREATE INDEX IF NOT EXISTS idx_counter_entries_date ON counter_entries(date)`,
	}

	for _, query := range queries {
		if _, err := c.db.Exec(query); err != nil {
			return fmt.Errorf("failed to execute query: %w", err)
		}
	}

	return nil
}
