import { readFileSync, existsSync } from 'fs';
import { resolve } from 'path';
import { Contract, JsonRpcProvider } from 'ethers';
import { runTripleStateReconcile } from './omnl-triple-reconcile';
import { getWeb3ComplianceSummary } from './omnl-web3-compliance';
import { getComplianceSignoffsSummary } from './omnl-ifrs-disclosures';
import { omnlReserveStore138 } from './omnl-chain138-addresses';
import { buildSafeNotaryGateTransaction } from './omnl-safe-notary-gate-tx';

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

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

const RESERVE_GATE_ABI = [
  'function requireNotarizedEvidence() view returns (bool)',
  'function notaryRegistry() view returns (address)',
  'function attestationThreshold() view returns (uint256)',
];

export interface ComplianceConsolePendingAction {
  id: string;
  severity: 'critical' | 'high' | 'medium' | 'low';
  title: string;
  detail: string;
  actionType: 'safe_multisig' | 'external_pr' | 'operator_cli' | 'key_custody';
  links?: Array<{ label: string; href: string }>;
}

export interface ComplianceConsoleSnapshot {
  generatedAt: string;
  lineId: string;
  posture: {
    reportingCompliant: boolean | null;
    attestationStale: boolean | null;
    tripleAligned: boolean | null;
    requireNotarizedEvidence: boolean | null;
    notaryThreshold: number | null;
    reserveAttestationThreshold: number | null;
    jurisdictionPolicyVersion: number | null;
    complianceThreshold: string;
  };
  pendingActions: ComplianceConsolePendingAction[];
  tripleReconcile: Awaited<ReturnType<typeof runTripleStateReconcile>> | null;
  web3: ReturnType<typeof getWeb3ComplianceSummary>;
  signoffs: ReturnType<typeof getComplianceSignoffsSummary>;
  onChainGate: {
    reserveStore: string | null;
    requireNotarizedEvidence: boolean | null;
    notaryRegistry: string | null;
    attestationThreshold: string | null;
    rpcReachable: boolean;
    error?: string;
  };
  proofReport: {
    status: string;
    complianceThreshold: string;
    evidenceHash?: string;
    merkleRoot?: string;
    packageNotarized3of3?: boolean;
    reserveAttested3of3?: boolean;
    gnosisSafe?: { address: string; threshold: number; owners: number };
  } | null;
  safeWallet: {
    status: string;
    npmRegistryHas138: boolean;
    upstreamPr: string;
    manualSetupRequired: boolean;
  } | null;
  externalVisibility: {
    defiLlama: { chainPage: string; pr12094: string; pr19451: string; note: string };
    safeDeployments: { pr1568: string; note: string };
  };
  explorerBase: string;
}

async function fetchReserveGateStatus(): Promise<ComplianceConsoleSnapshot['onChainGate']> {
  const deployed = readOptionalJson<{ contracts?: { ReserveCommitmentStore?: string } }>(
    'config/compliance/web3-multisig-deployed.v1.json'
  );
  const store = omnlReserveStore138() || deployed?.contracts?.ReserveCommitmentStore || null;
  const rpc = (process.env.RPC_URL_138 || process.env.RPC_URL || '').trim();
  if (!store || !rpc) {
    return {
      reserveStore: store,
      requireNotarizedEvidence: null,
      notaryRegistry: null,
      attestationThreshold: null,
      rpcReachable: false,
      error: 'Set RPC_URL_138 and OMNL_RESERVE_COMMITMENT_STORE (or v2 env)',
    };
  }
  try {
    const provider = new JsonRpcProvider(rpc, 138, { staticNetwork: true });
    const c = new Contract(store, RESERVE_GATE_ABI, provider);
    const [req, reg, th] = await Promise.all([
      c.requireNotarizedEvidence() as Promise<boolean>,
      c.notaryRegistry() as Promise<string>,
      c.attestationThreshold() as Promise<bigint>,
    ]);
    return {
      reserveStore: store,
      requireNotarizedEvidence: req,
      notaryRegistry: reg,
      attestationThreshold: th.toString(),
      rpcReachable: true,
    };
  } catch (e) {
    return {
      reserveStore: store,
      requireNotarizedEvidence: null,
      notaryRegistry: null,
      attestationThreshold: null,
      rpcReachable: false,
      error: e instanceof Error ? e.message : String(e),
    };
  }
}

function buildPendingActions(
  gate: ComplianceConsoleSnapshot['onChainGate'],
  safeWallet: ComplianceConsoleSnapshot['safeWallet']
): ComplianceConsolePendingAction[] {
  const actions: ComplianceConsolePendingAction[] = [];

  if (gate.requireNotarizedEvidence === false) {
    actions.push({
      id: 'enable-notary-gate',
      severity: 'high',
      title: 'Enable requireNotarizedEvidence on reserve store',
      detail:
        'Reserve store v2 has notaryRegistry set but requireNotarizedEvidence is false. Execute via OMNL Gnosis Safe (3-of-5).',
      actionType: 'safe_multisig',
      links: [
        { label: 'Download Safe tx JSON', href: '/omnl/compliance/safe-notary-gate-tx' },
        { label: 'Safe Wallet', href: 'https://app.safe.global/' },
        { label: 'Reserve store on explorer', href: `https://explorer.d-bis.org/address/${gate.reserveStore}` },
      ],
    });
  }

  if (safeWallet && !safeWallet.npmRegistryHas138) {
    actions.push({
      id: 'safe-wallet-chain138',
      severity: 'medium',
      title: 'Safe Wallet — await chain 138 npm registry',
      detail: 'Use manual singleton addresses until safe-global/safe-deployments PR merges.',
      actionType: 'external_pr',
      links: [
        { label: 'Upstream PR #1568', href: safeWallet.upstreamPr },
        { label: 'GnosisSafeProxyFactory', href: 'https://explorer.d-bis.org/address/0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2' },
      ],
    });
  }

  actions.push({
    id: 'defillama-pricing',
    severity: 'medium',
    title: 'DefiLlama hub token USD pricing',
    detail: 'Chain page may show $0 TVL until defillama-server #12094 merges.',
    actionType: 'external_pr',
    links: [
      { label: 'defillama-server #12094', href: 'https://github.com/DefiLlama/defillama-server/pull/12094' },
      { label: 'Chain page', href: 'https://defillama.com/chain/defi-oracle-meta' },
      { label: 'Bridge TVL PR #19451', href: 'https://github.com/DefiLlama/DefiLlama-Adapters/pull/19451' },
    ],
  });

  actions.push({
    id: 'rotate-signer-keys',
    severity: 'low',
    title: 'Rotate notary/attestation signer keys to HSM',
    detail: 'Cold signer keys should not remain on operator workstations.',
    actionType: 'key_custody',
      links: [{ label: 'Verify on-chain', href: '/omnl/compliance/web3' }],
  });

  return actions;
}

export async function buildComplianceConsoleSnapshot(
  lineId?: string
): Promise<ComplianceConsoleSnapshot> {
  const defaultLine =
    lineId?.trim() ||
    process.env.OMNL_HEALTH_LINE_ID?.trim() ||
    '0xfefb7411285a639b00be06bbffe897eb802ee817983aa57facf5bde6a1b52ff4';

  const [tripleReconcile, onChainGate] = await Promise.all([
    runTripleStateReconcile(defaultLine).catch(() => null),
    fetchReserveGateStatus(),
  ]);

  const proofRaw = readOptionalJson<{
    status: string;
    complianceThreshold: string;
    onChain?: {
      evidenceHash?: string;
      merkleRoot?: string;
      packageNotarized3of3?: boolean;
      reserveAttested3of3?: boolean;
      jurisdictionPolicyVersion?: number;
      notaryThreshold?: number;
      reserveAttestationThreshold?: number;
      gnosisSafe?: { address: string; threshold: number; owners: number };
    };
  }>('reports/status/hybx-offchain-onchain-cryptographic-proof-latest.json');

  const safeWalletRaw = readOptionalJson<{
    status: string;
    npmRegistryHas138: boolean;
    upstreamPr: string;
    manualSetupRequired: boolean;
  }>('reports/status/safe-wallet-chain138-readiness-latest.json');

  const proofReport = proofRaw
    ? {
        status: proofRaw.status,
        complianceThreshold: proofRaw.complianceThreshold,
        evidenceHash: proofRaw.onChain?.evidenceHash,
        merkleRoot: proofRaw.onChain?.merkleRoot,
        packageNotarized3of3: proofRaw.onChain?.packageNotarized3of3,
        reserveAttested3of3: proofRaw.onChain?.reserveAttested3of3,
        gnosisSafe: proofRaw.onChain?.gnosisSafe,
      }
    : null;

  const safeWallet = safeWalletRaw
    ? {
        status: safeWalletRaw.status,
        npmRegistryHas138: safeWalletRaw.npmRegistryHas138,
        upstreamPr: safeWalletRaw.upstreamPr,
        manualSetupRequired: safeWalletRaw.manualSetupRequired,
      }
    : null;

  const posture = {
    reportingCompliant: tripleReconcile?.onChain?.reportingCompliant ?? null,
    attestationStale: tripleReconcile?.onChain?.attestationStale ?? null,
    tripleAligned: tripleReconcile?.aligned ?? null,
    requireNotarizedEvidence: onChainGate.requireNotarizedEvidence,
    notaryThreshold: proofRaw?.onChain?.notaryThreshold ?? null,
    reserveAttestationThreshold: proofRaw?.onChain?.reserveAttestationThreshold ?? null,
    jurisdictionPolicyVersion: proofRaw?.onChain?.jurisdictionPolicyVersion ?? null,
    complianceThreshold: proofRaw?.complianceThreshold ?? '3-of-3',
  };

  return {
    generatedAt: new Date().toISOString(),
    lineId: defaultLine,
    posture,
    pendingActions: buildPendingActions(onChainGate, safeWallet),
    tripleReconcile,
    web3: getWeb3ComplianceSummary(),
    signoffs: getComplianceSignoffsSummary(),
    onChainGate,
    proofReport,
    safeWallet,
    externalVisibility: {
      defiLlama: {
        chainPage: 'https://defillama.com/chain/defi-oracle-meta',
        pr12094: 'https://github.com/DefiLlama/defillama-server/pull/12094',
        pr19451: 'https://github.com/DefiLlama/DefiLlama-Adapters/pull/19451',
        note: 'TVL USD blocked on server pricing merge',
      },
      safeDeployments: {
        pr1568: 'https://github.com/safe-global/safe-deployments/pull/1568',
        note: 'Safe Wallet npm registry for chain 138',
      },
    },
    explorerBase: process.env.EXPLORER_PUBLIC_URL?.trim() || 'https://explorer.d-bis.org',
  };
}
