package com.flightticket.scheduler;

import com.flightticket.service.BillingAggregatorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.YearMonth;

/**
 * Scheduler for automated monthly billing job execution.
 * 
 * This scheduler:
 * - Runs automatically based on configurable cron expression (default: 2 AM on 1st of each month)
 * - Processes the previous month's usage data
 * - Generates billing records for all clients with usage
 * - Logs execution for monitoring and debugging
 * - Can be enabled/disabled via configuration property
 * 
 * Configuration properties (in application.yml):
 * - billing.scheduler.cron: Cron expression for scheduling (default: "0 0 2 1 * ?")
 * - billing.scheduler.enabled: Enable/disable scheduler (default: true)
 * 
 * The default cron expression "0 0 2 1 * ?" means:
 * - Second: 0
 * - Minute: 0
 * - Hour: 2 (2 AM)
 * - Day of month: 1 (1st day)
 * - Month: * (every month)
 * - Day of week: ? (no specific day)
 * 
 * Requirements: 3.1 - Execute scheduled billing job at end of month
 */
@Component
@ConditionalOnProperty(
    prefix = "billing.scheduler",
    name = "enabled",
    havingValue = "true",
    matchIfMissing = true
)
public class BillingScheduler {
    
    private static final Logger logger = LoggerFactory.getLogger(BillingScheduler.class);
    
    private final BillingAggregatorService billingAggregatorService;
    
    @Value("${billing.scheduler.cron:0 0 2 1 * ?}")
    private String cronExpression;
    
    public BillingScheduler(BillingAggregatorService billingAggregatorService) {
        this.billingAggregatorService = billingAggregatorService;
    }
    
    /**
     * Scheduled method that runs monthly billing job.
     * 
     * Executes based on the configured cron expression to process the previous month's usage.
     * The method:
     * 1. Calculates the previous month (YearMonth)
     * 2. Logs the start of billing execution
     * 3. Calls the billing aggregator service to generate bills
     * 4. Logs completion or any errors
     * 
     * The cron expression is configurable via billing.scheduler.cron property.
     * The scheduler can be disabled via billing.scheduler.enabled=false property.
     * 
     * Requirements:
     * - 3.1: Execute scheduled billing job
     * - 3.2: Process each client separately (delegated to BillingAggregatorService)
     */
    @Scheduled(cron = "${billing.scheduler.cron:0 0 2 1 * ?}")
    public void runMonthlyBilling() {
        YearMonth lastMonth = YearMonth.now().minusMonths(1);
        
        logger.info("Starting monthly billing job for period: {} (cron: {})", lastMonth, cronExpression);
        
        try {
            billingAggregatorService.generateMonthlyBills(lastMonth);
            logger.info("Successfully completed monthly billing job for period: {}", lastMonth);
        } catch (Exception e) {
            logger.error("Error executing monthly billing job for period {}: {}", 
                lastMonth, e.getMessage(), e);
            // Don't rethrow - we want the scheduler to continue running for future months
        }
    }
}
