// Скрипт для ручного создания DLE без использования фабрики
const { ethers } = require("hardhat");
const fs = require("fs");
const path = require("path");

async function main() {
  // Получаем параметры деплоя из файла или аргументов
  const deployParams = getDeployParams();
  
  console.log("Начинаем создание нового DLE вручную (без фабрики)...");
  console.log("Параметры DLE:");
  console.log(JSON.stringify(deployParams, null, 2));

  // Получаем аккаунт деплоя
  const [deployer] = await ethers.getSigners();
  console.log(`Адрес деплоера: ${deployer.address}`);
  console.log(`Баланс деплоера: ${ethers.formatEther(await deployer.provider.getBalance(deployer.address))} ETH`);

  try {
    // 1. Создаем токен управления
    console.log("\n1. Деплой токена управления...");
    const GovernanceToken = await ethers.getContractFactory("GovernanceToken");
    const token = await GovernanceToken.deploy(
      deployParams.name, 
      deployParams.symbol,
      deployer.address // адрес управляющего минтом
    );
    await token.waitForDeployment();
    const tokenAddress = await token.getAddress();
    console.log(`Токен задеплоен по адресу: ${tokenAddress}`);

    // 2. Создаем Timelock контракт
    console.log("\n2. Деплой Timelock контракта...");
    
    // Создаем временные пустые массивы
    const proposers = [deployer.address]; // Временно даем права деплоеру
    const executors = [ethers.ZeroAddress]; // Адрес 0 означает, что любой может выполнять
    
    // Минимальная задержка в секундах
    const minDelayInSeconds = deployParams.minTimelockDelay * 24 * 60 * 60; // Перевод дней в секунды
    
    const GovernanceTimelock = await ethers.getContractFactory("GovernanceTimelock");
    const timelock = await GovernanceTimelock.deploy(
      minDelayInSeconds,
      proposers,
      executors,
      deployer.address // admin
    );
    await timelock.waitForDeployment();
    const timelockAddress = await timelock.getAddress();
    console.log(`Timelock задеплоен по адресу: ${timelockAddress}`);

    // 3. Создаем Governor контракт
    console.log("\n3. Деплой Governor контракта...");
    const GovernorContract = await ethers.getContractFactory("GovernorContract");
    const governor = await GovernorContract.deploy(
      `${deployParams.name} Governor`,
      token,
      timelock,
      deployParams.votingDelay,
      deployParams.votingPeriod,
      deployParams.proposalThreshold,
      deployParams.quorumPercentage
    );
    await governor.waitForDeployment();
    const governorAddress = await governor.getAddress();
    console.log(`Governor задеплоен по адресу: ${governorAddress}`);

    // 4. Настраиваем разрешения Timelock
    console.log("\n4. Настройка разрешений Timelock...");
    
    // Отменяем временные предложения
    const tx1 = await timelock.revokeRole(await timelock.PROPOSER_ROLE(), deployer.address);
    await tx1.wait();
    console.log(`Отозвана роль PROPOSER у деплоера`);
    
    // Устанавливаем Governor как единственного proposer
    const tx2 = await timelock.grantRole(await timelock.PROPOSER_ROLE(), governorAddress);
    await tx2.wait();
    console.log(`Назначена роль PROPOSER контракту Governor`);
    
    // Отказываемся от роли администратора для Timelock
    const adminRole = await timelock.DEFAULT_ADMIN_ROLE();
    const tx3 = await timelock.revokeRole(adminRole, deployer.address);
    await tx3.wait();
    console.log(`Отозвана роль ADMIN у деплоера`);

    // 5. Распределяем начальные токены
    console.log("\n5. Распределение начальных токенов...");
    const mintTx = await token.mintInitialSupply(deployParams.partners, deployParams.amounts);
    await mintTx.wait();
    console.log(`Токены распределены между партнерами`);

    // 6. Сохраняем информацию о созданных контрактах
    console.log("\n6. Сохранение информации о DLE...");
    const dleData = {
      name: deployParams.name,
      symbol: deployParams.symbol,
      location: deployParams.location,
      isicCodes: deployParams.isicCodes,
      tokenAddress,
      timelockAddress,
      governorAddress,
      creationBlock: (await mintTx.provider.getBlockNumber()),
      creationTimestamp: (await mintTx.provider.getBlock()).timestamp,
      deployedManually: true
    };
    
    const saveResult = saveDLEData(dleData);
    
    console.log("\nDLE успешно создано вручную!");
    console.log(`Адрес токена: ${tokenAddress}`);
    console.log(`Адрес таймлока: ${timelockAddress}`);
    console.log(`Адрес контракта Governor: ${governorAddress}`);
    
    if (!saveResult) {
      console.warn("\nВНИМАНИЕ: Не удалось сохранить информацию о DLE в файл!");
      console.warn("Убедитесь, что директория contracts-data/dles существует и доступна для записи.");
      console.warn("Данные контрактов доступны выше в логах.");
    }

    return dleData;
  } catch (error) {
    console.error("Ошибка при создании DLE вручную:", error);
    throw error;
  }
}

// Получаем параметры деплоя из JSON-файла (переданного как аргумент)
function getDeployParams() {
  const defaultParamsPath = path.join(__dirname, 'current-params.json');
  
  if (fs.existsSync(defaultParamsPath)) {
    console.log(`Загрузка параметров из файла: ${defaultParamsPath}`);
    return JSON.parse(fs.readFileSync(defaultParamsPath, "utf8"));
  }
  
  // Используем параметры по умолчанию, если файл не найден
  console.log("Используются параметры по умолчанию");
  return {
    name: "Manual DLE",
    symbol: "MDLE",
    location: "Test Location",
    isicCodes: ["A01", "B02"],
    partners: [
      "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
      "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
    ],
    amounts: [
      ethers.parseEther("1000000"),
      ethers.parseEther("500000")
    ],
    minTimelockDelay: 2,
    votingDelay: 1,
    votingPeriod: 45818,
    proposalThreshold: ethers.parseEther("100000"),
    quorumPercentage: 4
  };
}

// Сохраняем информацию о созданном DLE
function saveDLEData(dleData) {
  const dlesDir = path.join(__dirname, "../../contracts-data/dles");
  
  // Проверяем существование директории и создаем при необходимости
  try {
    if (!fs.existsSync(dlesDir)) {
      console.log(`Директория ${dlesDir} не существует, создаю...`);
      fs.mkdirSync(dlesDir, { recursive: true });
      console.log(`Директория ${dlesDir} успешно создана`);
    }
    
    // Проверяем права на запись, создавая временный файл
    const testFile = path.join(dlesDir, '.write-test');
    fs.writeFileSync(testFile, 'test');
    fs.unlinkSync(testFile);
    console.log(`Директория ${dlesDir} доступна для записи`);
    
    const fileName = `${dleData.name.replace(/\s+/g, '-')}-${Date.now()}.json`;
    const filePath = path.join(dlesDir, fileName);
    fs.writeFileSync(filePath, JSON.stringify(dleData, null, 2));
    
    console.log(`Информация о DLE сохранена в файл: ${fileName}`);
    return true;
  } catch (error) {
    console.error(`Ошибка при сохранении информации о DLE: ${error.message}`);
    console.error(`Убедитесь, что директория ${dlesDir} существует и доступна для записи`);
    console.error(`Для исправления в Docker-контейнере выполните: docker exec -it [container_id] /bin/sh -c "mkdir -p /app/contracts-data/dles && chown -R node:node /app/contracts-data"`);
    return false;
  }
}

// Если скрипт выполняется напрямую
if (require.main === module) {
  main()
    .then(() => process.exit(0))
    .catch((error) => {
      console.error(error);
      process.exit(1);
    });
} else {
  // Если скрипт импортируется как модуль
  module.exports = main;
} 