'use client';

import { useState, useRef, useEffect } from 'react';
import { useWallet } from '@solana/wallet-adapter-react';
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import {createTransferInstruction, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, TOKEN_PROGRAM_ID } from '@solana/spl-token';
import Header, { HeaderRef } from './components/Header';
import Leaderboard from './components/Leaderboard';
import { CLUSTER_URL, ENTRY_FEE_DINO } from './shared';
import { DINO_TOKEN_ADDRESS, FEE_COLLECTOR } from './constants';
import { 
  sendTransactionWithMobileOptimization, 
  isMobileDevice, 
  getMobileCommitmentLevel,
  validateTransactionForMobile 
} from './utils/mobileWalletUtils';

interface DashboardData {
  leaderboard: Array<{ owner: string; score: string }>;
  available_tx: string | null;
  attempts_count:number;
}

export default function Home() {
  const wallet = useWallet();
  const { publicKey, sendTransaction } = wallet;
  const [isProcessing, setIsProcessing] = useState(false);
  const [txHash, setTxHash] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [hasTicket, setHasTicket] = useState(false);
  const [ticketTxHash, setTicketTxHash] = useState<string | null>(null);
  const [showPaymentSuccess, setShowPaymentSuccess] = useState(false);
  const [highscore, setHighscore] = useState(0);
  const [dashboardData, setDashboardData] = useState<DashboardData>({ leaderboard: [], available_tx: null, attempts_count: 0 });
  const [dashboardLoading, setDashboardLoading] = useState(true);
  const [dashboardError, setDashboardError] = useState<string | null>(null);
  const headerRef = useRef<HeaderRef>(null);

  // Poll for available tickets every 5 seconds (only when no ticket is available)
  useEffect(() => {
    if (!publicKey) {
      setHasTicket(false);
      return;
    }

    // Don't poll if we already have a ticket
    if (hasTicket) {
      return;
    }

    const checkTicket = async () => {
      try {
        const response = await fetch(`https://vps.playpoolstudios.com/dino/api/get_available_tx.php?owner=${publicKey.toString()}`);
        
        if (response.ok) {
          const ticketData = await response.text();
          // If we get a valid transaction hash (not "0"), we have a ticket
          const ticketAvailable = ticketData !== "0" && ticketData.trim().length > 0;
          setHasTicket(ticketAvailable);
          
          // If ticket becomes available, stop polling immediately
          if (ticketAvailable) {
            setTicketTxHash(ticketData);
            return;
          }

          setTicketTxHash(null);
        } else {
          setHasTicket(false);
          setTicketTxHash(null);
        }
      } catch (error) {
        console.error('Error checking ticket:', error);
        setHasTicket(false);
      } finally {

      }
    };

    // Check immediately
    checkTicket();

    // Set up polling every 5 seconds
    const interval = setInterval(checkTicket, 5000);

    // Cleanup interval on unmount, when publicKey changes, or when ticket becomes available
    return () => clearInterval(interval);
  }, [publicKey, hasTicket]);


  useEffect(() => {
    const handleMessage = (event: MessageEvent) => {
      if (event.origin === window.location.origin && typeof event.data === "string") {
        try {
          const message = JSON.parse(event.data);
          if (message?.type === "gameClose" && typeof message.status === "number") {
            game_close_signal(message.status);
          }
        } catch (error) {
          console.error("JSON parse error from Unity message:", error);
        }
      }
    };

    window.addEventListener("message", handleMessage);
    return () => window.removeEventListener("message", handleMessage);
  }, []);

  // Fetch dashboard data every 5 seconds
  useEffect(() => {
    const fetchDashboardData = async () => {
      try {
        setDashboardLoading(true);
        const response = await fetch('https://vps.playpoolstudios.com/dino/api/get_dashboard_data.php');
        
        if (!response.ok) {
          throw new Error('Failed to fetch dashboard data');
        }
        
        const data: DashboardData = await response.json();

        setHighscore(parseInt(data.leaderboard[0].score));
        setDashboardData(data);
        setDashboardError(null);
      } catch (err) {
        console.error('Error fetching dashboard data:', err);
        setDashboardError(err instanceof Error ? err.message : 'Failed to fetch dashboard data');
      } finally {
        setDashboardLoading(false);
      }
    };

    fetchDashboardData();
    
    // Refresh dashboard data every 5 seconds
    const interval = setInterval(fetchDashboardData, 5000);
    
    return () => clearInterval(interval);
  }, []);

  const game_close_signal = (status: number) => {
    console.log("game_close_signal", status);
    setHasTicket(false);
    setTicketTxHash(null);
  };

  // Auto-hide payment success panel after 5 seconds
  useEffect(() => {
    console.log('useEffect triggered:', { txHash, showPaymentSuccess });
    
    if (txHash && !showPaymentSuccess) {
      console.log('Starting progress animation');
      setShowPaymentSuccess(true);
      console.log('showPaymentSuccess set to true');
    } else {
      console.log('Condition not met:', { txHash: !!txHash, showPaymentSuccess });
    }
  }, [txHash, showPaymentSuccess]);

  // Test useEffect
  useEffect(() => {
    console.log('Test useEffect - component mounted');
  }, []);

  const handleEnterGame = async () => { 
    if (!publicKey) {
      setError('Please connect your wallet first');
      return;
    }

    // CRITICAL: Verify wallet connection is stable for mobile wallets
    if (isMobileDevice()) {
      console.log('Mobile device detected - verifying wallet connection...');
      
      // Check if wallet is still connected
      if (!wallet.connected || !wallet.publicKey) {
        setError('Wallet connection lost. Please reconnect your wallet and try again.');
        return;
      }
      
      // Verify public key matches
      if (!wallet.publicKey.equals(publicKey)) {
        setError('Wallet public key mismatch. Please refresh the page and reconnect your wallet.');
        return;
      }
      
      console.log('Mobile wallet connection verified successfully');
    }

    setIsProcessing(true);
    setError(null);
    setTxHash(null);

    try {
      const connection = new Connection(CLUSTER_URL, 'confirmed');
      const dinoMint = new PublicKey(DINO_TOKEN_ADDRESS);
      
      // Get the user's DINO token account
      const userTokenAccount = await getAssociatedTokenAddress(
        dinoMint,
        publicKey
      );

      // Check user's token account status and balance
      console.log('Checking user token account status...');
      const userTokenAccountInfo = await connection.getAccountInfo(userTokenAccount);
      if (!userTokenAccountInfo) {
        throw new Error('DINO token account not found. Please ensure you have DINO tokens in your wallet.');
      }
      
      // Get token balance
      const userTokenAccounts = await connection.getParsedTokenAccountsByOwner(
        publicKey,
        { mint: dinoMint }
      );
      
      if (userTokenAccounts.value.length === 0) {
        throw new Error('No DINO tokens found in your wallet.');
      }
      
      const userBalance = userTokenAccounts.value[0].account.data.parsed.info.tokenAmount.uiAmount;
      console.log('User DINO balance:', userBalance);
      
      if (userBalance < ENTRY_FEE_DINO) {
        throw new Error(`Insufficient DINO tokens. You have ${userBalance} DINO, but need ${ENTRY_FEE_DINO} DINO to play.`);
      }

      // Get or create the fee collector's DINO token account
      const feeCollectorTokenAccount = await getAssociatedTokenAddress(
        dinoMint,
        FEE_COLLECTOR
      );

      const transaction = new Transaction();

      // Check if fee collector token account exists, if not create it
      const feeCollectorAccountInfo = await connection.getAccountInfo(feeCollectorTokenAccount);
      if (!feeCollectorAccountInfo) {
        console.log('Creating fee collector token account...');
        const createAccountIx = createAssociatedTokenAccountInstruction(
          publicKey,
          feeCollectorTokenAccount,
          FEE_COLLECTOR,
          dinoMint
        );
        transaction.add(createAccountIx);
        console.log('Added create account instruction');
      }

      // Add the transfer instruction (10 DINO tokens = 10,000,000,000 lamports for 9 decimals)
      const transferAmount = ENTRY_FEE_DINO * 1_000_000_000; // 10 DINO tokens
      console.log('Adding transfer instruction for', ENTRY_FEE_DINO, 'DINO tokens (', transferAmount, 'lamports)');
      
      const transferIx = createTransferInstruction(
        userTokenAccount,
        feeCollectorTokenAccount,
        publicKey,
        transferAmount
      );
      
      // CRITICAL: Validate the transfer instruction for mobile wallets
      console.log('Transfer instruction validation:');
      console.log('- From account:', userTokenAccount.toString());
      console.log('- To account:', feeCollectorTokenAccount.toString());
      console.log('- Authority:', publicKey.toString());
      console.log('- Amount (lamports):', transferAmount);
      console.log('- Program ID:', transferIx.programId.toString());
      console.log('- Expected SPL Token Program ID:', TOKEN_PROGRAM_ID.toString());
      
      // Ensure the instruction is using the correct SPL Token program
      if (!transferIx.programId.equals(TOKEN_PROGRAM_ID)) {
        throw new Error(`Transfer instruction program ID mismatch. Expected ${TOKEN_PROGRAM_ID.toString()}, got ${transferIx.programId.toString()}`);
      }
      
      // Ensure the instruction is properly formatted
      if (!transferIx.keys || transferIx.keys.length === 0) {
        throw new Error('Transfer instruction missing required account keys');
      }
      
      // Log all account keys in the instruction
      transferIx.keys.forEach((key, index) => {
        console.log(`- Key ${index}: ${key.pubkey.toString()} (${key.isSigner ? 'signer' : 'non-signer'}, ${key.isWritable ? 'writable' : 'readonly'})`);
      });
      
      transaction.add(transferIx);
      console.log('Added transfer instruction');

      // Get recent blockhash with higher commitment for mobile wallets
      const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
      transaction.recentBlockhash = blockhash;
      transaction.lastValidBlockHeight = lastValidBlockHeight;
      transaction.feePayer = publicKey;

      // CRITICAL: Double-check that all required fields are set for mobile wallets
      if (!transaction.feePayer) {
        throw new Error('Transaction fee payer not set - this will cause signature verification to fail');
      }
      if (!transaction.recentBlockhash) {
        throw new Error('Transaction blockhash not set - this will cause signature verification to fail');
      }
      if (!transaction.lastValidBlockHeight) {
        throw new Error('Transaction lastValidBlockHeight not set - this will cause signature verification to fail');
      }

      // Ensure the transaction is properly formatted for mobile wallets
      console.log('Transaction details before preflight:');
      console.log('- Recent blockhash:', transaction.recentBlockhash);
      console.log('- Last valid block height:', transaction.lastValidBlockHeight);
      console.log('- Fee payer:', transaction.feePayer?.toString());
      console.log('- Number of instructions:', transaction.instructions.length);
      console.log('- Instructions:', transaction.instructions.map((ix, i) => `${i}: ${ix.programId.toString()}`));

      // Validate transaction for mobile wallets
      const validationErrors = validateTransactionForMobile(transaction);
      if (validationErrors.length > 0) {
        console.warn('Transaction validation errors:', validationErrors);
        // For mobile wallets, we might want to be more strict
        if (isMobileDevice()) {
          throw new Error(`Transaction validation failed: ${validationErrors.join(', ')}`);
        }
      }

      // Preflight check for mobile wallets
      try {
        console.log('Running preflight check for transaction...');
        const { value: { err, logs } } = await connection.simulateTransaction(transaction);
        
        if (err) {
          console.warn('Preflight check failed:', err);
          console.log('Preflight logs:', logs);
          
          // For mobile wallets, we'll try to fix common issues and retry
          if (isMobileDevice()) {
            console.log('Attempting to fix transaction for mobile wallet...');
            
            // Refresh blockhash and retry preflight
            const { blockhash: newBlockhash, lastValidBlockHeight: newLastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
            transaction.recentBlockhash = newBlockhash;
            transaction.lastValidBlockHeight = newLastValidBlockHeight;
            
            // Retry preflight with fresh blockhash
            const retryResult = await connection.simulateTransaction(transaction);
            if (retryResult.value.err) {
              console.warn('Preflight retry also failed:', retryResult.value.err);
              // On mobile, we might want to proceed anyway as some wallets handle this differently
              console.log('Proceeding with transaction despite preflight failure (mobile wallet behavior)');
            } else {
              console.log('Preflight retry successful!');
            }
          } else {
            // On desktop, be more strict about preflight failures
            throw new Error(`Transaction simulation failed: ${err}`);
          }
        } else {
          console.log('Preflight check passed successfully');
        }
      } catch (simError) {
        console.warn('Preflight simulation failed:', simError);
        
        // On mobile, we might want to proceed anyway as some wallets handle this differently
        if (isMobileDevice()) {
          console.log('Proceeding with transaction despite preflight failure (mobile wallet behavior)');
        } else {
          throw new Error('Transaction preflight check failed. Please try again.');
        }
      }

      // Send the transaction with mobile-optimized options
      let signature: string;
      
      try {
        signature = await sendTransactionWithMobileOptimization(
          transaction,
          connection,
          wallet,
          {
            skipPreflight: false, // Try with preflight first
            preflightCommitment: 'confirmed',
            maxRetries: 3,
            commitment: getMobileCommitmentLevel()
          }
        );
      } catch (error) {
        console.warn('Mobile-optimized transaction failed, trying with preflight disabled...');
        
        // If mobile-optimized fails, try with preflight disabled for mobile wallets
        if (isMobileDevice()) {
          try {
            // Create a completely fresh transaction with new blockhash
            console.log('Creating fresh transaction for mobile wallet fallback...');
            const freshTransaction = new Transaction();
            
            // Re-add all instructions
            transaction.instructions.forEach(instruction => {
              freshTransaction.add(instruction);
            });
            
            // Get fresh blockhash
            const { blockhash: freshBlockhash, lastValidBlockHeight: freshLastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
            freshTransaction.recentBlockhash = freshBlockhash;
            freshTransaction.lastValidBlockHeight = freshLastValidBlockHeight;
            freshTransaction.feePayer = publicKey;
            
            console.log('Fresh transaction created with new blockhash');
            
            signature = await sendTransactionWithMobileOptimization(
              freshTransaction,
              connection,
              wallet,
              {
                skipPreflight: true, // Disable preflight as fallback
                preflightCommitment: 'confirmed',
                maxRetries: 2,
                commitment: getMobileCommitmentLevel()
              }
            );
          } catch (fallbackError) {
            console.error('Fallback transaction also failed:', fallbackError);
            throw fallbackError;
          }
        } else {
          throw error;
        }
      }
      
      // Remove the old confirmation logic since it's handled in the utility
      setTxHash(signature);
      console.log('Transaction successful! Hash:', signature);
      console.log('txHash state set to:', signature);
      
      // Refresh the dino balance in header after successful payment
      if (headerRef.current) {
        await headerRef.current.refreshBalance();
      }

      // Immediately check for ticket availability after successful payment
      try {
        const ticketResponse = await fetch(`https://vps.playpoolstudios.com/dino/api/get_available_tx.php?owner=${publicKey.toString()}`);
        if (ticketResponse.ok) {
          const ticketData = await ticketResponse.text();
          const ticketAvailable = ticketData !== "0" && ticketData.trim().length > 0;
          setHasTicket(ticketAvailable);
        }
      } catch (ticketError) {
        console.warn('Error checking ticket after payment:', ticketError);
      }
      
      // Send transaction to validator
      try {
        const validatorUrl = `https://solpay.playpoolstudios.com/tx/new?tx=${signature}&target_address=${FEE_COLLECTOR.toString()}&amount=10000000000&sender_address=${publicKey.toString()}&token_mint=${dinoMint.toString()}`;
        // Add leaderboard entry
        const leaderboardUrl = 'https://vps.playpoolstudios.com/dino/api/add_leaderboard.php';
        const leaderboardData = new FormData();
        leaderboardData.append('tx', signature);
        leaderboardData.append('owner', publicKey.toString());
        leaderboardData.append('score', '0'); // Initial score of 0

        try {
          const leaderboardResponse = await fetch(leaderboardUrl, {
            method: 'POST',
            body: leaderboardData
          });
          
          if (!leaderboardResponse.ok) {
            console.warn('Failed to add leaderboard entry');
          }
        } catch (leaderboardError) {
          console.warn('Error adding leaderboard entry:', leaderboardError);
        }
        const response = await fetch(validatorUrl);
        if (response.ok) {
          const result = await response.json();
          console.log('Transaction validated:', result);
        } else {
          console.warn('Failed to validate transaction with server');
        }
      } catch (validationError) {
        console.warn('Error validating transaction with server:', validationError);
      }
      
    } catch (err) {
      console.error('Error processing payment:', err);
      
      // Enhanced error handling for mobile wallets
      let errorMessage = 'Failed to process payment';
      
      if (err instanceof Error) {
        // Log additional debugging info for mobile wallets
        if (isMobileDevice()) {
          console.log('Mobile device detected, additional debugging info:');
          console.log('User agent:', navigator.userAgent);
          console.log('Screen size:', window.innerWidth, 'x', window.innerHeight);
          console.log('Wallet connected:', !!publicKey);
        }
        
        if (err.message.includes('signature verification failed')) {
          errorMessage = 'Mobile wallet signature verification failed. Please try again or check your wallet settings.';
        } else if (err.message.includes('missing signature')) {
          errorMessage = 'Transaction signature missing. Please approve the transaction in your wallet.';
        } else if (err.message.includes('User rejected')) {
          errorMessage = 'Transaction was rejected. Please try again.';
        } else if (err.message.includes('insufficient funds')) {
          errorMessage = 'Insufficient DINO tokens. Please check your balance.';
        } else if (err.message.includes('Transaction simulation failed')) {
          errorMessage = 'Transaction validation failed. Please check your wallet connection and try again.';
        } else if (err.message.includes('blockhash')) {
          errorMessage = 'Transaction expired. Please try again.';
        } else if (err.message.includes('preflight')) {
          errorMessage = 'Transaction preflight check failed. This usually means there\'s an issue with your wallet connection or token balance. Try the Debug Wallet button to diagnose the issue.';
        } else if (err.message.includes('insufficient lamports')) {
          errorMessage = 'Insufficient SOL for transaction fees. Please ensure you have some SOL in your wallet for gas fees.';
        } else if (err.message.includes('invalid account')) {
          errorMessage = 'Invalid account detected. Please refresh the page and reconnect your wallet.';
        } else {
          errorMessage = err.message;
        }
      }
      
      setError(errorMessage);
    } finally {
      setIsProcessing(false);
    }
  };

  const handleDebugWallet = async () => {
    if (!publicKey) {
      setError('Please connect your wallet first');
      return;
    }

    console.log('=== WALLET DEBUG INFO ===');
    console.log('Public key:', publicKey.toString());
    console.log('Is mobile device:', isMobileDevice());
    
    try {
      const connection = new Connection(CLUSTER_URL, 'confirmed');
      const dinoMint = new PublicKey(DINO_TOKEN_ADDRESS);
      
      // Test basic connection
      console.log('Testing Solana connection...');
      const version = await connection.getVersion();
      console.log('Solana version:', version);
      
      // Test token account
      console.log('Testing token account...');
      const userTokenAccount = await getAssociatedTokenAddress(dinoMint, publicKey);
      console.log('User token account:', userTokenAccount.toString());
      
      const userTokenAccountInfo = await connection.getAccountInfo(userTokenAccount);
      console.log('Token account exists:', !!userTokenAccountInfo);
      
      if (userTokenAccountInfo) {
        const userTokenAccounts = await connection.getParsedTokenAccountsByOwner(
          publicKey,
          { mint: dinoMint }
        );
        
        if (userTokenAccounts.value.length > 0) {
          const balance = userTokenAccounts.value[0].account.data.parsed.info.tokenAmount.uiAmount;
          console.log('DINO balance:', balance);
        } else {
          console.log('No DINO tokens found');
        }
      }
      
      // Test simple transaction simulation
      console.log('Testing simple transaction simulation...');
      const testTransaction = new Transaction();
      testTransaction.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash;
      testTransaction.feePayer = publicKey;
      
      try {
        const simResult = await connection.simulateTransaction(testTransaction);
        console.log('Simple transaction simulation result:', simResult);
      } catch (simError) {
        console.error('Simple transaction simulation failed:', simError);
      }
      
      console.log('=== END DEBUG INFO ===');
      setError('Debug info logged to console. Check browser console for details.');
      
    } catch (error) {
      console.error('Debug failed:', error);
      setError(`Debug failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  };

  return (
    <div className="min-h-screen">
      <Header ref={headerRef} />
      
              {/* Game iframe - shown when user has a ticket */}
        {hasTicket && (
          <div className="w-full h-screen flex justify-center items-center bg-white" style={{ marginTop: '80px' }}>
            <iframe
              src={`/Build/index.html?tx=${ticketTxHash}&highscore=${highscore}`}
              className="w-full h-full"
              title="Dino Game"
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
              allowFullScreen
            />
          </div>
        )}

      {/* Main content - only shown when no ticket */}
      {!hasTicket && (
        <main className="pt-20">
          <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
            <div className="text-center">
              <h2 className="text-4xl font-bold text-gray-900 mb-4">
                Welcome to <span className="text-green-600">$DINO</span>
              </h2>
              <p className="text-xl text-gray-600 max-w-2xl mx-auto mb-8">
                Beat the highscore to win the jackpot! 
              </p>


              
              {/* Enter Button - only show when no ticket */}
              {!hasTicket && (
                <div className="flex flex-col items-center space-y-4">
                  <button
                    onClick={handleEnterGame}
                    disabled={!publicKey || isProcessing}
                    className={`px-8 py-4 text-xl font-bold rounded-xl shadow-lg transition-all duration-300 transform hover:scale-105 hover:-translate-y-1 ${
                      !publicKey
                        ? 'bg-gray-400 cursor-not-allowed'
                        : isProcessing
                        ? 'bg-yellow-500 cursor-wait'
                        : 'bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-700 hover:to-emerald-700 text-white shadow-green-500/25 hover:shadow-xl hover:shadow-green-500/30'
                    }`}
                  >
                    {!publicKey 
                      ? 'Connect Wallet to Enter' 
                      : isProcessing 
                      ? 'Processing Payment...' 
                      : `Enter Game - Pay ${ENTRY_FEE_DINO} $DINO`
                    }
                  </button>

                  {/* Debug Button */}
                  {publicKey && (
                    <button
                      onClick={handleDebugWallet}
                      className="px-6 py-3 text-sm font-medium bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition-all duration-300 hover:scale-105"
                    >
                      Debug Wallet
                    </button>
                  )}

                  {/* Status Messages */}
                  {error && (
                    <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg max-w-md">
                      <p className="text-sm">{error}</p>
                    </div>
                  )}

                  {txHash && (
                    <div 
                      className={`bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded-lg max-w-md transition-all duration-300 ease-in-out transform ${
                        showPaymentSuccess 
                          ? 'opacity-100 scale-100 translate-y-0' 
                          : 'opacity-0 scale-95 translate-y-2'
                      }`}
                    >
                      <p className="text-sm font-semibold mb-2">Payment Successful!</p>
                      <p className="text-xs break-all">Transaction Hash: {txHash}</p>
                      <a
                        href={`https://explorer.solana.com/tx/${txHash}?cluster=devnet`}
                        target="_blank"
                        rel="noopener noreferrer"
                        className="text-xs underline hover:text-green-800"
                      >
                        View on Explorer
                      </a>
                    </div>
                  )}
                  
                </div>
              )}

              {/* Leaderboard */}
              <div className="mt-12 max-w-2xl mx-auto">
                <Leaderboard 
                  leaderboard={dashboardData.leaderboard}
                  loading={dashboardLoading}
                  error={dashboardError}
                  attemptsCount={dashboardData.attempts_count}
                />
              </div>
            </div>
          </div>
        </main>
      )}
    </div>
  );
}
