import { useCallback } from 'react';
import { usePersSDK } from '../providers/PersSDKProvider';
import { useTransactionSigner } from './useTransactionSigner';
export const useRedemptions = () => {
    const { sdk, isInitialized, isAuthenticated } = usePersSDK();
    const { signAndSubmitTransactionWithJWT, isSignerAvailable, currentStatus, statusMessage } = useTransactionSigner();
    /**
     * Get redemption offers based on user permissions
     *
     * **Regular Users:** Automatically see only active redemptions available for purchase
     * **Administrators:** Can see all redemptions and filter by active/inactive status
     *
     * The backend enforces permission-based filtering automatically.
     *
     * @param options - Filter and pagination options
     * @param options.active - Filter by active status (Admin only)
     * @param options.search - Free text search across name, description, tags
     * @param options.startDate - Filter redemptions starting on or after this date
     * @param options.endDate - Filter redemptions ending on or before this date
     * @param options.include - Relations to include: 'redeemCount'
     * @param options.page - Page number (1-indexed)
     * @param options.limit - Results per page
     * @param options.sortBy - Field to sort by ('name' | 'createdAt')
     * @param options.sortOrder - Sort direction ('ASC' | 'DESC')
     *
     * @example Basic usage
     * ```typescript
     * const { data: offers } = await getRedemptions();
     * ```
     *
     * @example Filter by date range
     * ```typescript
     * const { data: dateFiltered } = await getRedemptions({
     *   startDate: '2026-05-01',
     *   endDate: '2026-06-30'
     * });
     * ```
     *
     * @example Get redemptions with redeem count
     * ```typescript
     * const { data: offers } = await getRedemptions({ include: ['redeemCount'] });
     * offers.forEach(o => console.log(`${o.name}: ${o.redeemCount} redeems`));
     * ```
     *
     * @example Search with pagination
     * ```typescript
     * const { data, pagination } = await getRedemptions({
     *   search: 'discount',
     *   page: 1,
     *   limit: 10,
     *   sortBy: 'name',
     *   sortOrder: 'ASC'
     * });
     * ```
     */
    const getRedemptions = useCallback(async (options) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.redemptions.getRedemptions(options);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch redemptions:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    /**
     * Get user's redemption history with optional filters, pagination and include relations
     *
     * @param filters - Optional filters (redemptionId, status)
     * @param options - Pagination options (page, limit, sortBy, sortOrder)
     * @param include - Relations to include: 'redemption', 'user', 'business', 'transactions'
     * @returns Promise resolving to paginated redemption history
     *
     * @example
     * ```typescript
     * // Get first page of user redemptions
     * const { data: redeems, pagination } = await getUserRedemptions({}, { page: 1, limit: 10 });
     * console.log(`Page ${pagination.page} of ${pagination.pages}`);
     *
     * // Get only completed redemptions
     * import { ProcessRecordStatus } from '@explorins/pers-shared';
     * const { data: completed } = await getUserRedemptions({ status: ProcessRecordStatus.COMPLETED });
     *
     * // Get user redemptions with full redemption details
     * const { data: redeems } = await getUserRedemptions({}, {}, ['redemption', 'business']);
     * redeems.forEach(redeem => {
     *   console.log('Redemption:', redeem.included?.redemption?.name);
     *   console.log('Business:', redeem.included?.business?.displayName);
     * });
     * ```
     */
    const getUserRedemptions = useCallback(async (filters, options, include) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        if (!isAuthenticated) {
            console.warn('SDK not authenticated. getUserRedemptions requires authentication.');
            return { data: [], pagination: { page: 1, limit: 0, total: 0, pages: 0, hasNext: false, hasPrev: false } };
        }
        try {
            const result = await sdk.redemptions.getUserRedemptions(filters, options, include);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch user redemptions:', error);
            throw error;
        }
    }, [sdk, isInitialized, isAuthenticated]);
    /**
     * Redeem a redemption offer with optional dynamic context
     *
     * Supports dynamic context for personalized NFT generation when the redemption
     * issues ERC721 tokens. Context can include validity dates, AI prompt placeholders,
     * and custom metadata.
     *
     * @param redemptionId - ID of the redemption to redeem
     * @param options - Optional settings
     * @param options.context - Dynamic context for NFT personalization (validity dates, AI prompts)
     * @param options.onStatusUpdate - Callback for transaction signing status updates
     * @returns Promise resolving to redemption result
     *
     * @example Basic redemption
     * ```typescript
     * const result = await redeem('redemption-123');
     * ```
     *
     * @example Redemption with dynamic context (personalized NFT)
     * ```typescript
     * const result = await redeem('event-ticket-123', {
     *   context: {
     *     // Validity - token valid for event duration
     *     validityDate: new Date().toISOString(),
     *     validityDuration: 8,  // 8 hours
     *
     *     // AI prompt context - available as {{context.xxx}} in prompts
     *     attendeeName: 'John Doe',
     *     ticketTier: 'VIP',
     *     seatSection: 'A12',
     *   }
     * });
     * ```
     *
     * @example Hotel stay NFT with check-in/check-out dates
     * ```typescript
     * const result = await redeem('hotel-nft-456', {
     *   context: {
     *     validityDate: '2026-04-15T14:00:00Z',      // Check-in
     *     validityEndDate: '2026-04-20T11:00:00Z',   // Check-out
     *     guestName: 'Jane Smith',
     *     roomNumber: '305',
     *     roomType: 'Suite',
     *   }
     * });
     * ```
     */
    const redeem = useCallback(async (redemptionId, options) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        if (!isAuthenticated) {
            throw new Error('SDK not authenticated. redeem requires authentication.');
        }
        try {
            const result = await sdk.redemptions.redeem(redemptionId, options?.context);
            const txToken = result.senderTransaction?.actionable?.authToken;
            if (txToken && isSignerAvailable) {
                try {
                    const signingResult = await signAndSubmitTransactionWithJWT(txToken, options?.onStatusUpdate);
                    if (signingResult.success) {
                        // Return enhanced result with signing information
                        return {
                            ...result,
                            transactionHash: signingResult.transactionHash,
                            // signature: signingResult.signature,
                            isSigned: true,
                            signedAt: new Date().toISOString()
                        };
                    }
                    else {
                        console.error('Transaction signing failed:', signingResult.error);
                        throw new Error(signingResult.error || 'Transaction signing failed');
                    }
                }
                catch (signingError) {
                    console.error('Blockchain signing error:', signingError);
                    throw new Error(`Transaction signing failed: ${signingError}`);
                }
            }
            else if (txToken && !isSignerAvailable) {
                console.warn('Transaction requires signature but signer is not available');
                throw new Error('Transaction requires signature but blockchain signer is not initialized');
            }
            // Return original result if no signing was required
            return result;
        }
        catch (error) {
            console.error('Failed to redeem redemption:', error);
            throw error;
        }
    }, [sdk, isInitialized, isAuthenticated, signAndSubmitTransactionWithJWT, isSignerAvailable]);
    // Admin methods
    /**
     * Admin: Get all redemption redeems with filters and include relations
     *
     * Retrieves all redemption redeems across the platform with filtering.
     *
     * @param filters - Optional filters for user, redemption, date range, and pagination
     * @param filters.userId - Filter by user ID
     * @param filters.redemptionId - Filter by redemption offer ID
     * @param filters.businessId - Filter by business ID (admin only)
     * @param filters.status - Filter by processing status (PENDING, PROCESSING, COMPLETED, FAILED)
     * @param filters.dateFrom - Filter redeems created on or after this date (ISO 8601 format)
     * @param filters.dateTo - Filter redeems created on or before this date (ISO 8601 format)
     * @param filters.page - Page number (1-indexed)
     * @param filters.limit - Items per page
     * @param filters.sortBy - Field to sort by
     * @param filters.sortOrder - Sort direction
     * @param include - Relations to include: 'redemption', 'user', 'business'
     * @returns Promise resolving to paginated redemption redeems
     *
     * @example
     * ```typescript
     * // Get all redeems with user details
     * const { data: redeems } = await getRedemptionRedeems({}, ['user', 'redemption']);
     *
     * // Filter by specific user
     * const { data: userRedeems } = await getRedemptionRedeems(
     *   { userId: 'user-123' },
     *   ['redemption']
     * );
     *
     * // Filter by date range
     * const { data } = await getRedemptionRedeems({
     *   dateFrom: '2026-01-01',
     *   dateTo: '2026-03-31'
     * }, ['user', 'redemption']);
     * ```
     */
    const getRedemptionRedeems = useCallback(async (filters, include) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.redemptions.getRedemptionRedeems(filters, include);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch redemption redeems:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    const createRedemption = useCallback(async (redemptionData) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.redemptions.createRedemption(redemptionData);
            return result;
        }
        catch (error) {
            console.error('Failed to create redemption offer:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    const getRedemptionTypes = useCallback(async () => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.redemptions.getRedemptionTypes();
            return result;
        }
        catch (error) {
            console.error('Failed to fetch redemption types:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    const updateRedemption = useCallback(async (redemptionId, redemptionData) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.redemptions.updateRedemption(redemptionId, redemptionData);
            return result;
        }
        catch (error) {
            console.error('Failed to update redemption:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    const toggleRedemptionStatus = useCallback(async (redemptionId) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.redemptions.toggleRedemptionStatus(redemptionId);
            return result;
        }
        catch (error) {
            console.error('Failed to toggle redemption status:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    return {
        getRedemptions,
        getUserRedemptions,
        redeem,
        getRedemptionTypes,
        getRedemptionRedeems,
        createRedemption,
        updateRedemption,
        toggleRedemptionStatus,
        isAvailable: isInitialized && !!sdk?.redemptions,
        // Expose signing status for UI feedback
        signingStatus: currentStatus,
        signingStatusMessage: statusMessage,
    };
};
