// OKCupid API integration
// Uses JWT bearer token auth, proxied through Vite to bypass Cloudflare

const DEFAULT_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjb3JlYXBpIiwiYXVkIjoiY29yZWFwaSIsInBsYXRmb3JtSWQiOjExMSwic2Vzc2lvbklkIjoiZjYwYjY3NTAtZTRkMC00ZmViLTg2MzEtNDk3OTVkMWViN2Y5Iiwic2l0ZUNvZGUiOjM2LCJTZXJ2ZXJJZCI6NzksInZlciI6MTIsImlzc1NyYyI6MTAsImVudiI6MSwic2NvcGUiOlsyXSwiYXV0aF90aW1lIjoxNzU3MzM0NTk4LCJpYXQiOjE3NzQ3NTc3NzgsImV4cCI6MTc3NDc2MDQ3OCwic3ViIjoidXZNbGtiYXF6N0Q3VFNqSG91YlE1ZzIiLCJ1cmxDb2RlIjoiMTg2IiwicmVnVXJsQ29kZSI6IjE4NiJ9.X1RwfV7A8aDq6gVXr9IVLIFTQwtlyiQRogWKJwB1Wqc';

export function getOkcToken(): string {
  return localStorage.getItem('okc_token') || DEFAULT_TOKEN;
}

// Try to load token from backend on first use
let _tokenLoaded = false;
async function ensureToken(): Promise<string> {
  const local = localStorage.getItem('okc_token');
  if (local) return local;
  if (!_tokenLoaded) {
    _tokenLoaded = true;
    try {
      const resp = await fetch('/api/okcupid/token');
      const data = await resp.json();
      if (data.token) {
        // Backend only returns a preview — we need the full token saved there
        // Actually check if backend has full token by trying a query
      }
    } catch (e) {}
  }
  return DEFAULT_TOKEN;
}

export function setOkcToken(token: string): void {
  localStorage.setItem('okc_token', token);
  // Also save to backend so it persists across sessions
  fetch('/api/okcupid/token', {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token }),
  }).catch(() => {});
}

// ─── Token refresh ──────────────────────────────────────────────────────────

async function refreshOkcToken(): Promise<string | null> {
  const currentToken = getOkcToken();
  try {
    const res = await fetch('/api/okcupid/graphql/authTokenRefresh', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'x-okc-token': currentToken },
      body: JSON.stringify({
        operationName: 'authTokenRefresh',
        query: 'mutation authTokenRefresh($token: String!) { authTokenRefresh(token: $token) { token loginDisabled } }',
        variables: { token: currentToken },
      }),
    });
    if (!res.ok) return null;
    const json = await res.json();
    const newToken = json?.data?.authTokenRefresh?.token;
    if (newToken) {
      setOkcToken(newToken);
      return newToken;
    }
  } catch (e) {}
  return null;
}

// ─── Core query helper ───────────────────────────────────────────────────────

export async function okcQuery(
  operationName: string,
  query: string,
  variables: Record<string, unknown> = {},
): Promise<any> {
  const token = getOkcToken();
  const res = await fetch(`/api/okcupid/graphql/${operationName}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-okc-token': token,
    },
    body: JSON.stringify({ operationName, query, variables }),
  });

  if (res.status === 401) {
    throw new Error('OKCupid token expired. Paste a new JWT in the Profile tab.');
  }

  if (!res.ok) {
    const text = await res.text().catch(() => '');
    throw new Error(`OKC API ${res.status}: ${text.slice(0, 200)}`);
  }

  const json = await res.json();
  if (json.errors?.length) {
    const errCode = json.errors[0]?.extensions?.code;
    // Auto-refresh on expired token
    if (errCode === 'TOKEN_EXPIRED' || errCode === 'UNAUTHENTICATED') {
      const newToken = await refreshOkcToken();
      if (newToken) {
        // Retry with new token
        const retry = await fetch(`/api/okcupid/graphql/${operationName}`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'x-okc-token': newToken },
          body: JSON.stringify({ operationName, query, variables }),
        });
        if (retry.ok) {
          const retryJson = await retry.json();
          if (!retryJson.errors?.length) return retryJson.data;
        }
      }
      throw new Error('OKCupid token expired. Paste a new JWT in the Profile tab.');
    }
    throw new Error(`OKC GraphQL: ${json.errors[0].message}`);
  }
  return json.data;
}

// ─── Query strings (full, from captured operations) ──────────────────────────

const QUERIES = {
  MainSessionQuery: `query MainSessionQuery($experimentNames: [String]!) { session { __typename ...SessionDataFragment } me { __typename ...SessionUserFragment ...ApolloNotificationCounts ...CrossSellDataFragmentV2 } }\nfragment ApolloNotificationCounts on User { __typename notificationCounts { __typename messages likesIncoming likesMutual likesAndViews intros } }\nfragment CrossSellDataFragmentV2 on User { __typename id photos { __typename id original caption width height } xMatchFields { __typename astrologicalSign bio birthday bodyType drinking education firstName genderPresentation genderReductive hasKids heightInCm highestEducation isPayer jobCompany jobTitle languagesSpoken lookingFor marijuana pets preferences { __typename age { __typename max min } bodyType distanceInKilometers drinking ethnicity hasKids heightInCm { __typename max min } highestEducation marijuana pets politics relationshipStatus religion sexualRole smoking wantsKids } registrationDate relationshipIntent relationshipStatus relationshipType sensitiveFields { __typename ethnicity location { __typename latitude longitude } politics preferences { __typename genderSeeking } religion sexualRole } smoking wantsKids work } }\nfragment GateKeeperChecksFragment on Session { __typename gatekeeperChecks { __typename APP_FORCE_UPDATE ONBOARDING_MANDATORY_REDIRECT TERMS_MANDATORY_REDIRECT SMS_MANDATORY_REDIRECT BLOCK_PERSONALIZED_MARKETING HAS_PHONE SMS_KILL_SWITCH NEEDS_DETAILS_REBOARDING IDENTITY_TAGS_QUALIFIES JEWISH_RELIGIOUS_IDENTITY_ATTRIBUTES_QUALIFIES INCOGNITO_TERMED_MANDATORY_REDIRECT } }\nfragment SessionDataFragment on Session { __typename guestId ipCountry isInEU isAppsConsentKillswitchEnabled additionalPolicies traceSampleRate ...GateKeeperChecksFragment experiments(names: $experimentNames) { __typename group } }\nfragment SessionUserFragment on User { __typename id displayname age emailAddress binaryGenderLetter orientations relationshipType unitPreference userLocation { __typename publicName } primaryImage { __typename square800 } boostTokenCount superlikeTokenCount rewindTokenCount learnMyTypeLikeCount isIncognito hasMetPhotoRequirements hasSeenSwipingTutorial: hasSeenUserGuide(feature: USER_SWIPING_TUTORIAL) joinDate ...SubscriptionInfo globalPreferences { __typename gender { __typename values } } selfieVerifiedStatus(shouldReturnStatus: true) isPurchaseBanned }\nfragment SubscriptionFeature on FeatureSubscription { __typename timeOfActualLoss wasEverActive isActive }\nfragment SubscriptionInfo on User { __typename unlimitedLikesSubscriptionFeature: featureSubscription(feature: UNLIMITED_LIKES) { __typename ...SubscriptionFeature } seeWhoLikesYouSubscriptionFeature: featureSubscription( feature: SEE_WHO_LIKES_YOU ) { __typename ...SubscriptionFeature } ALIST_BASIC: hasPremium(name: ALIST_BASIC) ALIST_PREMIUM: hasPremium(name: ALIST_PREMIUM) ALIST_PREMIUM_PLUS: hasPremium(name: ALIST_PREMIUM_PLUS) INCOGNITO: hasPremium(name: INCOGNITO_BUNDLE) }`,

  PublicProfile: `query PublicProfile($userId: ID!, $userIdString: String!, $conversationThreadLimit: Int) { me { __typename id ...SelfProfile match(id: $userIdString) { __typename ...ApolloBaseUser user { __typename id ...ProfileDetailsAndPreferences ...ProfileEssays ...PhotosFragment } } } }\nfragment ApolloBaseUser on Match { __typename user { __typename id displayname age userLocation { __typename publicName } primaryImage { __typename square800 } isOnline } matchPercent senderVote senderMessageTime senderBlocked targetVote targetLikes targetViewedMe likeTime targetLikeViaSpotlight targetLikeViaSuperBoost targetMessageTime firstMessage { __typename id text time threadId attachments { __typename ...AttachmentFragment } } }\nfragment ApolloEssay on Essay { __typename id title groupTitle groupId isActive isPassion processedContent rawContent placeholder picture { __typename id square800 } }\nfragment AttachmentFragment on Attachment { __typename ... on ProfileCommentPhoto { __typename photo { __typename id original } } ... on ProfileCommentEssay { __typename essayTitle essayText } }\nfragment PhotosFragment on User { __typename photos { __typename id original square225 square800 caption width height crop { __typename upperLeftX upperLeftY lowerRightX lowerRightY } } }\nfragment ProfileDetailsAndPreferences on User { __typename badges { __typename name } bodyType children relationshipStatus relationshipType drinking pets weed ethnicity smoking politics height astrologicalSign diet knownLanguages genders orientations pronounCategory customPronouns identityTags occupation { __typename title employer status } education { __typename level school { __typename name } } religion { __typename value modifier } shabbatRoutine kosherHabits religiousBackground globalPreferences { __typename relationshipType { __typename values } connectionType { __typename values } gender { __typename values } } selfieVerifiedStatus(shouldReturnStatus: true) }\nfragment ProfileEssays on User { __typename essaysWithUniqueIds { __typename ...ApolloEssay } }\nfragment SelfProfile on User { __typename isIncognito unitPreference conversationThread(targetId: $userId, limit: $conversationThreadLimit) { __typename canMessage messages { __typename senderId text attachments { __typename ...AttachmentFragment } } } match(id: $userIdString) { __typename senderIsVisibleThroughIncognito } }`,

  NotificationBatch: `query NotificationBatch { me { __typename notificationCounts { __typename likesMutual messages } matches: conversationsAndMatches(filter: MATCHES, limit: 1) { __typename data { __typename ... on MutualMatch { __typename match { __typename user { __typename ...BasicUserInfo } } } } } messages: conversationsAndMatches(filter: REPLIES, limit: 1) { __typename data { __typename ... on Conversation { __typename correspondent { __typename user { __typename ...BasicUserInfo } } } } } } }\nfragment BasicUserInfo on User { __typename id displayname primaryImage { __typename square225 } }`,

  LikesIncomingPage: `query LikesIncomingPage($nextPageKey: String, $limit: Int, $sort: LikesListSort, $includeViews: Boolean! = false) { me { __typename likesIncomingWithPreviews( after: $nextPageKey limit: $limit sort: $sort includeViews: $includeViews ) { __typename data { __typename ...ApolloBaseUser ...ApolloPreviewUser ...UserMatchHighlightsFragment ...PreviewMatchHighlightsFragment } pageInfo { __typename ...ApolloPaging } } promosForPage(page: LIKES_INCOMING) { __typename ...ApolloPromo } } }\nfragment ApolloBaseUser on Match { __typename user { __typename id displayname age userLocation { __typename publicName } primaryImage { __typename square800 } isOnline } matchPercent senderVote senderMessageTime senderBlocked targetVote targetLikes targetViewedMe likeTime targetLikeViaSpotlight targetLikeViaSuperBoost targetMessageTime firstMessage { __typename id text time threadId attachments { __typename ...AttachmentFragment } } }\nfragment ApolloPaging on PageInfo { __typename before after hasMore total }\nfragment ApolloPreviewUser on MatchPreview { __typename primaryImage { __typename square800 } primaryImageBlurred { __typename square800 } hasFirstMessage targetSuperlikes targetViewedMe matchHighlights { __typename ...MatchHighlightsFragment } }\nfragment ApolloPromo on Promo { __typename id name type upsellType featureType }\nfragment AttachmentFragment on Attachment { __typename ... on ProfileCommentPhoto { __typename photo { __typename id original } } ... on ProfileCommentEssay { __typename essayTitle essayText } }\nfragment MatchHighlightsFragment on MatchHighlights { __typename age matchScore isOnline isVerified hasIntroMessage dynamicHighlight { __typename ... on RelationshipIntentHighlight { __typename sharedIntents } ... on LocationHighlight { __typename summary } } }\nfragment PreviewMatchHighlightsFragment on MatchPreview { __typename matchHighlights { __typename ...MatchHighlightsFragment } }\nfragment UserMatchHighlightsFragment on Match { __typename matchHighlights { __typename ...MatchHighlightsFragment } }`,

  MessagesAndMatches: `query MessagesAndMatches($nextPageKey: String, $filter: ConversationsAndMatchesFilter!) { me { __typename conversationsAndMatches(filter: $filter, after: $nextPageKey) { __typename data { __typename ... on Conversation { __typename ...ApolloConversationRow } ... on MutualMatch { __typename status isUnread match { __typename ...ConversationCorrespondent } } } pageInfo { __typename ...ApolloPaging } } } }\nfragment ApolloConversationRow on Conversation { __typename correspondent { __typename ...ConversationCorrespondent } attachmentPreviews { __typename ... on GifAttachmentPreview { __typename id } ... on ReactionUpdate { __typename reaction originalMessage updateType } } snippet { __typename text sender { __typename id } } time isUnread threadid status }\nfragment ApolloPaging on PageInfo { __typename before after hasMore total }\nfragment ConversationCorrespondent on Match { __typename likeTime senderVote targetVote targetLikeViaSpotlight targetLikeViaSuperBoost user { __typename id displayname primaryImage { __typename square225 } isOnline } }`,

  conversationThread: `query conversationThread($targetId: ID!, $limit: Int, $before: String) { me { __typename conversationThread(targetId: $targetId, limit: $limit, before: $before) { __typename id status canMessage pageInfo { __typename ...ApolloPaging } correspondent { __typename senderVote targetVote targetLikeViaSpotlight targetLikeViaSuperBoost matchPercent user { __typename id displayname isOnline primaryImage { __typename square225 } } } messages { __typename id senderId threadId text time attachments { __typename ...AttachmentFragment } readTime } isReadReceiptActivated } } }\nfragment ApolloPaging on PageInfo { __typename before after hasMore total }\nfragment AttachmentFragment on Attachment { __typename ... on ProfileCommentPhoto { __typename photo { __typename id original } } ... on ProfileCommentEssay { __typename essayTitle essayText } }`,

  ConversationSend: `mutation ConversationSend($input: ConversationMessageSendInput!) { conversationMessageSend(input: $input) { __typename success nway messageId threadId adTrigger } }`,

  UserVote: `mutation UserVote($input: UserVoteInput!) { userVote(input: $input) { __typename likesRemaining success } }`,

  StacksMenu: `query StacksMenu { me { __typename id stacks { __typename ...StackFragment } hasSeenSwipingTutorial: hasSeenUserGuide(feature: USER_SWIPING_TUTORIAL) } }\nfragment Highlight on ProfileHighlight { __typename ... on PhotoHighlight { __typename id url caption } }\nfragment StackFragment on Stack { __typename id status emptyStateStatus badge data { __typename ... on StackMatch { __typename stream targetLikesSender hasSuperlikeRecommendation profileHighlights { __typename ...Highlight } match { __typename user { __typename id } } } ... on FirstPartyAd { __typename id } ... on ThirdPartyAd { __typename ad } ... on PromotedQuestionPrompt { __typename promotedQuestionId } } }`,

  Stack: `query Stack($stackId: StackTypes!, $excludedUserIds: [String]!, $usersRemaining: Int!) { me { __typename stack( id: $stackId excludedUserIds: $excludedUserIds usersRemaining: $usersRemaining shouldReturnStatusForSelfieVerification: true ) { __typename ...StackWithStackMatchesFragment } } }\nfragment ApolloBaseUser on Match { __typename user { __typename id displayname age userLocation { __typename publicName } primaryImage { __typename square800 } isOnline } matchPercent senderVote senderMessageTime senderBlocked targetVote targetLikes targetViewedMe likeTime targetLikeViaSpotlight targetLikeViaSuperBoost targetMessageTime firstMessage { __typename id text time threadId attachments { __typename ...AttachmentFragment } } }\nfragment ApolloEssay on Essay { __typename id title groupTitle groupId isActive isPassion processedContent rawContent placeholder picture { __typename id square800 } }\nfragment AttachmentFragment on Attachment { __typename ... on ProfileCommentPhoto { __typename photo { __typename id original } } ... on ProfileCommentEssay { __typename essayTitle essayText } }\nfragment Highlight on ProfileHighlight { __typename ... on PhotoHighlight { __typename id url caption } }\nfragment PhotosFragment on User { __typename photos { __typename id original square225 square800 caption width height crop { __typename upperLeftX upperLeftY lowerRightX lowerRightY } } }\nfragment StackMatchFragment on Match { __typename ...ApolloBaseUser user { __typename selfieVerifiedStatus(shouldReturnStatus: true) essaysWithUniqueIds { __typename ...ApolloEssay } ...PhotosFragment badges { __typename name } } }\nfragment StackWithStackMatchesFragment on Stack { __typename id status emptyStateStatus badge data { __typename ... on StackMatch { __typename stream targetLikesSender hasSuperlikeRecommendation profileHighlights { __typename ...Highlight } match { __typename user { __typename id } ...StackMatchFragment } } ... on FirstPartyAd { __typename id } ... on ThirdPartyAd { __typename ad } ... on PromotedQuestionPrompt { __typename promotedQuestionId } } }`,

  StackMatches: `query StackMatches($userIds: [String!]!) { me { __typename matches(ids: $userIds) { __typename ...StackMatchFragment } } }\nfragment ApolloBaseUser on Match { __typename user { __typename id displayname age userLocation { __typename publicName } primaryImage { __typename square800 } isOnline } matchPercent senderVote senderMessageTime senderBlocked targetVote targetLikes targetViewedMe likeTime targetLikeViaSpotlight targetLikeViaSuperBoost targetMessageTime firstMessage { __typename id text time threadId attachments { __typename ...AttachmentFragment } } }\nfragment ApolloEssay on Essay { __typename id title groupTitle groupId isActive isPassion processedContent rawContent placeholder picture { __typename id square800 } }\nfragment AttachmentFragment on Attachment { __typename ... on ProfileCommentPhoto { __typename photo { __typename id original } } ... on ProfileCommentEssay { __typename essayTitle essayText } }\nfragment PhotosFragment on User { __typename photos { __typename id original square225 square800 caption width height crop { __typename upperLeftX upperLeftY lowerRightX lowerRightY } } }\nfragment StackMatchFragment on Match { __typename ...ApolloBaseUser user { __typename selfieVerifiedStatus(shouldReturnStatus: true) essaysWithUniqueIds { __typename ...ApolloEssay } ...PhotosFragment badges { __typename name } } }`,

  LikesCapInfo: `query LikesCapInfo { me { __typename likesCap { __typename ...LikesCapFragment } } }\nfragment LikesCapFragment on LikesCap { __typename likesCapTotal likesRemaining viewCount resetTime }`,

  UserViewedUsers: `mutation UserViewedUsers($input: UserViewedUsersInput!) { userViewedUsers(input: $input) { __typename success } }`,
};

// ─── Exported API functions ──────────────────────────────────────────────────

export async function getMainSession() {
  return okcQuery('MainSessionQuery', QUERIES.MainSessionQuery, {
    experimentNames: [
      'cbmPivotPhase2',
      'iOS.cbmpivot.2485',
      'iOS.LearnMyType.2497',
      'okQuizzyAd',
      'iOS.IAPV3',
      'testExperiment',
    ],
  });
}

export async function getProfile(userId: string) {
  return okcQuery('PublicProfile', QUERIES.PublicProfile, {
    userId,
    userIdString: userId,
    conversationThreadLimit: 2,
  });
}

export async function getNotifications() {
  return okcQuery('NotificationBatch', QUERIES.NotificationBatch);
}

export async function getLikesIncoming(limit = 10, nextPageKey: string | null = null) {
  return okcQuery('LikesIncomingPage', QUERIES.LikesIncomingPage, {
    includeViews: true,
    limit,
    nextPageKey,
    sort: 'LIKES_VIEWS_GLOBAL',
  });
}

export async function getRealLikesCount() {
  const data = await okcQuery('LikesIncomingPage', QUERIES.LikesIncomingPage, {
    includeViews: false,
    limit: 1,
    nextPageKey: null,
    sort: 'LIKES_VIEWS_GLOBAL',
  });
  return data?.me?.likesIncomingWithPreviews?.pageInfo?.total || 0;
}

export async function getMessages(filter: string = 'ALL', nextPageKey: string | null = null) {
  return okcQuery('MessagesAndMatches', QUERIES.MessagesAndMatches, {
    filter,
    nextPageKey,
  });
}

export async function getConversation(targetId: string, limit = 30) {
  return okcQuery('conversationThread', QUERIES.conversationThread, {
    targetId,
    limit,
    before: null,
  });
}

export async function sendMessage(targetId: string, text: string) {
  return okcQuery('ConversationSend', QUERIES.ConversationSend, {
    input: { targetId, text },
  });
}

export async function vote(targetId: string, voteType: 'LIKE' | 'PASS', userMetadata?: string) {
  return okcQuery('UserVote', QUERIES.UserVote, {
    input: {
      votes: [
        {
          targetId,
          vote: voteType,
          voteSource: 'DOUBLETAKE',
          ...(userMetadata ? { userMetadata } : {}),
        },
      ],
    },
  });
}

export async function getStacks() {
  return okcQuery('StacksMenu', QUERIES.StacksMenu);
}

export async function getStack(stackId: string, excludedUserIds: string[] = []) {
  return okcQuery('Stack', QUERIES.Stack, {
    stackId,
    excludedUserIds,
    usersRemaining: 0,
  });
}

export async function getStackMatches(userIds: string[]) {
  return okcQuery('StackMatches', QUERIES.StackMatches, { userIds });
}

export async function getLikesCapInfo() {
  return okcQuery('LikesCapInfo', QUERIES.LikesCapInfo);
}

export async function markUsersViewed(targetIds: string[]) {
  return okcQuery('UserViewedUsers', QUERIES.UserViewedUsers, {
    input: { targetIds },
  });
}
