/**
 * Receipt Partner Authority Gateway — complete synthetic sandbox quickstart.
 * Test and Live are operating modes, not separate products. Test mode currently
 * includes the Reference Economic Action profile, and Live access is available
 * by request. Code-first custom Action Profiles and the Standard Action Library
 * are coming next.
 * No real provider, credential, money movement, or financial action is used.
 */
import {
  ReceiptPartnerClient,
  verifySignedArtifact,
  type ReferenceEconomicAction,
} from "@receiptprotocol/partner-sdk";
import {
  ReceiptAuthorityGate,
  type Ed25519PublicJwk,
  type SignedExecutionAdmission,
} from "@receiptprotocol/gate-sdk";
import { readFile, unlink, writeFile } from "node:fs/promises";
import { createServer } from "node:http";
import { resolve } from "node:path";

const required = (name: string) => {
  const value = process.env[name];
  if (!value) throw new Error(`missing_environment:${name}`);
  return value;
};
const optional = (name: string) => process.env[name]?.trim() || undefined;
const baseUrl = required("RECEIPT_PARTNER_BASE_URL");
const partnerKey = required("RECEIPT_PARTNER_KEY");
const partnerReference = required("RECEIPT_PARTNER_REFERENCE");
const receipt = new ReceiptPartnerClient({ baseUrl, partnerKey });
const now = Date.now();
const mandateReference = optional("RECEIPT_MANDATE_REFERENCE");

if (!mandateReference) {
  const redirectUri = new URL(required("RECEIPT_REDIRECT_URI"));
  const partnerStateReference = crypto.randomUUID();
  if (
    redirectUri.protocol !== "http:" ||
    !["127.0.0.1", "localhost"].includes(redirectUri.hostname)
  ) {
    throw new Error("quickstart_callback_requires_localhost_http");
  }
  const callback = new Promise<void>((resolveCallback, rejectCallback) => {
    const server = createServer((request, response) => {
      const callbackUrl = new URL(request.url ?? "/", redirectUri);
      if (callbackUrl.pathname !== redirectUri.pathname) {
        response.writeHead(404).end("Not found");
        return;
      }
      const result = callbackUrl.searchParams.get("result");
      if (callbackUrl.searchParams.get("state") !== partnerStateReference) {
        response.writeHead(400).end("Callback state mismatch");
        server.close(() => rejectCallback(new Error("mandate_callback_state_mismatch")));
        return;
      }
      if (result !== "authorized") {
        response.writeHead(400, { "content-type": "text/plain" }).end(`Receipt result: ${result}`);
        server.close(() => rejectCallback(new Error(`mandate_${result ?? "callback_invalid"}`)));
        return;
      }
      const values = {
        RECEIPT_PRINCIPAL_REFERENCE: callbackUrl.searchParams.get("principal_reference"),
        RECEIPT_AGENT_CONNECTION_REFERENCE: callbackUrl.searchParams.get(
          "agent_connection_reference",
        ),
        RECEIPT_MANDATE_REFERENCE: callbackUrl.searchParams.get("mandate_reference"),
        RECEIPT_MANDATE_VERSION: callbackUrl.searchParams.get("mandate_version"),
      };
      if (Object.values(values).some((value) => !value)) {
        response.writeHead(400).end("Callback bindings missing");
        server.close(() => rejectCallback(new Error("mandate_callback_bindings_missing")));
        return;
      }
      response
        .writeHead(200, { "content-type": "text/plain" })
        .end(
          "Mandate activated. Return to the terminal and add the printed bindings to your environment.",
        );
      console.log(
        Object.entries(values)
          .map(([key, value]) => `${key}=${value}`)
          .join("\n"),
      );
      server.close(() => resolveCallback());
    });
    server.once("error", rejectCallback);
    server.listen(Number(redirectUri.port || 80), redirectUri.hostname);
  });
  const intent = await receipt.createMandateIntent({
    partner_reference: partnerReference,
    agent_display_name: "Synthetic quickstart agent",
    action_profile_reference: "reference_economic_action.v1",
    action_profile_version: 1,
    redirect_uri: redirectUri.toString(),
    partner_state_reference: partnerStateReference,
    terms: {
      provider_refs: ["provider:synthetic"],
      counterparty_refs: ["counterparty:synthetic"],
      currency_codes: ["CAD"],
      resource_refs: ["resource:synthetic"],
      daily_limit_minor: 10_000,
      per_action_limit_minor: 2_500,
      evidence_requirement_ids: ["synthetic.delivery.receipt"],
      effective_at: new Date(now).toISOString(),
      expires_at: new Date(now + 24 * 60 * 60 * 1_000).toISOString(),
    },
  });
  console.log(
    JSON.stringify(
      {
        next: "Open hosted_review_url. This process is waiting on the localhost callback and will print the opaque bindings after authorization.",
        hosted_review_url: intent.hosted_review_url,
        intent_reference: intent.intent_reference,
      },
      null,
      2,
    ),
  );
  await callback;
} else {
  const principalReference = required("RECEIPT_PRINCIPAL_REFERENCE");
  const agentConnectionReference = required("RECEIPT_AGENT_CONNECTION_REFERENCE");
  const mandateVersion = Number(required("RECEIPT_MANDATE_VERSION"));
  if (!Number.isSafeInteger(mandateVersion) || mandateVersion < 1) {
    throw new Error("invalid_environment:RECEIPT_MANDATE_VERSION");
  }
  const signingKeys = await receipt.getSigningKeys();
  const trustedAdmissionKeys = Object.fromEntries(
    signingKeys.keys
      .filter((key) => key.environment === "sandbox" && key.purpose === "execution_admission")
      .map((key) => [key.key_id, key.public_jwk as Ed25519PublicJwk]),
  );
  const gate = new ReceiptAuthorityGate({
    authorityBaseUrl: baseUrl,
    partnerKey,
    partnerReference,
    environment: "sandbox",
    agentConnectionReference,
    trustedAdmissionKeys,
  });
  const action = (
    label: string,
    overrides: Partial<ReferenceEconomicAction> = {},
  ): ReferenceEconomicAction => {
    const occurrence = `${label}-${crypto.randomUUID()}`;
    return {
      action_kind: "synthetic.deliver",
      counterparty_ref: "counterparty:synthetic",
      amount_minor: 100,
      currency: "CAD",
      execution_provider_ref: "provider:synthetic",
      resource_ref: "resource:synthetic",
      occurrence_id: occurrence,
      idempotency_key: `action:${occurrence}`,
      action_expires_at: new Date(Date.now() + 10 * 60_000).toISOString(),
      ...overrides,
    };
  };
  const propose = async (candidate: ReferenceEconomicAction) => {
    const proposal = await receipt.createProposal({
      partner_reference: partnerReference,
      principal_reference: principalReference,
      agent_connection_reference: agentConnectionReference,
      mandate_reference: mandateReference,
      expected_mandate_version: mandateVersion,
      action_profile_reference: "reference_economic_action.v1",
      action_profile_version: 1,
      proposed_action: candidate,
      occurrence_id: candidate.occurrence_id,
      idempotency_key: `proposal:${candidate.occurrence_id}`,
      proposal_expires_at: candidate.action_expires_at,
    });
    const verified = await verifySignedArtifact({
      artifact: proposal.decision_record,
      expectedEnvironment: "sandbox",
      expectedPurpose: "policy_decision",
      signingKeys: signingKeys.keys,
    });
    if (!verified) throw new Error("policy_decision_signature_invalid");
    return proposal;
  };
  const executeSynthetic = async (
    candidate: ReferenceEconomicAction,
    admission: unknown,
    outcome: "complete" | "indeterminate",
  ) =>
    gate.executeOnce({
      admission: admission as SignedExecutionAdmission,
      action: candidate,
      providerReference: "provider:synthetic",
      invoke: async () => ({
        synthetic: true,
        provider_called: false,
        effect_known: outcome === "complete",
      }),
      classifyResult: (result) => ({ event_type: outcome, report: result }),
    });

  const statePath = resolve(
    process.cwd(),
    optional("RECEIPT_QUICKSTART_STATE_FILE") ?? ".receipt-quickstart-state.json",
  );
  type ApprovalState = {
    phase: "candidate" | "pending";
    approval_action: ReferenceEconomicAction;
    approval_url?: string;
  };
  let approvalState: ApprovalState | null = null;
  try {
    approvalState = JSON.parse(await readFile(statePath, "utf8")) as ApprovalState;
    if (!approvalState.approval_action || !["candidate", "pending"].includes(approvalState.phase)) {
      throw new Error("quickstart_state_invalid");
    }
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
  }

  if (approvalState) {
    const continued = await propose(approvalState.approval_action);
    if (continued.policy_decision === "approval_required") {
      const approvalUrl = approvalState.approval_url ?? continued.approval?.approval_url;
      if (!approvalUrl) throw new Error("approval_url_unavailable");
      await writeFile(
        statePath,
        `${JSON.stringify({ ...approvalState, phase: "pending", approval_url: approvalUrl }, null, 2)}\n`,
        { mode: 0o600 },
      );
      console.log(
        JSON.stringify(
          {
            approval_required: approvalUrl,
            state_file: statePath,
            next: "Open approval_required, approve this exact action, then rerun. The same persisted material action and idempotency identity will be replayed.",
          },
          null,
          2,
        ),
      );
    } else if (
      approvalState.phase === "pending" &&
      continued.policy_decision === "permitted" &&
      continued.execution_admission
    ) {
      const executed = await executeSynthetic(
        approvalState.approval_action,
        continued.execution_admission,
        "complete",
      );
      await unlink(statePath);
      console.log(
        JSON.stringify(
          { approval_required: true, exact_action_approved: true, state_removed: true, executed },
          null,
          2,
        ),
      );
    } else {
      throw new Error(`approval_continuation_failed:${continued.policy_decision}`);
    }
  } else if (optional("RECEIPT_APPROVAL_READY") === "true") {
    const approvalAction = action("approval-check");
    await writeFile(
      statePath,
      `${JSON.stringify({ phase: "candidate", approval_action: approvalAction }, null, 2)}\n`,
      {
        mode: 0o600,
        flag: "wx",
      },
    );
    const approvalCandidate = await propose(approvalAction);
    if (approvalCandidate.policy_decision !== "approval_required") {
      await unlink(statePath);
      throw new Error(
        `expected_approval_required:${approvalCandidate.policy_decision}; enable fresh approval in the Receipt mandate centre first`,
      );
    }
    const approvalUrl = approvalCandidate.approval?.approval_url;
    if (!approvalUrl) {
      await unlink(statePath);
      throw new Error("approval_url_unavailable");
    }
    await writeFile(
      statePath,
      `${JSON.stringify(
        { phase: "pending", approval_action: approvalAction, approval_url: approvalUrl },
        null,
        2,
      )}\n`,
      { mode: 0o600 },
    );
    console.log(
      JSON.stringify(
        {
          approval_required: approvalUrl,
          state_file: statePath,
          next: "Approve once in the hosted page, then rerun. Approval creates no standing authority.",
        },
        null,
        2,
      ),
    );
  } else {
    const permittedAction = action("permitted");
    const permitted = await propose(permittedAction);
    if (permitted.policy_decision !== "permitted" || !permitted.execution_admission) {
      throw new Error(`expected_permitted:${permitted.policy_decision}`);
    }
    const executed = await executeSynthetic(
      permittedAction,
      permitted.execution_admission,
      "complete",
    );

    const denied = await propose(
      action("denied", { counterparty_ref: "counterparty:not-authorized" }),
    );
    if (denied.policy_decision !== "denied") {
      throw new Error(`expected_denied:${denied.policy_decision}`);
    }

    const uncertainAction = action("indeterminate");
    const uncertain = await propose(uncertainAction);
    if (uncertain.policy_decision !== "permitted" || !uncertain.execution_admission) {
      throw new Error(`expected_indeterminate_admission:${uncertain.policy_decision}`);
    }
    const uncertainExecution = await executeSynthetic(
      uncertainAction,
      uncertain.execution_admission,
      "indeterminate",
    );
    const reconciliation = await gate.reconcile({
      executionReference: uncertainExecution.executionReference,
      outcome: "confirmed_no_effect",
      evidence: { synthetic: true, provider_called: false },
      idempotencyKey: `reconcile:${uncertainExecution.occurrenceId}`,
    });
    console.log(
      JSON.stringify(
        {
          permitted: true,
          denied: denied.policy_decision,
          execution: executed,
          reconciliation,
          next: "In the Receipt mandate centre, choose ‘Require approval for every action’, then rerun with RECEIPT_APPROVAL_READY=true.",
        },
        null,
        2,
      ),
    );
  }
}
