const API_BASE_URL = "https://hyperapp.in";

import {
  IMultiTransaction,
  MultiTransactionType,
  TransactionStatus,
  OverallStatus,
  TokenURI,
} from "../types/activity";

// Define interface for the output details
export interface OutputDetails {
  amount: string;
  amountFormatted: string;
  amountUsd: string;
  minimumAmount: string;
}

// Define interface for the request parameters
export interface MultiRelayBuyQuoteParams {
  username: string;
  amount: number;
  outputToken: string;
  outputChainId: number;
}

// Balance interfaces
export interface TokenBalance {
  // Add balance properties as needed
  symbol: string;
  balance: string;
  balanceInUsd: string;
  // Other properties from the API response
}

export interface BalanceResponse {
  success: boolean;
  data: any;
  portfolioSummary?: any;
}

export interface MultiRelaySellQuoteParams {
  username: string;
  amount: number;
  inputToken: string;
  chainId: number;
}

export interface MultiRelaySwapQuoteParams {
  username: string;
  userBalance: any[] | undefined;
  outputToken: string;
  outputChainId: number;
  inputAmount?: number | string;
  proMode?: boolean;
  txsGasLimit?: number;
  metadata?: {
    inputToken: TokenURI;
    outputToken: TokenURI;
  };
}

export interface BuyFlowParams {
  username: string;
  amount: number;
  outputToken: string;
  outputChainId: number;
  txGasLimit: number;
}

export interface SellFlowParams {
  username: string;
  amount: number;
  inputToken: string;
  chainId: number;
}

export interface SwapInput {
  chainId: number;
  tokenAddress: string;
  amount: string;
}

export interface SwapFlowParams {
  username: string;
  userBalance: any[] | undefined;
  outputToken: string | undefined;
  outputChainId: number | undefined;
  metadata: {
    inputToken: TokenURI;
    outputToken: TokenURI;
  };
  inputAmount?: number | string;
  proMode?: boolean;
  txsGasLimit?: number;
}

export interface TransactionResult {
  chainId: number;
  success: boolean;
  txnHash: string;
  requestId?: string;
}

export interface TransferFlowParams {
  username: string;
  inputAmount: string;
  outputToken: string;
  outputDecimals: number;
  outputChainId: number;
  recipient: string;
  userBalance: any[];
  metadata?: any;
}

export interface TransferResponse {
  spendPlan: {
    total_withdrawn: string;
    spend_distribution: { [key: string]: string };
    remaining_balance: string;
  };
  onChainTransfer?: {
    chainId: number;
    txHash: string;
  };
  relayTransfer?: {
    type: string;
    success: boolean;
    evmTransactions: TransactionResult[];
    solanaTransactions: TransactionResult[];
  };
  outputDetails: {
    amount: string;
    minimumAmount: string;
    amountFormatted: string;
  };
}

export interface User {
  username: string;
  walletAddress: string;
  solana_program_wallet: string;
  ens: string;
}

export interface TokenDetail {
  amount: string;
  amountFormatted: string;
  tokenAddress: string;
  tokenName: string;
  tokenSymbol: string;
  receiver?: User;
}

export interface ChainTokenDetails {
  [chainId: string]: TokenDetail[];
}

export interface ChainTransactions {
  [chainId: string]: {
    [txHash: string]: string;
  };
}

export interface TransactionMetadata {
  senderDetails: User;
  receiverDetails: User[];
  inputAmounts: ChainTokenDetails;
  destinationAmounts: ChainTokenDetails;
  status: string;
  lastUpdatedTimestamp: number;
  transactions: ChainTransactions;
  requestIdsMap?: {
    [chainId: string]: string;
  };
}

export interface ActivityItem {
  _id: string;
  multiTransactionId: string;
  sender: User;
  transactionType: string;
  transactionDescription: string;
  receivers: User[];
  sourceChains: number[];
  destinationChains: number[];
  inputTokens: ChainTokenDetails;
  outputTokens: ChainTokenDetails;
  transactions: ChainTransactions;
  overallStatus: string;
  metadata: TransactionMetadata;
  createdTimestamp: number;
  lastUpdatedTimestamp: number;
  updatedAt: string;
  __v: number;
}

export interface ActivityResponse {
  success: boolean;
  data: IMultiTransaction[];
}

// Add new interface for BTC swap quote params
export interface BTCRelaySwapQuoteParams {
  username: string;
  amount: number | string;
  outputToken: string;
  outputChainId: number;
}

// Add new interface for BTC swap quote params
export interface ToBTCRelaySwapQuoteParams {
  username: string;
  userBalance: any[] | undefined;
  inputAmount?: number | string;
  proMode?: boolean;
  txsGasLimit?: number;
}

// Add new interface for BTC swap execution params
export interface ToBTCSwapFlowParams {
  username: string;
  userBalance: any[] | undefined;
  inputAmount?: number | string;
  proMode: boolean;
  metadata: {
    inputToken: TokenURI;
    outputToken: TokenURI;
  };
}

// Add new interface for from BTC swap execution params
export interface FromBTCSwapFlowParams {
  username: string;
  amount: number | string;
  outputToken: string;
  outputChainId: number;
  metadata: {
    inputToken: TokenURI;
    outputToken: TokenURI;
  };
}

export interface BitcoinTransferParams {
  username: string;
  inputAmount: string;
  recipient: string;
  outputChainId: number;
  metadata?: {
    token: {
      tokenSymbol: string;
      tokenName: string;
      decimals: number;
      logoURI?: string;
    };
    receiver: {
      username?: string;
      walletAddress?: string;
      solanaWalletAddress?: string;
      ensName?: string;
      sns?: string;
    };
  };
}

export interface BitcoinTransferResponse {
  success: boolean;
  transactionDetails: {
    multiTransactionId: string;
    txHash?: string;
  };
}

/**
 * Fetches a buy quote from the multi-relay endpoint
 * @param params Request parameters for the quote
 * @param apiKey The wallet SDK key for authorization
 * @returns The output details from the quote response
 */
export const getMultiRelayBuyQuote = async (
  params: MultiRelayBuyQuoteParams,
  apiKey: string
): Promise<OutputDetails | string> => {
  try {
    const response = await fetch(`${API_BASE_URL}/relay/buy/quote`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      const errorData = await response.json();
      console.log("errorData", errorData);
      return errorData.message;
    }

    const data = await response.json();
    return data.outputDetails || null;
  } catch (error) {
    console.error("Error fetching multi relay buy quote:", error);
    return "Error fetching quote";
  }
};

export const getMultiRelaySellQuote = async (
  params: MultiRelaySellQuoteParams,
  apiKey: string
): Promise<OutputDetails | string> => {
  try {
    const response = await fetch(`${API_BASE_URL}/relay/sell/quote`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      const errorData = await response.json();
      console.log("errorData", errorData);
      return errorData.message;
    }

    const data = await response.json();
    return data.outputDetails || null;
  } catch (error) {
    console.error("Error fetching multi relay buy quote:", error);
    return "Error fetching quote";
  }
};

export const getMultiRelaySwapQuote = async (
  params: MultiRelaySwapQuoteParams,
  apiKey: string
): Promise<OutputDetails | any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/swap/unified/quote`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      const errorData = await response.json();
      console.log("errorData", errorData);
      return errorData;
    }

    const data = await response.json();
    return data || null;
  } catch (error) {
    console.error("Error fetching multi relay buy quote:", error);
    return "Error fetching quote";
  }
};

export const getMultiFromBTCRelaySwapQuote = async (
  params: BTCRelaySwapQuoteParams,
  apiKey: string
): Promise<OutputDetails | any> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/relay/fromBitcoin/swap/quote`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `${apiKey}`,
        },
        body: JSON.stringify(params),
      }
    );

    if (!response.ok) {
      const errorData = await response.json();
      console.log("errorData", errorData);
      return errorData;
    }

    const data = await response.json();
    return data || null;
  } catch (error) {
    console.error("Error fetching BTC relay swap quote:", error);
    return "Error fetching quote";
  }
};

export const getMultiToBTCRelaySwapQuote = async (
  params: ToBTCRelaySwapQuoteParams,
  apiKey: string
): Promise<OutputDetails | any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/relay/toBitcoin/swap/quote`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      const errorData = await response.json();
      console.log("errorData", errorData);
      return errorData;
    }

    const data = await response.json();
    return data || null;
  } catch (error) {
    console.error("Error fetching to BTC relay swap quote:", error);
    return "Error fetching quote";
  }
};

/**
 * Fetches the user's crypto balance
 * @param username The user's username
 * @param apiKey The wallet SDK key for authorization
 * @returns The user's crypto balance data
 */
export const getUserCryptoBalance = async (
  username: string,
  apiKey: string
): Promise<BalanceResponse | null> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/v1/userbalance?username=${username}`,
      {
        headers: {
          Authorization: `${apiKey}`,
        },
      }
    );
    if (!response.ok) throw new Error("Failed to fetch balance");
    const data = await response.json();
    return {
      success: data.success,
      data: data.userBalances,
      portfolioSummary: data.portfolioSummary,
    };
  } catch (error) {
    console.error("Error fetching crypto balance:", error);
    return null;
  }
};

/**
 * Executes a buy flow transaction
 * @param params The buy flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeBuyFlow = async (
  params: BuyFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/relay/buy/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing buy flow:", error);
    throw error;
  }
};

/**
 * Executes a sell flow transaction
 * @param params The sell flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeSellFlow = async (
  params: SellFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/relay/sell/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing sell flow:", error);
    throw error;
  }
};

/**
 * Executes a swap flow transaction
 * @param params The swap flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeSwapFlow = async (
  params: SwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/relay/swap/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing swap flow:", error);
    throw error;
  }
};

/**
 * Executes a bungee swap flow transaction
 * @param params The swap flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeBungeeSwapFlow = async (
  params: SwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/bungee/swap/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing bungee swap flow:", error);
    throw error;
  }
};

/**
 * Executes a CCTP swap flow transaction for USDC to USDC transfers
 * @param params The swap flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeCCTPSwapFlow = async (
  params: SwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/cctp/v1/swap/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing CCTP swap flow:", error);
    throw error;
  }
};

/**
 * Executes a LiFi swap flow transaction
 * @param params The swap flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeLiFiSwapFlow = async (
  params: SwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/lifi/swap/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing LiFi swap flow:", error);
    throw error;
  }
};

export const executeCCTPV2SwapFlow = async (
  params: SwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(`${API_BASE_URL}/cctp/v2/swap/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `${apiKey}`,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing CCTP swap flow:", error);
    throw error;
  }
};

export const executeTransferFlow = async (
  params: TransferFlowParams,
  apiKey: string
): Promise<TransferResponse> => {
  try {
    // Log the request parameters with detailed balance info
    console.log("Transfer Flow Request Details:", {
      username: params.username,
      inputAmount: params.inputAmount,
      inputAmountFormatted: `${
        Number(params.inputAmount) / Math.pow(10, params.outputDecimals)
      } USDC`,
      outputToken: params.outputToken,
      outputChainId: params.outputChainId,
      recipient: params.recipient,
      availableBalance: params.userBalance.find(
        (token) => token.chainId === params.outputChainId
      )?.balance,
    });

    // Validate required parameters
    if (
      !params.username ||
      !params.inputAmount ||
      !params.outputToken ||
      !params.outputChainId ||
      !params.recipient
    ) {
      throw new Error("Missing required parameters");
    }

    // Validate userBalance array
    if (!Array.isArray(params.userBalance) || params.userBalance.length === 0) {
      throw new Error("Invalid user balance data");
    }

    // // Find the token balance for the output chain
    // const tokenBalance = params.userBalance.find(
    //   (token) => token.chainId === params.outputChainId
    // );

    // if (!tokenBalance) {
    //   throw new Error(`No balance found for chain ${params.outputChainId}`);
    // }

    const response = await fetch(`${API_BASE_URL}/relay/transfer/full-flow`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: apiKey,
      },
      body: JSON.stringify(params),
    });

    // Log the response status and headers
    console.log("Transfer Flow Response Status:", response.status);
    console.log("Transfer Flow Response Headers:", {
      "content-type": response.headers.get("content-type"),
      "content-length": response.headers.get("content-length"),
    });

    if (!response.ok) {
      const errorData = await response.json();
      console.error("Transfer Flow Error Response:", errorData);
      throw new Error(errorData.message || "Transfer failed");
    }

    const data = await response.json();
    console.log("Transfer Flow Success Response:", data);
    return data;
  } catch (error: any) {
    console.error("Error executing transfer flow:", {
      error,
      message: error.message,
      params: JSON.stringify(params, null, 2),
    });
    throw error;
  }
};

export const getMultiTransactionsList = async (
  username: string,
  apiKey: string
): Promise<ActivityResponse | null> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/api/multiTransactions/list?username=${username}`,
      {
        headers: {
          Authorization: `${apiKey}`,
        },
      }
    );
    if (!response.ok) throw new Error("Failed to fetch activity");
    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Error fetching activity:", error);
    return null;
  }
};

// Interface for transaction info response
export interface TxnInfoResponse {
  transaction: IMultiTransaction;
}

// Function to fetch transaction details by ID
export const getTransactionInfo = async (
  multiTransactionId: string,
  apiKey: string
): Promise<IMultiTransaction | null> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/relay/txnInfo?multiTransactionId=${multiTransactionId}`,
      {
        headers: {
          Authorization: `${apiKey}`,
        },
      }
    );

    if (!response.ok) {
      throw new Error("Failed to fetch transaction details");
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Error fetching transaction details:", error);
    return null;
  }
};

// Interface for token info
export interface TokenInfo {
  symbol: string;
  name: string;
  logoURI?: string;
  icon?: string;
  address: string;
  chainId: number;
  chainIds?: Array<{
    chainId: number;
    address: string;
  }>;
  decimals: number;
  balance?: string;
  amount?: number;
  priceUsd?: number;
  price?: number;
}

export interface AllTokensResponse {
  success: boolean;
  tokens: TokenInfo[];
}

export const getAllTokens = async (
  apiKey: string
): Promise<AllTokensResponse | null> => {
  try {
    const response = await fetch(`${API_BASE_URL}/paginated-tokens`, {
      headers: {
        Authorization: `${apiKey}`,
      },
    });

    if (!response.ok) {
      throw new Error("Failed to fetch tokens");
    }

    const data = await response.json();
    return {
      success: true,
      tokens: data.data,
    };
  } catch (error) {
    console.error("Error fetching all tokens:", error);
    return null;
  }
};

// Update search token interface to match actual response
export interface SearchTokenResponse {
  success: boolean;
  data: {
    name: string;
    symbol: string;
    decimals: number;
    logoURI: string;
    chainIds: Array<{
      chainId: string;
      address: string;
    }>;
    price: number;
  };
}

export const searchToken = async (
  tokenAddress: string,
  chainId: number,
  apiKey: string
): Promise<SearchTokenResponse | null> => {
  try {
    const response = await fetch(`${API_BASE_URL}/search-token`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: apiKey,
      },
      body: JSON.stringify({
        tokenAddress,
        chainId: chainId.toString(),
      }),
    });

    if (!response.ok) {
      throw new Error("Failed to search token");
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Error searching token:", error);
    return null;
  }
};

// Add new interface for token search response
export interface TokenSearchResponse {
  success: boolean;
  data: TokenInfo[];
}

export const searchTokensByQuery = async (
  query: string,
  apiKey: string
): Promise<TokenSearchResponse | null> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/token/final/search?query=${encodeURIComponent(query)}`,
      {
        headers: {
          Authorization: `${apiKey}`,
        },
      }
    );

    if (!response.ok) {
      throw new Error("Failed to search tokens");
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Error searching tokens:", error);
    return null;
  }
};

/**
 * Executes a swap to BTC flow transaction
 * @param params The swap to BTC flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeToBTCSwapFlow = async (
  params: ToBTCSwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/relay/toBitcoin/swap/full-flow`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `${apiKey}`,
        },
        body: JSON.stringify(params),
      }
    );

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing swap to BTC flow:", error);
    throw error;
  }
};

/**
 * Executes a swap from BTC flow transaction
 * @param params The swap from BTC flow parameters
 * @param apiKey The wallet SDK key for authorization
 * @returns The transaction response
 */
export const executeFromBTCSwapFlow = async (
  params: FromBTCSwapFlowParams,
  apiKey: string
): Promise<any> => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/relay/fromBitcoin/swap/full-flow`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `${apiKey}`,
        },
        body: JSON.stringify(params),
      }
    );

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    return await response.json();
  } catch (error) {
    console.error("Error executing swap from BTC flow:", error);
    throw error;
  }
};

export const executeBitcoinTransfer = async (
  params: BitcoinTransferParams,
  apiKey: string
): Promise<BitcoinTransferResponse> => {
  try {
    const response = await fetch(`${API_BASE_URL}/bitcoin/send-transaction`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: apiKey,
      },
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message || "Bitcoin transfer failed");
    }

    const data = await response.json();
    return data;
  } catch (error: any) {
    console.error("Error executing Bitcoin transfer:", error);
    throw error;
  }
};

// Social login interfaces
export interface SocialLoginParams {
  googleUser: any; // The complete Google user object from Firebase
}

export interface SocialLoginResponse {
  username: string;
  socialLoginDetails: {
    googleUser: {
      email: string;
      displayName: string;
      photoURL: string;
      uid: string;
    };
  };
  verified: boolean;
  multiUserOps: any;
  wallet: {
    scw_address: string;
    type: string;
    multi_scw: Array<{
      network: number;
      address: string;
      deployed: boolean;
    }>;
    eoa_address: string;
    solana_public_key: string;
    solana_program_wallet: string;
    bitcoin_wallet: {
      legacy_address: string;
      segwit_address: string;
      native_segwit_address: string;
      taproot_address: string;
    };
  };
  orgId: string;
  addedOn: number;
  updatedOn: number;
  version: number;
  smartBalanceEnabled: boolean;
  _id: string;
  __v: number;
}

export const getSocialAccount = async (
  params: SocialLoginParams,
  apiKey: string
): Promise<SocialLoginResponse> => {
  const url = `${API_BASE_URL}/social/get-account`;
  const headers = {
    "Content-Type": "application/json",
    Authorization: apiKey,
  };

  try {
    const response = await fetch(url, {
      method: "POST",
      headers,
      body: JSON.stringify(params),
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message || "Social login failed");
    }

    const data = await response.json();
    return data;
  } catch (error: any) {
    console.error("Error getting social account:", error);
    throw error;
  }
};

export { API_BASE_URL };
