package com.saas.shared.core;

import com.saas.admin.entity.Tenant;
import com.saas.admin.repository.TenantRepository;
import com.saas.admin.service.TenantSchemaMigrationService;
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.stereotype.Component;

import java.util.List;

/**
 * Automatically updates ALL tenant database schemas on application startup.
 * 
 * This ensures that when you add/modify entity fields (e.g., add 'conversation' column),
 * Hibernate automatically updates ALL existing tenant databases, not just saas_db.
 * 
 * Execution Order:
 * 1. SchemaInitializer creates/updates saas_db (Order 1)
 * 2. Hibernate creates tables in saas_db via ddl-auto
 * 3. This runner updates ALL tenant schemas (Order 100)
 */
@Slf4j
@Component
@Order(100)
@RequiredArgsConstructor
public class TenantSchemaUpdateRunner implements ApplicationRunner {

    private final TenantRepository tenantRepository;
    private final TenantSchemaMigrationService migrationService;

    @Override
    public void run(ApplicationArguments args) {
        log.info("=".repeat(80));
        log.info("🚀 Starting automatic tenant schema updates...");
        log.info("=".repeat(80));
        
        try {
            // Temporarily set context to saas_db to query tenants
            TenantContext.setTenantId("saas_db");
            
            List<Tenant> tenants = tenantRepository.findAll();
            log.info("📊 Found {} tenant(s) to update", tenants.size());
            
            if (tenants.isEmpty()) {
                log.info("ℹ️ No tenants found. Skipping schema updates.");
                return;
            }
            
            int successCount = 0;
            int failCount = 0;
            
            for (Tenant tenant : tenants) {
                String schemaName = tenant.getSchemaName();
                
                try {
                    log.info("🔄 Updating schema for tenant: {} ({})", tenant.getTenantName(), schemaName);
                    
                    // This will:
                    // 1. Calculate current entity hash
                    // 2. Compare with stored hash in tenant's schema_version table
                    // 3. If different, run Hibernate UPDATE to add missing columns
                    migrationService.migrateIfNeeded(schemaName);
                    
                    successCount++;
                    log.info("✅ Schema updated successfully for: {}", schemaName);
                    
                } catch (Exception e) {
                    failCount++;
                    log.error("❌ Failed to update schema for tenant: {} ({})", 
                             tenant.getTenantName(), schemaName, e);
                    // Continue with other tenants even if one fails
                }
            }
            
            log.info("=".repeat(80));
            log.info("🎯 Tenant schema update completed!");
            log.info("   ✅ Success: {} tenant(s)", successCount);
            if (failCount > 0) {
                log.warn("   ❌ Failed: {} tenant(s)", failCount);
            }
            log.info("=".repeat(80));
            
        } catch (Exception e) {
            log.error("❌ CRITICAL: Tenant schema update runner failed", e);
            // Don't throw exception - let app start even if schema update fails
        } finally {
            TenantContext.clear();
        }
    }
}
