/**
 * Blockchain Rewards System
 * Crypto wallet integration and NFT collectibles
 */

export type CryptoNetwork = 'ethereum' | 'polygon' | 'binance' | 'solana' | 'arbitrum';
export type RewardType = 'token' | 'nft' | 'cash';
export type TransactionStatus = 'pending' | 'confirmed' | 'failed' | 'cancelled';

export interface CryptoWallet {
  id: string;
  userId: number;
  address: string;
  network: CryptoNetwork;
  balance: number;
  tokenBalance: number;
  nftCount: number;
  connectedAt: Date;
  lastSyncedAt: Date;
  isVerified: boolean;
}

export interface BlockchainReward {
  id: string;
  userId: number;
  rewardType: RewardType;
  amount: number;
  tokenSymbol: string;
  network: CryptoNetwork;
  transactionHash?: string;
  status: TransactionStatus;
  createdAt: Date;
  completedAt?: Date;
  walletAddress: string;
}

export interface NFTCollectible {
  id: string;
  tokenId: string;
  userId: number;
  name: string;
  description: string;
  imageUrl: string;
  rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary';
  contractAddress: string;
  network: CryptoNetwork;
  acquiredAt: Date;
  value: number; // USD
  isListed: boolean;
  listingPrice?: number;
}

export interface NFTCollection {
  id: string;
  name: string;
  description: string;
  contractAddress: string;
  network: CryptoNetwork;
  totalSupply: number;
  mintedCount: number;
  floorPrice: number;
  imageUrl: string;
  createdAt: Date;
}

export interface CryptoTransaction {
  id: string;
  userId: number;
  walletAddress: string;
  network: CryptoNetwork;
  type: 'deposit' | 'withdrawal' | 'reward' | 'nft_mint';
  amount: number;
  tokenSymbol: string;
  transactionHash: string;
  status: TransactionStatus;
  gasUsed?: number;
  gasFee?: number;
  createdAt: Date;
  completedAt?: Date;
  failureReason?: string;
}

/**
 * Connect crypto wallet
 */
export function connectCryptoWallet(
  userId: number,
  address: string,
  network: CryptoNetwork
): CryptoWallet {
  return {
    id: `wallet_${userId}_${network}`,
    userId,
    address,
    network,
    balance: 0,
    tokenBalance: 0,
    nftCount: 0,
    connectedAt: new Date(),
    lastSyncedAt: new Date(),
    isVerified: false,
  };
}

/**
 * Verify wallet ownership
 */
export function verifyWalletOwnership(wallet: CryptoWallet, signature: string): boolean {
  // In production, verify the signature against the wallet address
  // This is a placeholder implementation
  wallet.isVerified = true;
  return true;
}

/**
 * Create blockchain reward
 */
export function createBlockchainReward(
  userId: number,
  rewardType: RewardType,
  amount: number,
  tokenSymbol: string,
  network: CryptoNetwork,
  walletAddress: string
): BlockchainReward {
  return {
    id: `reward_${userId}_${Date.now()}`,
    userId,
    rewardType,
    amount,
    tokenSymbol,
    network,
    status: 'pending',
    createdAt: new Date(),
    walletAddress,
  };
}

/**
 * Process blockchain reward
 */
export function processBlockchainReward(
  reward: BlockchainReward,
  transactionHash: string
): void {
  reward.transactionHash = transactionHash;
  reward.status = 'confirmed';
  reward.completedAt = new Date();
}

/**
 * Create NFT collectible
 */
export function createNFTCollectible(
  userId: number,
  tokenId: string,
  name: string,
  description: string,
  imageUrl: string,
  rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary',
  contractAddress: string,
  network: CryptoNetwork,
  value: number
): NFTCollectible {
  return {
    id: `nft_${userId}_${tokenId}`,
    tokenId,
    userId,
    name,
    description,
    imageUrl,
    rarity,
    contractAddress,
    network,
    acquiredAt: new Date(),
    value,
    isListed: false,
  };
}

/**
 * List NFT for sale
 */
export function listNFTForSale(nft: NFTCollectible, price: number): void {
  nft.isListed = true;
  nft.listingPrice = price;
}

/**
 * Delist NFT
 */
export function delistNFT(nft: NFTCollectible): void {
  nft.isListed = false;
  nft.listingPrice = undefined;
}

/**
 * Get NFT rarity multiplier
 */
export function getNFTRarityMultiplier(rarity: string): number {
  const multipliers: Record<string, number> = {
    common: 1,
    uncommon: 1.5,
    rare: 2.5,
    epic: 5,
    legendary: 10,
  };
  return multipliers[rarity] || 1;
}

/**
 * Calculate NFT value based on rarity and market
 */
export function calculateNFTValue(
  basePrice: number,
  rarity: string,
  marketMultiplier: number = 1
): number {
  const rarityMultiplier = getNFTRarityMultiplier(rarity);
  return basePrice * rarityMultiplier * marketMultiplier;
}

/**
 * Create crypto transaction
 */
export function createCryptoTransaction(
  userId: number,
  walletAddress: string,
  network: CryptoNetwork,
  type: 'deposit' | 'withdrawal' | 'reward' | 'nft_mint',
  amount: number,
  tokenSymbol: string,
  transactionHash: string
): CryptoTransaction {
  return {
    id: `tx_${userId}_${Date.now()}`,
    userId,
    walletAddress,
    network,
    type,
    amount,
    tokenSymbol,
    transactionHash,
    status: 'pending',
    createdAt: new Date(),
  };
}

/**
 * Confirm crypto transaction
 */
export function confirmCryptoTransaction(
  transaction: CryptoTransaction,
  gasUsed: number,
  gasFee: number
): void {
  transaction.status = 'confirmed';
  transaction.completedAt = new Date();
  transaction.gasUsed = gasUsed;
  transaction.gasFee = gasFee;
}

/**
 * Fail crypto transaction
 */
export function failCryptoTransaction(transaction: CryptoTransaction, reason: string): void {
  transaction.status = 'failed';
  transaction.failureReason = reason;
  transaction.completedAt = new Date();
}

/**
 * Crypto reward tier
 */
export interface CryptoRewardTier {
  tier: string;
  minSpend: number;
  rewardPercentage: number;
  bonusTokens: number;
  nftReward?: string;
}

export const CRYPTO_REWARD_TIERS: CryptoRewardTier[] = [
  {
    tier: 'bronze',
    minSpend: 0,
    rewardPercentage: 1,
    bonusTokens: 0,
  },
  {
    tier: 'silver',
    minSpend: 1000,
    rewardPercentage: 2,
    bonusTokens: 100,
    nftReward: 'silver_collectible',
  },
  {
    tier: 'gold',
    minSpend: 5000,
    rewardPercentage: 3,
    bonusTokens: 500,
    nftReward: 'gold_collectible',
  },
  {
    tier: 'platinum',
    minSpend: 10000,
    rewardPercentage: 5,
    bonusTokens: 1000,
    nftReward: 'platinum_collectible',
  },
  {
    tier: 'diamond',
    minSpend: 50000,
    rewardPercentage: 10,
    bonusTokens: 5000,
    nftReward: 'diamond_collectible',
  },
];

/**
 * Get crypto reward tier
 */
export function getCryptoRewardTier(totalSpend: number): CryptoRewardTier {
  for (let i = CRYPTO_REWARD_TIERS.length - 1; i >= 0; i--) {
    if (totalSpend >= CRYPTO_REWARD_TIERS[i].minSpend) {
      return CRYPTO_REWARD_TIERS[i];
    }
  }
  return CRYPTO_REWARD_TIERS[0];
}

/**
 * Calculate crypto rewards
 */
export function calculateCryptoRewards(
  amount: number,
  totalSpend: number
): { tokens: number; bonus: number } {
  const tier = getCryptoRewardTier(totalSpend);
  const tokens = (amount * tier.rewardPercentage) / 100;
  const bonus = tier.bonusTokens > 0 ? tier.bonusTokens / 1000 : 0;

  return {
    tokens: Math.floor(tokens),
    bonus: Math.floor(bonus),
  };
}

/**
 * Staking configuration
 */
export interface StakingConfig {
  minStakeAmount: number;
  maxStakeAmount: number;
  stakingPeriod: number; // days
  apy: number; // Annual Percentage Yield
  lockupPeriod: number; // days
}

export interface StakingPosition {
  id: string;
  userId: number;
  walletAddress: string;
  stakedAmount: number;
  startTime: Date;
  endTime: Date;
  rewards: number;
  isActive: boolean;
  claimedAt?: Date;
}

/**
 * Create staking position
 */
export function createStakingPosition(
  userId: number,
  walletAddress: string,
  stakedAmount: number,
  stakingPeriod: number,
  apy: number
): StakingPosition {
  const startTime = new Date();
  const endTime = new Date(startTime.getTime() + stakingPeriod * 24 * 60 * 60 * 1000);
  const rewards = (stakedAmount * apy * stakingPeriod) / (100 * 365);

  return {
    id: `stake_${userId}_${Date.now()}`,
    userId,
    walletAddress,
    stakedAmount,
    startTime,
    endTime,
    rewards: Math.floor(rewards),
    isActive: true,
  };
}

/**
 * Claim staking rewards
 */
export function claimStakingRewards(position: StakingPosition): number {
  if (!position.isActive || new Date() < position.endTime) {
    return 0;
  }

  position.isActive = false;
  position.claimedAt = new Date();
  return position.rewards;
}

/**
 * Crypto portfolio
 */
export interface CryptoPortfolio {
  userId: number;
  totalValue: number; // USD
  tokenValue: number;
  nftValue: number;
  stakingValue: number;
  assets: Array<{
    symbol: string;
    amount: number;
    value: number;
    network: CryptoNetwork;
  }>;
}

export function calculateCryptoPortfolio(
  wallet: CryptoWallet,
  nfts: NFTCollectible[],
  stakingPositions: StakingPosition[]
): CryptoPortfolio {
  const userNFTs = nfts.filter((n) => n.userId === wallet.userId);
  const userStaking = stakingPositions.filter((s) => s.userId === wallet.userId && s.isActive);

  const nftValue = userNFTs.reduce((sum, n) => sum + n.value, 0);
  const stakingValue = userStaking.reduce((sum, s) => sum + s.stakedAmount, 0);
  const tokenValue = wallet.tokenBalance * 1; // Assuming 1 token = $1 for now

  return {
    userId: wallet.userId,
    totalValue: tokenValue + nftValue + stakingValue,
    tokenValue,
    nftValue,
    stakingValue,
    assets: [
      {
        symbol: 'CKZ',
        amount: wallet.tokenBalance,
        value: tokenValue,
        network: wallet.network,
      },
    ],
  };
}
