package com.flightticket.service;

import com.flightticket.dto.wallet.TransactionResult;
import com.flightticket.model.entity.RechargeRequest;
import com.flightticket.model.entity.Wallet;
import com.flightticket.model.entity.WalletTransaction;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;

public interface WalletService {
    
    /**
     * Get wallet by agency ID
     */
    Wallet getWalletByAgency(UUID agencyId);
    
    /**
     * Create a recharge request
     */
    RechargeRequest createRechargeRequest(UUID agencyId, BigDecimal amount, UUID requestedBy);
    
    /**
     * Approve a recharge request
     */
    void approveRecharge(UUID requestId, UUID approvedBy);
    
    /**
     * Reject a recharge request
     */
    void rejectRecharge(UUID requestId, UUID rejectedBy, String reason);
    
    /**
     * Reserve funds in wallet
     */
    TransactionResult reserveFunds(UUID agencyId, BigDecimal amount, String reference);
    
    /**
     * Debit wallet
     */
    TransactionResult debitWallet(UUID agencyId, BigDecimal amount, String reference, UUID createdBy);
    
    /**
     * Credit wallet
     */
    TransactionResult creditWallet(UUID agencyId, BigDecimal amount, String reference, UUID createdBy);
    
    /**
     * Release reserved funds
     */
    void releaseFunds(UUID reservationId);
    
    /**
     * Get transaction history
     */
    List<WalletTransaction> getTransactionHistory(UUID agencyId, LocalDate from, LocalDate to);
    
    /**
     * Record modification charge (deduct modification fee)
     * Requirements: 4.1, 6.5, 6.7
     * 
     * @param agencyId Agency ID
     * @param amount Modification fee amount
     * @param modificationId Modification record ID
     * @param bookingId Booking ID
     * @param createdBy User who initiated the modification
     * @return Transaction result
     * @throws InsufficientBalanceException if wallet balance is insufficient
     */
    TransactionResult recordModificationCharge(
        UUID agencyId, 
        BigDecimal amount, 
        String modificationId, 
        UUID bookingId, 
        UUID createdBy
    );
    
    /**
     * Record modification refund (refund fare difference when fare decreases)
     * Requirements: 4.2, 6.5, 6.6
     * 
     * @param agencyId Agency ID
     * @param amount Refund amount (fare difference)
     * @param modificationId Modification record ID
     * @param bookingId Booking ID
     * @param createdBy User who initiated the modification
     * @return Transaction result
     */
    TransactionResult recordModificationRefund(
        UUID agencyId, 
        BigDecimal amount, 
        String modificationId, 
        UUID bookingId, 
        UUID createdBy
    );
    
    /**
     * Record modification credit (credit fare difference when fare decreases exceeds fee)
     * Requirements: 4.2, 6.5, 6.6
     * 
     * @param agencyId Agency ID
     * @param amount Credit amount (fare difference minus modification fee)
     * @param modificationId Modification record ID
     * @param bookingId Booking ID
     * @param createdBy User who initiated the modification
     * @return Transaction result
     */
    TransactionResult recordModificationCredit(
        UUID agencyId, 
        BigDecimal amount, 
        String modificationId, 
        UUID bookingId, 
        UUID createdBy
    );
    
    /**
     * Check if wallet has sufficient balance for modification
     * Requirements: 4.3, 6.3
     * 
     * @param agencyId Agency ID
     * @param amount Required amount
     * @return true if balance is sufficient, false otherwise
     */
    boolean hasSufficientBalance(UUID agencyId, BigDecimal amount);
    
    /**
     * Rollback modification transaction (reverse wallet transaction for failed modifications)
     * Requirements: 7.4
     * 
     * @param transactionId Transaction ID to rollback
     */
    void rollbackModificationTransaction(UUID transactionId);
}
