package com.petshop.backend.config;

import org.flywaydb.core.Flyway;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

import java.util.Arrays;

public class FlywayContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private static final int MAX_RETRIES = 15;
    private static final long RETRY_DELAY_MILLIS = 1000L;

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        String url = environment.getProperty("spring.datasource.url");
        String username = environment.getProperty("spring.datasource.username");
        String password = environment.getProperty("spring.datasource.password");

        if (url == null || username == null || password == null) {
            throw new IllegalStateException("Datasource properties are required before startup");
        }

        String[] locations = Arrays.stream(environment
                        .getProperty("spring.flyway.locations", "classpath:db/migration")
                        .split(","))
                .map(String::trim)
                .filter(location -> !location.isEmpty())
                .toArray(String[]::new);

        RuntimeException lastFailure = null;
        for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
            try {
                Flyway flyway = Flyway.configure()
                        .dataSource(url, username, password)
                        .locations(locations)
                        .validateOnMigrate(false)
                        .load();
                flyway.repair();
                flyway.migrate();
                return;
            } catch (RuntimeException ex) {
                lastFailure = ex;
                if (attempt == MAX_RETRIES) {
                    throw ex;
                }
                try {
                    Thread.sleep(RETRY_DELAY_MILLIS);
                } catch (InterruptedException interruptedException) {
                    Thread.currentThread().interrupt();
                    throw new IllegalStateException("Interrupted while waiting for database startup", interruptedException);
                }
            }
        }

        if (lastFailure != null) {
            throw lastFailure;
        }
    }
}
