import { useCallback } from 'react';
import { usePersSDK } from '../providers/PersSDKProvider';
export const useCampaigns = () => {
    const { sdk, isInitialized, isAuthenticated } = usePersSDK();
    /**
     * Get active campaigns with optional filters and include relations
     *
     * @param options - Filter, pagination, and include options
     * @returns Promise resolving to paginated active campaigns
     *
     * @example
     * ```typescript
     * // Simple: get active campaigns with trigger sources
     * const { data: campaigns } = await getActiveCampaigns({ include: ['triggerSources'] });
     *
     * // With pagination
     * const { data, pagination } = await getActiveCampaigns({
     *   page: 1,
     *   limit: 10,
     *   include: ['triggerSources', 'businesses']
     * });
     *
     * // Filter by date range
     * const { data } = await getActiveCampaigns({
     *   startDate: '2026-05-01',
     *   endDate: '2026-12-31'
     * });
     *
     * // Get campaigns with claim count
     * const { data } = await getActiveCampaigns({ include: ['claimCount'] });
     * data.forEach(c => console.log(`${c.name}: ${c.claimCount} claims`));
     * ```
     */
    const getActiveCampaigns = useCallback(async (options) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaigns({
                active: true,
                ...options
            });
            return result;
        }
        catch (error) {
            console.error('Failed to fetch active campaigns:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    /**
     * Get campaign by ID with optional include relations
     *
     * @param campaignId - The campaign ID
     * @param include - Relations to include: 'triggerSources', 'businesses', 'claimCount'
     * @returns Promise resolving to campaign data
     *
     * @example
     * ```typescript
     * // Get campaign with all related data
     * const campaign = await getCampaignById('campaign-123', ['triggerSources', 'businesses']);
     * console.log('Trigger sources:', campaign.included?.triggerSources);
     *
     * // Get campaign with claim count
     * const campaign = await getCampaignById('campaign-123', ['claimCount']);
     * console.log('Total claims:', campaign.claimCount);
     * ```
     */
    const getCampaignById = useCallback(async (campaignId, include) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaignById(campaignId, include);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch campaign:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    /**
     * Claim a campaign reward with optional dynamic context
     *
     * Triggers a campaign claim for the authenticated user. The campaign must be active
     * and the user must meet all eligibility requirements. Supports dynamic context for
     * personalized NFT generation when the campaign issues ERC721 tokens.
     *
     * @param request - Campaign claim request with optional context
     * @param request.campaignId - ID of the campaign to claim (optional if using triggerSourceId)
     * @param request.triggerSourceId - ID of trigger source (QR, NFC, etc.)
     * @param request.context - Dynamic context for NFT personalization
     * @param request.metadata - Additional metadata for the claim
     * @param request.latitude - User's latitude for geo-validated claims
     * @param request.longitude - User's longitude for geo-validated claims
     * @returns Promise resolving to campaign claim result
     *
     * @example Basic campaign claim
     * ```typescript
     * const claim = await claimCampaign({
     *   triggerSourceId: 'qr-code-123',
     * });
     * ```
     *
     * @example Campaign claim with dynamic context (personalized NFT)
     * ```typescript
     * import { DynamicContext } from '@explorins/pers-sdk-react-native';
     *
     * const context: DynamicContext = {
     *   // Validity - token valid for 30 days
     *   validityDate: new Date().toISOString(),
     *   validityDuration: 30,
     *
     *   // AI prompt context - available as {{context.xxx}} in prompts
     *   visitorName: 'John Doe',
     *   visitLocation: 'Grand Hotel Lobby',
     *   membershipTier: 'Gold',
     * };
     *
     * const claim = await claimCampaign({
     *   triggerSourceId: 'hotel-checkin-qr',
     *   context,
     * });
     * ```
     *
     * @example Geo-validated claim with context
     * ```typescript
     * const claim = await claimCampaign({
     *   triggerSourceId: 'museum-entrance-nfc',
     *   latitude: 48.8606,
     *   longitude: 2.3376,
     *   context: {
     *     visitorType: 'Adult',
     *     ticketCategory: 'General Admission',
     *   }
     * });
     * ```
     */
    const claimCampaign = useCallback(async (request) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        if (!isAuthenticated) {
            throw new Error('SDK not authenticated. claimCampaign requires authentication.');
        }
        try {
            const result = await sdk.campaigns.claimCampaign(request);
            return result;
        }
        catch (error) {
            console.error('Failed to claim campaign:', error);
            throw error;
        }
    }, [sdk, isInitialized, isAuthenticated]);
    /**
     * Get user's campaign claims with optional pagination and include relations
     *
     * @param options - Optional options including pagination and include relations
     * @returns Promise resolving to paginated campaign claims
     *
     * @example
     * ```typescript
     * // Get user's claims with campaign details
     * const { data: claims } = await getUserClaims({ include: ['campaign', 'business'] });
     * claims.forEach(claim => {
     *   console.log('Campaign:', claim.included?.campaign?.name);
     * });
     *
     * // With pagination
     * const { data } = await getUserClaims({ page: 1, limit: 10, include: ['campaign'] });
     * ```
     */
    const getUserClaims = useCallback(async (options) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        if (!isAuthenticated) {
            console.warn('SDK not authenticated. getUserClaims requires authentication.');
            return { data: [], pagination: { page: 1, limit: 0, total: 0, pages: 0, hasNext: false, hasPrev: false } };
        }
        try {
            const result = await sdk.campaigns.getUserClaims(options);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch user claims:', error);
            throw error;
        }
    }, [sdk, isInitialized, isAuthenticated]);
    const getCampaignTriggers = useCallback(async () => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaignTriggers();
            return result;
        }
        catch (error) {
            console.error('Failed to fetch campaign triggers:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    // Admin methods
    /**
     * Admin: Get all campaigns with optional filters and include relations
     *
     * @param options - Filter, pagination, and include options (same as getActiveCampaigns but active is optional)
     * @returns Promise resolving to paginated campaigns
     *
     * @example
     * ```typescript
     * // Get all campaigns
     * const { data } = await getAllCampaigns();
     *
     * // Get only active campaigns with trigger sources
     * const { data } = await getAllCampaigns({ active: true, include: ['triggerSources'] });
     *
     * // Filter by date range with claim count
     * const { data } = await getAllCampaigns({
     *   startDate: '2026-05-01',
     *   endDate: '2026-12-31',
     *   include: ['claimCount']
     * });
     * data.forEach(c => console.log(`${c.name}: ${c.claimCount} claims`));
     *
     * // With pagination and sorting
     * const { data } = await getAllCampaigns({
     *   page: 1,
     *   limit: 20,
     *   sortBy: 'createdAt',
     *   sortOrder: 'DESC'
     * });
     * ```
     */
    const getAllCampaigns = useCallback(async (options) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaigns(options);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch all campaigns:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    /**
     * Admin: Get campaign claims with optional filters and include relations
     *
     * @param filters - Optional filters for campaign, user, business, and date range
     * @param filters.campaignId - Filter by specific campaign ID
     * @param filters.userId - Filter by user ID
     * @param filters.businessId - Filter by business ID
     * @param filters.dateFrom - Filter claims created on or after this date (ISO 8601 format)
     * @param filters.dateTo - Filter claims 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: 'campaign', 'user', 'business'
     * @returns Promise resolving to paginated campaign claims
     *
     * @example
     * ```typescript
     * // Get all claims with user details
     * const { data: claims } = await getCampaignClaims({}, ['user']);
     *
     * // Get claims for a specific campaign
     * const { data } = await getCampaignClaims({ campaignId: 'campaign-123' }, ['user', 'business']);
     *
     * // Filter by date range
     * const { data } = await getCampaignClaims({
     *   dateFrom: '2026-01-01',
     *   dateTo: '2026-03-31'
     * }, ['campaign']);
     * ```
     */
    const getCampaignClaims = useCallback(async (filters, include) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaignClaims(filters, include);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch campaign claims:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    /**
     * Admin: Get campaign claims by user ID with optional include relations
     *
     * @param userId - The user ID
     * @param include - Relations to include: 'campaign', 'user', 'business'
     * @returns Promise resolving to paginated campaign claims
     */
    const getCampaignClaimsByUserId = useCallback(async (userId, include) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaignClaimsByUserId(userId, undefined, include);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch campaign claims by user ID:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    /**
     * Admin: Get campaign claims by business ID with optional include relations
     *
     * @param businessId - The business ID
     * @param include - Relations to include: 'campaign', 'user', 'business'
     * @returns Promise resolving to paginated campaign claims
     */
    const getCampaignClaimsByBusinessId = useCallback(async (businessId, include) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        try {
            const result = await sdk.campaigns.getCampaignClaimsByBusinessId(businessId, undefined, include);
            return result;
        }
        catch (error) {
            console.error('Failed to fetch campaign claims by business ID:', error);
            throw error;
        }
    }, [sdk, isInitialized]);
    // ==========================================
    // TRIGGER SOURCE ASSIGNMENT (Admin)
    // Note: TriggerSource CRUD is in useTriggerSources hook
    // ==========================================
    /**
     * Admin: Assign a trigger source to a campaign
     *
     * Associates a trigger source (QR code, NFC tag, etc.) with a campaign.
     * A campaign can have multiple trigger sources.
     *
     * Note: To create/update/delete trigger sources, use `useTriggerSources` hook.
     *
     * @param campaignId - Campaign UUID
     * @param triggerSourceId - Trigger source UUID
     * @returns Promise resolving to updated campaign
     *
     * @example
     * ```typescript
     * const { create } = useTriggerSources();
     * const { assignTriggerSource } = useCampaigns();
     *
     * // Create trigger source first
     * const source = await create({ type: 'QR_CODE', name: 'Store QR' });
     *
     * // Then assign to campaign
     * const updated = await assignTriggerSource('campaign-123', source.id);
     * ```
     */
    const assignTriggerSource = useCallback(async (campaignId, triggerSourceId) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        if (!isAuthenticated) {
            throw new Error('SDK not authenticated. assignTriggerSource requires admin authentication.');
        }
        try {
            const result = await sdk.campaigns.assignTriggerSource(campaignId, triggerSourceId);
            return result;
        }
        catch (error) {
            console.error('Failed to assign trigger source:', error);
            throw error;
        }
    }, [sdk, isInitialized, isAuthenticated]);
    /**
     * Admin: Remove a trigger source from a campaign
     *
     * Removes the association between a trigger source and a campaign.
     * The trigger source itself is not deleted.
     *
     * @param campaignId - Campaign UUID
     * @param triggerSourceId - Trigger source UUID
     * @returns Promise resolving to updated campaign
     */
    const removeTriggerSource = useCallback(async (campaignId, triggerSourceId) => {
        if (!isInitialized || !sdk) {
            throw new Error('SDK not initialized. Call initialize() first.');
        }
        if (!isAuthenticated) {
            throw new Error('SDK not authenticated. removeTriggerSource requires admin authentication.');
        }
        try {
            const result = await sdk.campaigns.removeTriggerSource(campaignId, triggerSourceId);
            return result;
        }
        catch (error) {
            console.error('Failed to remove trigger source:', error);
            throw error;
        }
    }, [sdk, isInitialized, isAuthenticated]);
    return {
        getActiveCampaigns,
        getCampaignById,
        claimCampaign,
        getUserClaims,
        getCampaignTriggers,
        getAllCampaigns,
        getCampaignClaims,
        getCampaignClaimsByUserId,
        getCampaignClaimsByBusinessId,
        assignTriggerSource,
        removeTriggerSource,
        isAvailable: isInitialized && !!sdk?.campaigns,
    };
};
