/* eslint-disable no-console */
import fs from 'node:fs';
import path from 'node:path';

import YAML from 'yaml';

const ParamsPatternMatching = [
  // ['VITE_L1_CONTRACT_ADDRESS', 'l1_contract_address'],
];

const ContractIdPattern = 'VITE_CONTRACT_ADDRESS';

const updated = [];

function isMatch(value, pattern) {
  return value.toLowerCase().includes(pattern.toLowerCase());
}

function updateValue(line, value) {
  let startIndex = line.indexOf('=') + 1;

  const startQuote = [`'`, '"'].find((quote) => line[startIndex] === quote);

  if (startQuote) {
    startIndex += 1;
  }

  const dividerIndex = line.indexOf(startQuote ?? ' ', startIndex);
  const endIndex = dividerIndex > startIndex ? dividerIndex : line.length;

  if (startIndex === 0 || endIndex === -1) {
    return line;
  }

  const addQuotes = !startQuote && typeof value === 'string' ? `'` : '';

  return line.slice(0, startIndex) + addQuotes + value + addQuotes + line.slice(endIndex);
}

function updateLine(line, parameters, index) {
  const paramPattern = ParamsPatternMatching.find(([pattern]) => isMatch(line, pattern));

  if (paramPattern) {
    const value = Object.entries(parameters.parameters.content).find(([name]) => isMatch(name, paramPattern[1]))?.[1];

    if (value !== undefined) {
      const updatedLine = updateValue(line, value);

      if (line !== updatedLine) {
        updated.push(updatedLine);
      }

      return updatedLine;
    }
  }

  if (isMatch(line, ContractIdPattern)) {
    const instances = Object.entries(index).find((template) => template[1].target_instances.length)?.[1]
      .target_instances;

    if (instances?.length) {
      const contractId = instances[0]?.instance_id;

      if (contractId !== undefined) {
        const updatedLine = updateValue(line, '0x' + contractId);

        if (line !== updatedLine) {
          updated.push(updatedLine);
        }

        return updatedLine;
      }
    }
  }

  return line;
}

function printResults() {
  updated.forEach((line) => console.log('\x1B[34m', line));
  console.log('');
  console.log('\x1b[35m%s\x1b[0m', 'Done!');
}

(function () {
  try {
    const { '--env': envFileName } = Object.fromEntries([(process.argv[2] ?? '').split('=')]);

    const profilePath = path.resolve('.env.yarn');
    const profile = fs
      .readFileSync(profilePath, 'utf-8')
      ?.split('\n')
      .find((line) => line.startsWith('REGISTRATION_PROFILE'))
      ?.split('=')[1];
    if (!profile) {
      throw new Error('"REGISTRATION_PROFILE" in .env.yarn is not defined');
    }

    const configPath = path.resolve('.cweb-config/config.yaml');
    const configFile = fs.readFileSync(configPath, 'utf8');
    const config = YAML.parse(configFile)[profile];
    if (!config) {
      throw new Error('Cannot find config for profile', profile);
    }

    const indexPath = path.resolve(config.pathToLockIndexFile);
    const indexFile = fs.readFileSync(indexPath, 'utf8');
    const index = YAML.parse(indexFile)?.contract_templates;

    if (!index) {
      throw new Error('Cannot find lockfile or contract instances', profile);
    }

    const parametersPath = path.resolve(config.pathToIndexFile);
    const parametersFile = fs.readFileSync(parametersPath, 'utf8');
    const parameters = YAML.parse(parametersFile)?.contract_instances;
    if (!parameters) {
      throw new Error('Cannot find config for profile', profile);
    }

    const envFilePath = path.resolve('packages/ui', envFileName);

    const env = fs.readFileSync(envFilePath, 'utf-8');
    if (!env) {
      console.error('Env file is not found in', envFilePath);
      process.exit(2);
    }

    const updatedEnv = env
      .split('\n')
      .map((line) => updateLine(line, parameters, index))
      .join('\n');

    fs.writeFileSync(envFilePath, updatedEnv, 'utf-8');

    printResults();
  } catch (error) {
    console.log('\x1b[31m%s\x1b[0m', error.message);
    process.exit(2);
  }
})();
