import { readFileSync, existsSync } from 'fs';
import { resolve } from 'path';
import { Interface } from 'ethers';
import { jurisdictionIdBytes32, matrixControlIdBytes32 } from './omnl-web3-compliance';

function projectRoot(): string {
  return (
    process.env.PROXMOX_ROOT?.trim() ||
    process.env.PHOENIX_REPO_ROOT?.trim() ||
    resolve(__dirname, '../../../../../..')
  );
}

function readJson<T>(rel: string): T | null {
  const p = resolve(projectRoot(), rel);
  if (!existsSync(p)) return null;
  return JSON.parse(readFileSync(p, 'utf8')) as T;
}

export interface SafeNotaryGateTransaction {
  schemaVersion: string;
  chainId: number;
  safeAddress: string;
  threshold: number;
  owners: string[];
  description: string;
  transactions: Array<{
    to: string;
    value: string;
    data: string;
    contractMethod: { name: string; inputs: Array<{ name: string; type: string }> };
    contractInputsValues: Record<string, string>;
  }>;
  safeTransactionBuilder: Record<string, unknown>;
}

/** Gnosis Safe Transaction Builder JSON — enable requireNotarizedEvidence on ReserveCommitmentStore v2. */
export function buildSafeNotaryGateTransaction(): SafeNotaryGateTransaction | null {
  const web3Cfg = readJson<{ contracts: Record<string, string> }>(
    'config/compliance/web3-multisig-deployed.v1.json'
  );
  const safeCfg = readJson<{
    omnlAdminSafe: { threshold: number; owners: string[] };
  }>('config/compliance/gnosis-safe-chain138-deployed.v1.json');

  if (!web3Cfg?.contracts || !safeCfg?.omnlAdminSafe) return null;

  const safe = web3Cfg.contracts.GnosisSafeAdmin;
  const store = web3Cfg.contracts.ReserveCommitmentStore;
  const notary = web3Cfg.contracts.OMNLNotaryRegistry;
  if (!safe || !store || !notary) return null;

  const jurId = process.env.OMNL_JURISDICTION_ID || 'ID';
  const matrixId = process.env.OMNL_MATRIX_CONTROL_ID || 'ID-OMNL-001';
  const jurBytes = jurisdictionIdBytes32(jurId);
  const matrixBytes = matrixControlIdBytes32(matrixId);

  const iface = new Interface([
    'function configureNotaryGate(address registry, bool required, bytes32 jurisdictionId, bytes32 matrixControlId)',
  ]);
  const data = iface.encodeFunctionData('configureNotaryGate', [notary, true, jurBytes, matrixBytes]);

  const contractInputsValues = {
    registry: notary,
    required: 'true',
    jurisdictionId: jurBytes,
    matrixControlId: matrixBytes,
  };

  return {
    schemaVersion: '1.0.0',
    chainId: 138,
    safeAddress: safe,
    threshold: safeCfg.omnlAdminSafe.threshold,
    owners: safeCfg.omnlAdminSafe.owners,
    description:
      'Enable requireNotarizedEvidence on ReserveCommitmentStore v2 (3-of-3 notary + attestation already live).',
    transactions: [
      {
        to: store,
        value: '0',
        data,
        contractMethod: {
          name: 'configureNotaryGate',
          inputs: [
            { name: 'registry', type: 'address' },
            { name: 'required', type: 'bool' },
            { name: 'jurisdictionId', type: 'bytes32' },
            { name: 'matrixControlId', type: 'bytes32' },
          ],
        },
        contractInputsValues,
      },
    ],
    safeTransactionBuilder: {
      version: '1.0',
      chainId: '138',
      createdAt: Date.now(),
      meta: {
        name: 'OMNL Wire Notary Gate',
        description: 'Set requireNotarizedEvidence=true on ReserveCommitmentStore',
        txBuilderVersion: '1.16.5',
      },
      transactions: [
        {
          to: store,
          value: '0',
          data: null,
          contractMethod: {
            inputs: [
              { internalType: 'address', name: 'registry', type: 'address' },
              { internalType: 'bool', name: 'required', type: 'bool' },
              { internalType: 'bytes32', name: 'jurisdictionId', type: 'bytes32' },
              { internalType: 'bytes32', name: 'matrixControlId', type: 'bytes32' },
            ],
            name: 'configureNotaryGate',
            payable: false,
          },
          contractInputsValues,
        },
      ],
    },
  };
}
