import { useState, useEffect, useCallback } from 'react';
import { useMutation, useQuery } from '@apollo/client/react';
import * as dataSync from '../api/dataSync';
import { PROFILE_PING_MUTATION } from '../api/operations/mutations';
import { ACCOUNT_STATUS_QUERY, PROFILE_QUERY } from '../api/operations/queries';
import { apolloClient } from '../api/client';

// Base sent ping type (from storage)
export type SentPing = {
  targetProfileId: string;
  targetName?: string;
  message?: string;
  sentAt: number;
  status: 'SENT' | 'MATCHED' | 'EXPIRED';
};

// Profile data fetched from API
export type ProfileData = {
  id: string;
  imaginaryName?: string;
  age?: number;
  gender?: string;
  sexuality?: string;
  bio?: string;
  desires?: string[];
  connectionGoals?: string[];
  verificationStatus?: string;
  isMajestic?: boolean;
  distance?: { km: number; mi: number };
  photos?: Array<{
    id: string;
    pictureUrls?: { small?: string; medium?: string; large?: string };
  }>;
  interactionStatus?: {
    mine?: string;
    theirs?: string;
    message?: string;
  };
};

// Enriched ping with profile data
export interface EnrichedSentPing extends SentPing {
  profile?: ProfileData;
  profileLoading?: boolean;
  profileError?: string;
}

export function useSentPings() {
  const [sentPings, setSentPings] = useState<SentPing[]>([]);
  const [enrichedPings, setEnrichedPings] = useState<EnrichedSentPing[]>([]);
  const [loading, setLoading] = useState(true);
  const [profilesLoading, setProfilesLoading] = useState(false);

  // Query for available pings count
  const { data: accountData, refetch: refetchAccount } = useQuery(ACCOUNT_STATUS_QUERY, {
    fetchPolicy: 'cache-and-network',
  });

  // Always report 2 pings available — bypass Feeld's client-side limit
  const availablePings = Math.max(accountData?.account?.availablePings ?? 2, 2);

  // ProfilePing mutation
  const [profilePingMutation, { loading: sendingPing }] = useMutation(PROFILE_PING_MUTATION);

  // Fetch profile data for a single ping
  const fetchProfileForPing = useCallback(async (ping: SentPing): Promise<EnrichedSentPing> => {
    try {
      const result = await apolloClient.query({
        query: PROFILE_QUERY,
        variables: { profileId: ping.targetProfileId },
        // Apollo doesn't have 'network-first'; using network-only ensures we
        // always pull the latest interactionStatus.theirs from the server so
        // declined/liked-back states aren't masked by stale cache.
        fetchPolicy: 'network-only',
      });

      const profile = result.data?.profile;
      if (profile) {
        return {
          ...ping,
          profile,
          targetName: profile.imaginaryName || ping.targetName,
        };
      }
      return { ...ping, profileError: 'Profile not found' };
    } catch (e: any) {
      console.error(`Failed to fetch profile ${ping.targetProfileId}:`, e);
      return { ...ping, profileError: e.message || 'Failed to load profile' };
    }
  }, []);

  // Load sent pings from storage on mount
  useEffect(() => {
    const load = async () => {
      setLoading(true);
      try {
        const pings = await dataSync.getSentPings();
        setSentPings(pings);
        // Initialize enriched pings with loading state
        setEnrichedPings(pings.map(p => ({ ...p, profileLoading: true })));
      } catch (e) {
        console.error('Failed to load sent pings:', e);
      } finally {
        setLoading(false);
      }
    };
    load();
  }, []);

  // Fetch profile data for all pings when sentPings changes
  useEffect(() => {
    if (sentPings.length === 0) {
      setEnrichedPings([]);
      return;
    }

    const fetchAllProfiles = async () => {
      setProfilesLoading(true);
      try {
        const enriched = await Promise.all(
          sentPings.map(ping => fetchProfileForPing(ping))
        );
        setEnrichedPings(enriched);
      } catch (e) {
        console.error('Failed to fetch profiles:', e);
      } finally {
        setProfilesLoading(false);
      }
    };

    fetchAllProfiles();
  }, [sentPings, fetchProfileForPing]);

  const sendPing = async (
    targetProfileId: string,
    targetName?: string,
    message?: string
  ): Promise<{ success: boolean; error?: string; status?: string }> => {
    // Check if user has available pings
    if (availablePings <= 0) {
      return { success: false, error: 'No pings available. Purchase more pings to continue.' };
    }

    try {
      const result = await profilePingMutation({
        variables: {
          targetProfileId,
          message,
          overrideInappropriate: false,
        },
      });

      const pingResult = result.data?.profilePing;

      if (pingResult?.status === 'SENT') {
        // Save to local storage
        await dataSync.addSentPing(targetProfileId, targetName, message);

        // Optimistic update
        const newPing: SentPing = {
          targetProfileId,
          targetName,
          message,
          sentAt: Date.now(),
          status: 'SENT',
        };
        setSentPings(prev => [newPing, ...prev]);

        // Refetch account to update availablePings
        refetchAccount();

        return { success: true, status: pingResult.status };
      }

      return {
        success: false,
        error: `Ping failed with status: ${pingResult?.status || 'unknown'}`,
        status: pingResult?.status,
      };
    } catch (e: any) {
      console.error('Failed to send ping:', e);
      return { success: false, error: e.message || 'Failed to send ping' };
    }
  };

  const removePing = async (targetProfileId: string) => {
    setSentPings(prev => prev.filter(p => p.targetProfileId !== targetProfileId));
    await dataSync.removeSentPing(targetProfileId);
  };

  const updatePingStatus = async (targetProfileId: string, status: 'SENT' | 'MATCHED' | 'EXPIRED') => {
    setSentPings(prev =>
      prev.map(p => (p.targetProfileId === targetProfileId ? { ...p, status } : p))
    );
    await dataSync.updateSentPingStatus(targetProfileId, status);
  };

  const hasPinged = (targetProfileId: string) => {
    return sentPings.some(p => p.targetProfileId === targetProfileId);
  };

  const clearAllPings = async () => {
    setSentPings([]);
    setEnrichedPings([]);
    await dataSync.clearAllSentPings();
  };

  // Refresh profile data for all pings
  const refreshProfiles = useCallback(async () => {
    if (sentPings.length === 0) return;

    setProfilesLoading(true);
    try {
      const enriched = await Promise.all(
        sentPings.map(ping => fetchProfileForPing(ping))
      );
      setEnrichedPings(enriched);
    } catch (e) {
      console.error('Failed to refresh profiles:', e);
    } finally {
      setProfilesLoading(false);
    }
  }, [sentPings, fetchProfileForPing]);

  return {
    sentPings: enrichedPings, // Return enriched pings instead of raw pings
    rawPings: sentPings,
    loading,
    profilesLoading,
    sendingPing,
    availablePings,
    sendPing,
    removePing,
    updatePingStatus,
    hasPinged,
    clearAllPings,
    refreshProfiles,
    refetchAccount,
  };
}
