package com.flightticket.service;

import com.flightticket.client.amadeus.AmadeusFlightSearchRequest;
import com.flightticket.client.amadeus.AmadeusFlightSearchResponse;
import com.flightticket.client.amadeus.AmadeusModificationRequest;
import com.flightticket.dto.modification.EligibilityResult;
import com.flightticket.dto.modification.ModificationCost;
import com.flightticket.exception.AmadeusServiceException;
import com.flightticket.exception.InsufficientBalanceException;
import com.flightticket.exception.ModificationNotAllowedException;
import com.flightticket.model.entity.Booking;
import com.flightticket.model.entity.ModificationRecord;

import java.math.BigDecimal;
import java.util.UUID;

/**
 * Service for orchestrating booking modifications.
 * 
 * This service coordinates the modification workflow:
 * 1. Eligibility validation
 * 2. Cost calculation
 * 3. Wallet balance verification
 * 4. API submission to Amadeus
 * 5. Wallet transaction processing
 * 6. Audit logging
 * 
 * All modification operations are transactional with proper rollback support.
 * 
 * Requirements: 1.1, 3.1, 4.1, 5.1, 6.3, 7.4
 */
public interface ModificationService {
    
    /**
     * Check if a booking is eligible for modification.
     * 
     * This method delegates to EligibilityService to perform comprehensive checks:
     * - Booking status validation (must be CONFIRMED)
     * - Departure time validation (not departed, not within 24 hours)
     * - Fare rules validation (fare class allows modifications)
     * 
     * @param bookingId The booking ID to check
     * @return Complete eligibility result with allowed modifications and restrictions
     * @throws IllegalArgumentException if booking ID is null or booking not found
     * 
     * Requirements: 1.1
     * Property 1: Eligibility Determination Consistency
     * Property 2: Eligibility Response Completeness
     * Property 3: Non-Modifiable Booking Handling
     */
    EligibilityResult checkEligibility(UUID bookingId);
    
    /**
     * Search for alternative flights for modification purposes.
     * 
     * This method delegates to AmadeusModificationAdapter to search for alternative
     * flight options based on the provided search criteria.
     * 
     * @param searchRequest Flight search criteria (origin, destination, date, etc.)
     * @return Alternative flight options with pricing
     * @throws AmadeusServiceException if the search fails
     * 
     * Requirements: 3.1, 4.1
     */
    AmadeusFlightSearchResponse searchAlternatives(AmadeusFlightSearchRequest searchRequest);
    
    /**
     * Calculate the cost of a modification.
     * 
     * This method delegates to CostCalculationService to calculate:
     * - Modification fee (from fare rules)
     * - Fare difference (new fare - original fare)
     * - Total cost (fee + fare difference)
     * - Wallet impact (DEBIT or CREDIT, new balance)
     * 
     * @param bookingId The booking being modified
     * @param newFare The new flight fare
     * @param modificationType The type of modification
     * @return Complete modification cost details including wallet impact
     * @throws IllegalArgumentException if parameters are invalid or booking not found
     * 
     * Requirements: 6.3
     * Property 9: Modification Cost Calculation
     * Property 10: Credit Calculation for Fare Decreases
     * Property 11: Fare Difference Calculation
     */
    ModificationCost calculateCost(
        UUID bookingId,
        BigDecimal newFare,
        String modificationType
    );
    
    /**
     * Execute a booking modification.
     * 
     * This method orchestrates the complete modification workflow:
     * 1. Validate eligibility (delegate to EligibilityService)
     * 2. Calculate cost (delegate to CostCalculationService)
     * 3. Check wallet balance (delegate to WalletService)
     * 4. Submit to Amadeus API (delegate to ModificationExecutionService)
     * 5. Process wallet transaction (delegate to WalletService)
     * 6. Create modification record (delegate to ModificationExecutionService)
     * 7. Log success (delegate to AuditLogService)
     * 
     * The entire operation is transactional. If any step fails:
     * - Wallet transactions are rolled back
     * - Booking state is preserved
     * - Failure is logged
     * 
     * @param bookingId The booking to modify
     * @param modificationRequest The modification details in Amadeus format
     * @param newFare The new flight fare (for cost calculation)
     * @param modificationType The type of modification
     * @param agentId The agent performing the modification
     * @return The created modification record
     * @throws InsufficientBalanceException if wallet balance is insufficient for debit
     * @throws ModificationNotAllowedException if booking is not eligible for modification
     * @throws AmadeusServiceException if the Amadeus API call fails
     * 
     * Requirements: 1.1, 5.1, 6.3, 7.4
     * Property 12: Wallet Balance Validation Before Processing
     * Property 13: Insufficient Balance Handling
     * Property 14: Transaction Record Creation
     * Property 17: API Rejection Preserves Original State
     * Property 20: Local State Synchronization
     * Property 21: Transaction Rollback on API Failure
     * Property 22: Modification Attempt Logging
     * Property 23: State Change Recording
     */
    ModificationRecord executeModification(
        UUID bookingId,
        AmadeusModificationRequest modificationRequest,
        BigDecimal newFare,
        String modificationType,
        UUID agentId
    ) throws InsufficientBalanceException, ModificationNotAllowedException, AmadeusServiceException;
    
    /**
     * Rollback a failed modification.
     * 
     * This method handles cleanup after a modification failure:
     * 1. Rollback wallet transaction (if any)
     * 2. Update modification record status to ROLLED_BACK
     * 3. Log the rollback
     * 
     * @param modificationId The modification record ID to rollback
     * 
     * Requirements: 7.4
     * Property 21: Transaction Rollback on API Failure
     */
    void rollbackModification(String modificationId);
}
