package com.storycove.config;

import com.storycove.service.LibraryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
import java.util.List;

/**
 * Runs database migrations on application startup.
 * This ensures all library databases have the required schema,
 * particularly for tables like backup_jobs that were added after initial deployment.
 */
@Component
@Order(1) // Run early in startup sequence
public class DatabaseMigrationRunner implements CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseMigrationRunner.class);

    @Autowired
    private DataSource dataSource;

    @Autowired
    private LibraryService libraryService;

    @Value("${spring.datasource.username}")
    private String dbUsername;

    @Value("${spring.datasource.password}")
    private String dbPassword;

    // SQL for last_completed_at column migration (idempotent)
    private static final String LAST_COMPLETED_AT_MIGRATION =
        "ALTER TABLE stories ADD COLUMN IF NOT EXISTS last_completed_at TIMESTAMP;";

    // SQL for backup_jobs table migration (idempotent)
    private static final String BACKUP_JOBS_MIGRATION = """
        CREATE TABLE IF NOT EXISTS backup_jobs (
            id UUID PRIMARY KEY,
            library_id VARCHAR(255) NOT NULL,
            type VARCHAR(50) NOT NULL,
            status VARCHAR(50) NOT NULL,
            file_path VARCHAR(1000),
            file_size_bytes BIGINT,
            progress_percent INTEGER,
            error_message VARCHAR(1000),
            created_at TIMESTAMP NOT NULL,
            started_at TIMESTAMP,
            completed_at TIMESTAMP
        );

        CREATE INDEX IF NOT EXISTS idx_backup_jobs_library_id ON backup_jobs(library_id);
        CREATE INDEX IF NOT EXISTS idx_backup_jobs_status ON backup_jobs(status);
        CREATE INDEX IF NOT EXISTS idx_backup_jobs_created_at ON backup_jobs(created_at DESC);
        """;

    // Remove the expires_at column and its index if they exist from the old schema
    private static final String BACKUP_JOBS_CLEANUP_MIGRATION = """
        ALTER TABLE backup_jobs DROP COLUMN IF EXISTS expires_at;
        DROP INDEX IF EXISTS idx_backup_jobs_expires_at;
        UPDATE backup_jobs SET status = 'COMPLETED' WHERE status = 'EXPIRED';
        """;

    @Override
    public void run(String... args) throws Exception {
        logger.info("🗄️  Starting database migrations...");

        List<String> databases = libraryService.getAllLibraries().stream()
                .map(lib -> libraryService.getDbNameForLibrary(lib.getId()))
                .filter(db -> db != null && !db.isBlank())
                .collect(java.util.stream.Collectors.toList());

        for (String database : databases) {
            try {
                applyMigrations(database);
                logger.info("✅ Successfully applied migrations to database: {}", database);
            } catch (Exception e) {
                // Log error but don't fail startup if database doesn't exist yet
                if (e.getMessage() != null && e.getMessage().contains("does not exist")) {
                    logger.warn("⚠️  Database {} does not exist yet, skipping migrations", database);
                } else {
                    logger.error("❌ Failed to apply migrations to database: {}", database, e);
                    // Don't throw - allow application to start even if some migrations fail
                }
            }
        }

        logger.info("✅ Database migrations completed");
    }

    private void applyMigrations(String database) throws Exception {
        // We need to connect directly to each database, not through SmartRoutingDataSource
        // Build connection URL from the default datasource URL
        String originalUrl = dataSource.getConnection().getMetaData().getURL();
        String baseUrl = originalUrl.substring(0, originalUrl.lastIndexOf('/'));
        String targetUrl = baseUrl + "/" + database;

        // Connect directly to target database using credentials from application properties
        try (Connection conn = java.sql.DriverManager.getConnection(
                targetUrl,
                dbUsername,
                dbPassword
        )) {
            // Apply last_completed_at column migration
            try (Statement stmt = conn.createStatement()) {
                stmt.execute(LAST_COMPLETED_AT_MIGRATION);
            }

            // Apply backup_jobs migration
            try (Statement stmt = conn.createStatement()) {
                stmt.execute(BACKUP_JOBS_MIGRATION);
            }

            // Remove expires_at column and update EXPIRED status from old schema
            try (Statement stmt = conn.createStatement()) {
                stmt.execute(BACKUP_JOBS_CLEANUP_MIGRATION);
            }

            logger.debug("Applied migrations to {}", database);
        }
    }
}
