/**
 * Blockchain Integration tRPC Router
 * Handles crypto deposits, withdrawals, and real-time conversion
 */

import { z } from 'zod';
import { protectedProcedure, publicProcedure, router } from '../_core/trpc.ts';
import {
  connectCryptoWallet,
  createCryptoDeposit,
  createCryptoWithdrawal,
  confirmCryptoTransaction,
  failCryptoTransaction,
  getExchangeRate,
  convertCryptoToUSD,
  convertUSDToCrypto,
  validateCryptoDeposit,
  validateCryptoWithdrawal,
  getSupportedNetworks,
  getNetworkInfo,
  getUserCryptoWallets,
  getUserCryptoTransactions,
  calculatePortfolioValue,
  getKYCStatusForCrypto,
} from '../blockchainIntegrationService.ts';
import { TRPCError } from '@trpc/server';

export const blockchainIntegrationRouter = router({
  /**
   * Get supported crypto networks
   */
  getSupportedNetworks: publicProcedure.query(async () => {
    return getSupportedNetworks();
  }),

  /**
   * Get network information
   */
  getNetworkInfo: publicProcedure
    .input(z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']))
    .query(async ({ input }) => {
      return getNetworkInfo(input);
    }),

  /**
   * Get real-time exchange rate
   */
  getExchangeRate: publicProcedure
    .input(z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']))
    .query(async ({ input }) => {
      try {
        return await getExchangeRate(input);
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to fetch exchange rate',
        });
      }
    }),

  /**
   * Convert crypto to USD
   */
  convertCryptoToUSD: publicProcedure
    .input(
      z.object({
        amount: z.number().positive(),
        network: z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']),
      })
    )
    .query(async ({ input }) => {
      try {
        const usdAmount = await convertCryptoToUSD(input.amount, input.network);
        return { usdAmount };
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Conversion failed',
        });
      }
    }),

  /**
   * Convert USD to crypto
   */
  convertUSDToCrypto: publicProcedure
    .input(
      z.object({
        usdAmount: z.number().positive(),
        network: z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']),
      })
    )
    .query(async ({ input }) => {
      try {
        const cryptoAmount = await convertUSDToCrypto(input.usdAmount, input.network);
        return { cryptoAmount };
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Conversion failed',
        });
      }
    }),

  /**
   * Connect crypto wallet
   */
  connectWallet: protectedProcedure
    .input(
      z.object({
        walletAddress: z.string(),
        network: z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        const wallet = await connectCryptoWallet(
          ctx.user.id,
          input.walletAddress,
          input.network
        );
        return wallet;
      } catch (error) {
        throw new TRPCError({
          code: 'BAD_REQUEST',
          message: error instanceof Error ? error.message : 'Failed to connect wallet',
        });
      }
    }),

  /**
   * Get user's crypto wallets
   */
  getUserWallets: protectedProcedure.query(async ({ ctx }) => {
    try {
      return await getUserCryptoWallets(ctx.user.id);
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch wallets',
      });
    }
  }),

  /**
   * Get user's crypto transaction history
   */
  getTransactionHistory: protectedProcedure
    .input(z.object({ limit: z.number().default(50) }))
    .query(async ({ ctx, input }) => {
      try {
        return await getUserCryptoTransactions(ctx.user.id, input.limit);
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to fetch transaction history',
        });
      }
    }),

  /**
   * Initiate crypto deposit
   */
  initiateCryptoDeposit: protectedProcedure
    .input(
      z.object({
        walletAddress: z.string(),
        network: z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']),
        cryptoAmount: z.number().positive(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        // Validate deposit
        const usdAmount = await convertCryptoToUSD(input.cryptoAmount, input.network);
        const validation = await validateCryptoDeposit(ctx.user.id, usdAmount);

        if (!validation.valid) {
          throw new TRPCError({
            code: 'BAD_REQUEST',
            message: validation.error || 'Invalid deposit',
          });
        }

        // Create deposit transaction (pending)
        const transaction = await createCryptoDeposit(
          ctx.user.id,
          input.walletAddress,
          input.network,
          input.cryptoAmount,
          '' // Transaction hash will be provided by blockchain
        );

        return transaction;
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to initiate deposit',
        });
      }
    }),

  /**
   * Confirm crypto deposit (called after blockchain confirmation)
   */
  confirmCryptoDeposit: protectedProcedure
    .input(
      z.object({
        transactionId: z.string(),
        transactionHash: z.string(),
        gasUsed: z.number().optional(),
        gasFee: z.number().optional(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        // In production, fetch transaction from database and confirm
        // For now, return success
        return { success: true, message: 'Deposit confirmed' };
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to confirm deposit',
        });
      }
    }),

  /**
   * Initiate crypto withdrawal
   */
  initiateCryptoWithdrawal: protectedProcedure
    .input(
      z.object({
        walletAddress: z.string(),
        network: z.enum(['ethereum', 'polygon', 'solana', 'bitcoin', 'arbitrum']),
        scAmount: z.number().positive(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        // Validate withdrawal
        const validation = await validateCryptoWithdrawal(ctx.user.id, input.scAmount);

        if (!validation.valid) {
          throw new TRPCError({
            code: 'BAD_REQUEST',
            message: validation.error || 'Invalid withdrawal',
          });
        }

        // Create withdrawal transaction (pending)
        const transaction = await createCryptoWithdrawal(
          ctx.user.id,
          input.walletAddress,
          input.network,
          input.scAmount,
          '' // Transaction hash will be provided by blockchain
        );

        return transaction;
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to initiate withdrawal',
        });
      }
    }),

  /**
   * Confirm crypto withdrawal (called after blockchain confirmation)
   */
  confirmCryptoWithdrawal: protectedProcedure
    .input(
      z.object({
        transactionId: z.string(),
        transactionHash: z.string(),
        gasUsed: z.number().optional(),
        gasFee: z.number().optional(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        // In production, fetch transaction from database and confirm
        // For now, return success
        return { success: true, message: 'Withdrawal confirmed' };
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to confirm withdrawal',
        });
      }
    }),

  /**
   * Get KYC status for crypto
   */
  getKYCStatus: protectedProcedure.query(async ({ ctx }) => {
    try {
      return await getKYCStatusForCrypto(ctx.user.id);
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch KYC status',
      });
    }
  }),

  /**
   * Get crypto portfolio value
   */
  getPortfolioValue: protectedProcedure.query(async ({ ctx }) => {
    try {
      const wallets = await getUserCryptoWallets(ctx.user.id);
      const totalValue = await calculatePortfolioValue(wallets);
      return { totalValue, wallets };
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to calculate portfolio value',
      });
    }
  }),

  /**
   * Get deposit requirements
   */
  getDepositRequirements: protectedProcedure.query(async ({ ctx }) => {
    return {
      minimumDeposit: 100, // USD
      minimumDepositSC: 100, // SC
      requiresKYC: true,
      supportedNetworks: getSupportedNetworks(),
      kycLevel: 'basic',
    };
  }),

  /**
   * Get withdrawal requirements
   */
  getWithdrawalRequirements: protectedProcedure.query(async ({ ctx }) => {
    return {
      minimumWithdrawal: 100, // SC
      requiresKYC: true,
      supportedNetworks: getSupportedNetworks(),
      kycLevel: 'basic',
    };
  }),
});
