package at.procon.ted.startup;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

/**
 * Startup runner that fixes the organization table schema if needed.
 * This is a workaround for Flyway V2 migration not being applied automatically.
 *
 * Extends VARCHAR fields to handle long TED data.
 *
 * @author Martin.Schweitzer@procon.co.at and claude.ai
 */
@Component
@Order(1) // Run before other startup runners
@RequiredArgsConstructor
@Slf4j
public class OrganizationSchemaFixRunner implements ApplicationRunner {

    private final JdbcTemplate jdbcTemplate;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("Checking organization table schema...");

        try {
            // Check if schema fix is needed by trying to query column types
            String checkSql = """
                SELECT column_name, character_maximum_length, data_type
                FROM information_schema.columns
                WHERE table_schema = 'ted'
                AND table_name = 'organization'
                AND column_name IN ('postal_code', 'company_id', 'name')
                ORDER BY column_name
                """;

            var columnInfo = jdbcTemplate.queryForList(checkSql);
            boolean needsFix = false;

            for (var row : columnInfo) {
                String columnName = (String) row.get("column_name");
                Integer maxLength = (Integer) row.get("character_maximum_length");
                String dataType = (String) row.get("data_type");

                log.debug("Column {}: type={}, max_length={}", columnName, dataType, maxLength);

                // Check if any field is still too small
                if ("postal_code".equals(columnName) && maxLength != null && maxLength < 255) {
                    needsFix = true;
                    log.warn("Column postal_code is too small: {} chars, needs 255", maxLength);
                }
                if ("company_id".equals(columnName) && maxLength != null && maxLength < 255) {
                    needsFix = true;
                    log.warn("Column company_id is too small: {} chars, needs 255", maxLength);
                }
            }

            if (needsFix) {
                log.warn("Organization table schema needs fixing - applying migration...");
                applySchemaFix();
                log.info("Organization table schema fixed successfully!");
            } else {
                log.info("Organization table schema is up to date");
            }

        } catch (Exception e) {
            log.error("Failed to check/fix organization table schema: {}", e.getMessage(), e);
            throw e;
        }
    }

    private void applySchemaFix() {
        log.info("Applying schema fix to ted.organization table...");

        // Apply all column type changes
        // Use TEXT for fields that can be extremely long
        String[] alterStatements = {
            "ALTER TABLE ted.organization ALTER COLUMN postal_code TYPE TEXT",
            "ALTER TABLE ted.organization ALTER COLUMN street_name TYPE TEXT",
            "ALTER TABLE ted.organization ALTER COLUMN city TYPE TEXT",  // Some cities have very long names
            "ALTER TABLE ted.organization ALTER COLUMN phone TYPE VARCHAR(100)",
            "ALTER TABLE ted.organization ALTER COLUMN org_reference TYPE VARCHAR(100)",
            "ALTER TABLE ted.organization ALTER COLUMN role TYPE VARCHAR(100)",
            "ALTER TABLE ted.organization ALTER COLUMN company_id TYPE TEXT",  // Can be very long
            "ALTER TABLE ted.organization ALTER COLUMN name TYPE TEXT"
        };

        for (String sql : alterStatements) {
            try {
                jdbcTemplate.execute(sql);
                log.debug("Executed: {}", sql);
            } catch (Exception e) {
                log.warn("Failed to execute {}: {} (may already be applied)", sql, e.getMessage());
            }
        }

        log.info("Schema fix applied successfully");
    }
}
