/**
 * Copyright (c) 2024-2026 Тарабанов Александр Викторович
 * All rights reserved.
 * 
 * This software is proprietary and confidential.
 * Unauthorized copying, modification, or distribution is prohibited.
 * 
 * For licensing inquiries: info@hb3-accelerator.com
 * Website: https://hb3-accelerator.com
 * GitHub: https://github.com/VC-HB3-Accelerator
 */

const express = require('express');
const router = express.Router();
const { ethers } = require('ethers');
const rpcProviderService = require('../services/rpcProviderService');
const { getSupportedChainIds } = require('../utils/networkLoader');

// Получить баланс токенов
router.post('/get-token-balance', async (req, res) => {
  try {
    const { dleAddress, account } = req.body;
    
    if (!dleAddress || !account) {
      return res.status(400).json({
        success: false,
        error: 'Адрес DLE и адрес аккаунта обязательны'
      });
    }

    console.log(`[DLE Tokens] Получение баланса токенов для аккаунта: ${account} в DLE: ${dleAddress}`);

    // Определяем корректную сеть для данного адреса
    let rpcUrl, targetChainId;
    let candidateChainIds = []; // Будет заполнено из deploy_params
    
    try {
      // Получаем поддерживаемые сети из параметров деплоя
      const latestParams = await deployParamsService.getLatestDeployParams(1);
      if (latestParams.length > 0) {
        const params = latestParams[0];
        candidateChainIds = params.supportedChainIds || candidateChainIds;
      }
    } catch (error) {
      console.error('❌ Ошибка получения параметров деплоя, используем fallback:', error);
    }
    
    for (const cid of candidateChainIds) {
      try {
        const url = await rpcProviderService.getRpcUrlByChainId(cid);
        if (!url) continue;
        const prov = new ethers.JsonRpcProvider(url);
        const code = await prov.getCode(dleAddress);
        if (code && code !== '0x') { 
          rpcUrl = url; 
          targetChainId = cid; 
          break; 
        }
      } catch (_) {}
    }
    
    if (!rpcUrl) {
      return res.status(500).json({
        success: false,
        error: 'Не удалось найти сеть, где по адресу есть контракт'
      });
    }
    if (!rpcUrl) {
      return res.status(500).json({
        success: false,
        error: 'RPC URL для Sepolia не найден'
      });
    }

    const provider = new ethers.JsonRpcProvider(await rpcProviderService.getRpcUrlByChainId(chainId));
    
    const dleAbi = [
      "function balanceOf(address account) external view returns (uint256)"
    ];

    const dle = new ethers.Contract(dleAddress, dleAbi, provider);

    // Получаем баланс токенов
    const balance = await dle.balanceOf(account);

    console.log(`[DLE Tokens] Баланс токенов для ${account}: ${balance}`);

    res.json({
      success: true,
      data: {
        account: account,
        balance: ethers.formatUnits(balance, 18)
      }
    });

  } catch (error) {
    console.error('[DLE Tokens] Ошибка при получении баланса токенов:', error);
    res.status(500).json({
      success: false,
      error: 'Ошибка при получении баланса токенов: ' + error.message
    });
  }
});

// Получить общее предложение токенов
router.post('/get-total-supply', async (req, res) => {
  try {
    const { dleAddress } = req.body;
    
    if (!dleAddress) {
      return res.status(400).json({
        success: false,
        error: 'Адрес DLE обязателен'
      });
    }

    console.log(`[DLE Tokens] Получение общего предложения токенов для DLE: ${dleAddress}`);

    // Определяем корректную сеть для данного адреса
    let rpcUrl, targetChainId;
    let candidateChainIds = []; // Будет заполнено из deploy_params
    
    try {
      // Получаем поддерживаемые сети из параметров деплоя
      const latestParams = await deployParamsService.getLatestDeployParams(1);
      if (latestParams.length > 0) {
        const params = latestParams[0];
        candidateChainIds = params.supportedChainIds || candidateChainIds;
      }
    } catch (error) {
      console.error('❌ Ошибка получения параметров деплоя, используем fallback:', error);
    }
    
    for (const cid of candidateChainIds) {
      try {
        const url = await rpcProviderService.getRpcUrlByChainId(cid);
        if (!url) continue;
        const prov = new ethers.JsonRpcProvider(url);
        const code = await prov.getCode(dleAddress);
        if (code && code !== '0x') { 
          rpcUrl = url; 
          targetChainId = cid; 
          break; 
        }
      } catch (_) {}
    }
    
    if (!rpcUrl) {
      return res.status(500).json({
        success: false,
        error: 'Не удалось найти сеть, где по адресу есть контракт'
      });
    }
    if (!rpcUrl) {
      return res.status(500).json({
        success: false,
        error: 'RPC URL для Sepolia не найден'
      });
    }

    const provider = new ethers.JsonRpcProvider(await rpcProviderService.getRpcUrlByChainId(chainId));
    
    const dleAbi = [
      "function totalSupply() external view returns (uint256)"
    ];

    const dle = new ethers.Contract(dleAddress, dleAbi, provider);

    // Получаем общее предложение токенов
    const totalSupply = await dle.totalSupply();

    console.log(`[DLE Tokens] Общее предложение токенов: ${totalSupply}`);

    res.json({
      success: true,
      data: {
        totalSupply: ethers.formatUnits(totalSupply, 18)
      }
    });

  } catch (error) {
    console.error('[DLE Tokens] Ошибка при получении общего предложения токенов:', error);
    res.status(500).json({
      success: false,
      error: 'Ошибка при получении общего предложения токенов: ' + error.message
    });
  }
});

// Получить держателей токенов
router.post('/get-token-holders', async (req, res) => {
  try {
    const { dleAddress, offset = 0, limit = 10 } = req.body;
    
    if (!dleAddress) {
      return res.status(400).json({
        success: false,
        error: 'Адрес DLE обязателен'
      });
    }

    console.log(`[DLE Tokens] Получение держателей токенов для DLE: ${dleAddress}`);

    // Определяем корректную сеть для данного адреса
    let rpcUrl, targetChainId;
    let candidateChainIds = []; // Будет заполнено из deploy_params
    
    try {
      // Получаем поддерживаемые сети из параметров деплоя
      const latestParams = await deployParamsService.getLatestDeployParams(1);
      if (latestParams.length > 0) {
        const params = latestParams[0];
        candidateChainIds = params.supportedChainIds || candidateChainIds;
      }
    } catch (error) {
      console.error('❌ Ошибка получения параметров деплоя, используем fallback:', error);
    }
    
    for (const cid of candidateChainIds) {
      try {
        const url = await rpcProviderService.getRpcUrlByChainId(cid);
        if (!url) continue;
        const prov = new ethers.JsonRpcProvider(url);
        const code = await prov.getCode(dleAddress);
        if (code && code !== '0x') { 
          rpcUrl = url; 
          targetChainId = cid; 
          break; 
        }
      } catch (_) {}
    }
    
    if (!rpcUrl) {
      return res.status(500).json({
        success: false,
        error: 'Не удалось найти сеть, где по адресу есть контракт'
      });
    }
    if (!rpcUrl) {
      return res.status(500).json({
        success: false,
        error: 'RPC URL для Sepolia не найден'
      });
    }

    const provider = new ethers.JsonRpcProvider(await rpcProviderService.getRpcUrlByChainId(chainId));
    
    const dleAbi = [
      "function totalSupply() external view returns (uint256)",
      "function balanceOf(address account) external view returns (uint256)"
    ];

    const dle = new ethers.Contract(dleAddress, dleAbi, provider);

    // Получаем общее предложение токенов
    const totalSupply = await dle.totalSupply();
    
    // Список известных адресов для проверки
    const knownAddresses = [
      "0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B", // Создатель
      "0x15A4ed4759e5762174b300a4Cf51cc17ad967f4d", // Инициатор предложения
      "0x2F2F070AA10bD3Ea14949b9953E2040a05421B17", // Сам DLE контракт
      "0x0000000000000000000000000000000000000000"  // Нулевой адрес
    ];
    
    const holders = [];
    
    // Проверяем балансы известных адресов
    for (const address of knownAddresses) {
      try {
        const balance = await dle.balanceOf(address);
        if (balance > 0) {
          const percentage = (Number(balance) / Number(totalSupply)) * 100;
          holders.push({
            address: address,
            balance: ethers.formatUnits(balance, 18),
            percentage: percentage
          });
        }
      } catch (error) {
        console.log(`[DLE Tokens] Ошибка при получении баланса для ${address}:`, error.message);
      }
    }
    
    // Сортируем по балансу (убывание)
    holders.sort((a, b) => Number(b.balance) - Number(a.balance));
    
    // Применяем пагинацию
    const start = Number(offset);
    const end = start + Number(limit);
    const paginatedHolders = holders.slice(start, end);

    console.log(`[DLE Tokens] Найдено держателей токенов: ${holders.length}`);

    res.json({
      success: true,
      data: {
        holders: paginatedHolders,
        total: holders.length,
        offset: Number(offset),
        limit: Number(limit)
      }
    });

  } catch (error) {
    console.error('[DLE Tokens] Ошибка при получении держателей токенов:', error);
    res.status(500).json({
      success: false,
      error: 'Ошибка при получении держателей токенов: ' + error.message
    });
  }
});

module.exports = router;
