/**
 * Wallet module — multichain Safe wallet visualization.
 *
 * Client-side only (no DB). Queries Safe Global API for balances,
 * transfers, and multisig data across multiple chains.
 */

import { Hono } from "hono";
import { renderShell } from "../../server/shell";
import { getModuleInfoList } from "../../shared/module";
import type { RSpaceModule } from "../../shared/module";
import { renderLanding } from "./landing";

const routes = new Hono();

// ── Proxy Safe Global API (avoid CORS issues from browser) ──
routes.get("/api/safe/:chainId/:address/balances", async (c) => {
	const chainId = c.req.param("chainId");
	const address = c.req.param("address");
	const chainPrefix = getSafePrefix(chainId);
	if (!chainPrefix) return c.json({ error: "Unsupported chain" }, 400);

	const res = await fetch(`https://safe-transaction-${chainPrefix}.safe.global/api/v1/safes/${address}/balances/usd/?trusted=true&exclude_spam=true`);
	if (!res.ok) return c.json({ error: "Safe API error" }, res.status as any);
	const data = await res.json();
	c.header("Cache-Control", "public, max-age=30");
	return c.json(data);
});

routes.get("/api/safe/:chainId/:address/transfers", async (c) => {
	const chainId = c.req.param("chainId");
	const address = c.req.param("address");
	const chainPrefix = getSafePrefix(chainId);
	if (!chainPrefix) return c.json({ error: "Unsupported chain" }, 400);

	const limit = c.req.query("limit") || "100";
	const res = await fetch(`https://safe-transaction-${chainPrefix}.safe.global/api/v1/safes/${address}/all-transactions/?limit=${limit}&executed=true`);
	if (!res.ok) return c.json({ error: "Safe API error" }, res.status as any);
	return c.json(await res.json());
});

routes.get("/api/safe/:chainId/:address/info", async (c) => {
	const chainId = c.req.param("chainId");
	const address = c.req.param("address");
	const chainPrefix = getSafePrefix(chainId);
	if (!chainPrefix) return c.json({ error: "Unsupported chain" }, 400);

	const res = await fetch(`https://safe-transaction-${chainPrefix}.safe.global/api/v1/safes/${address}/`);
	if (!res.ok) return c.json({ error: "Safe API error" }, res.status as any);
	const data = await res.json();
	c.header("Cache-Control", "public, max-age=300");
	return c.json(data);
});

// Detect which chains have a Safe for this address
routes.get("/api/safe/detect/:address", async (c) => {
	const address = c.req.param("address");
	const chains = Object.entries(CHAIN_MAP);
	const results: Array<{ chainId: string; name: string; prefix: string }> = [];

	await Promise.allSettled(
		chains.map(async ([chainId, info]) => {
			try {
				const res = await fetch(`https://safe-transaction-${info.prefix}.safe.global/api/v1/safes/${address}/`, {
					signal: AbortSignal.timeout(5000),
				});
				if (res.ok) results.push({ chainId, name: info.name, prefix: info.prefix });
			} catch {}
		})
	);

	return c.json({ address, chains: results.sort((a, b) => a.name.localeCompare(b.name)) });
});

// ── Chain mapping ──
const CHAIN_MAP: Record<string, { name: string; prefix: string }> = {
	"1": { name: "Ethereum", prefix: "mainnet" },
	"10": { name: "Optimism", prefix: "optimism" },
	"100": { name: "Gnosis", prefix: "gnosis-chain" },
	"137": { name: "Polygon", prefix: "polygon" },
	"8453": { name: "Base", prefix: "base" },
	"42161": { name: "Arbitrum", prefix: "arbitrum" },
	"42220": { name: "Celo", prefix: "celo" },
	"43114": { name: "Avalanche", prefix: "avalanche" },
	"56": { name: "BSC", prefix: "bsc" },
	"324": { name: "zkSync", prefix: "zksync" },
	"11155111": { name: "Sepolia", prefix: "sepolia" },
	"84532": { name: "Base Sepolia", prefix: "base-sepolia" },
};

function getSafePrefix(chainId: string): string | null {
	return CHAIN_MAP[chainId]?.prefix || null;
}

// ── Safe Proposal / Confirm / Execute (EncryptID-authenticated) ──

// Helper: extract and verify JWT from request
async function verifyWalletAuth(c: any): Promise<{ sub: string; did?: string; username?: string; eid?: any } | null> {
	const authorization = c.req.header("Authorization");
	if (!authorization?.startsWith("Bearer ")) return null;
	try {
		// Import verify dynamically to avoid adding hono/jwt as a module-level dep
		const { verify } = await import("hono/jwt");
		const secret = process.env.JWT_SECRET;
		if (!secret) return null;
		const payload = await verify(authorization.slice(7), secret, "HS256");
		return payload as any;
	} catch {
		return null;
	}
}

// POST /api/safe/:chainId/:address/propose — Create a Safe transaction proposal
routes.post("/api/safe/:chainId/:address/propose", async (c) => {
	const claims = await verifyWalletAuth(c);
	if (!claims) return c.json({ error: "Authentication required" }, 401);

	// Require ELEVATED auth level (3+)
	if (!claims.eid || claims.eid.authLevel < 3) {
		return c.json({ error: "Elevated authentication required for proposals" }, 403);
	}
	if (!claims.eid.capabilities?.wallet) {
		return c.json({ error: "Wallet capability required" }, 403);
	}

	const chainId = c.req.param("chainId");
	const address = c.req.param("address");
	const chainPrefix = getSafePrefix(chainId);
	if (!chainPrefix) return c.json({ error: "Unsupported chain" }, 400);

	const body = await c.req.json();
	const { to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, nonce, signature, sender } = body;

	if (!to || !signature || !sender) {
		return c.json({ error: "Missing required fields: to, signature, sender" }, 400);
	}

	// Submit proposal to Safe Transaction Service
	const res = await fetch(
		`https://safe-transaction-${chainPrefix}.safe.global/api/v1/safes/${address}/multisig-transactions/`,
		{
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({
				to,
				value: value || "0",
				data: data || "0x",
				operation: operation || 0,
				safeTxGas: safeTxGas || "0",
				baseGas: baseGas || "0",
				gasPrice: gasPrice || "0",
				gasToken: gasToken || "0x0000000000000000000000000000000000000000",
				refundReceiver: refundReceiver || "0x0000000000000000000000000000000000000000",
				nonce,
				signature,
				sender,
			}),
		},
	);

	if (!res.ok) {
		const err = await res.text();
		return c.json({ error: "Safe Transaction Service error", details: err }, res.status as any);
	}

	return c.json(await res.json(), 201);
});

// POST /api/safe/:chainId/:address/confirm — Confirm a pending transaction
routes.post("/api/safe/:chainId/:address/confirm", async (c) => {
	const claims = await verifyWalletAuth(c);
	if (!claims) return c.json({ error: "Authentication required" }, 401);

	if (!claims.eid || claims.eid.authLevel < 3) {
		return c.json({ error: "Elevated authentication required" }, 403);
	}
	if (!claims.eid.capabilities?.wallet) {
		return c.json({ error: "Wallet capability required" }, 403);
	}

	const chainId = c.req.param("chainId");
	const chainPrefix = getSafePrefix(chainId);
	if (!chainPrefix) return c.json({ error: "Unsupported chain" }, 400);

	const { safeTxHash, signature } = await c.req.json();
	if (!safeTxHash || !signature) {
		return c.json({ error: "Missing required fields: safeTxHash, signature" }, 400);
	}

	const res = await fetch(
		`https://safe-transaction-${chainPrefix}.safe.global/api/v1/multisig-transactions/${safeTxHash}/confirmations/`,
		{
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ signature }),
		},
	);

	if (!res.ok) {
		const err = await res.text();
		return c.json({ error: "Confirmation failed", details: err }, res.status as any);
	}

	return c.json(await res.json());
});

// POST /api/safe/:chainId/:address/execute — Execute a ready transaction (CRITICAL auth)
routes.post("/api/safe/:chainId/:address/execute", async (c) => {
	const claims = await verifyWalletAuth(c);
	if (!claims) return c.json({ error: "Authentication required" }, 401);

	// Require CRITICAL auth level (4) for execution
	if (!claims.eid || claims.eid.authLevel < 4) {
		return c.json({ error: "Critical authentication required for execution" }, 403);
	}
	if (!claims.eid.capabilities?.wallet) {
		return c.json({ error: "Wallet capability required" }, 403);
	}

	// Check auth freshness (must be within 60 seconds)
	const now = Math.floor(Date.now() / 1000);
	if (claims.eid.authTime && (now - claims.eid.authTime) > 60) {
		return c.json({ error: "Authentication too old for execution — re-authenticate" }, 403);
	}

	const chainId = c.req.param("chainId");
	const address = c.req.param("address");
	const chainPrefix = getSafePrefix(chainId);
	if (!chainPrefix) return c.json({ error: "Unsupported chain" }, 400);

	// Get pending transactions and find the one to execute
	const { safeTxHash } = await c.req.json();
	if (!safeTxHash) {
		return c.json({ error: "Missing required field: safeTxHash" }, 400);
	}

	// Fetch the transaction details from Safe Transaction Service
	const txRes = await fetch(
		`https://safe-transaction-${chainPrefix}.safe.global/api/v1/multisig-transactions/${safeTxHash}/`,
	);

	if (!txRes.ok) {
		return c.json({ error: "Transaction not found" }, 404);
	}

	const txData = await txRes.json() as { confirmations?: any[]; confirmationsRequired?: number; isExecuted?: boolean };

	if (txData.isExecuted) {
		return c.json({ error: "Transaction already executed" }, 400);
	}

	const confirmationsNeeded = txData.confirmationsRequired || 1;
	const confirmationsReceived = txData.confirmations?.length || 0;

	if (confirmationsReceived < confirmationsNeeded) {
		return c.json({
			error: "Not enough confirmations",
			required: confirmationsNeeded,
			received: confirmationsReceived,
		}, 400);
	}

	// Transaction is ready — return execution data for client-side submission
	// (Actual on-chain execution must happen client-side with the user's signer)
	return c.json({
		ready: true,
		safeTxHash,
		confirmations: confirmationsReceived,
		required: confirmationsNeeded,
		transaction: txData,
	});
});

// ── Page route ──
routes.get("/", (c) => {
	const spaceSlug = c.req.param("space") || "demo";
	return c.html(renderShell({
		title: `${spaceSlug} — Wallet | rSpace`,
		moduleId: "rwallet",
		spaceSlug,
		modules: getModuleInfoList(),
		theme: "dark",
		body: `<folk-wallet-viewer></folk-wallet-viewer>`,
		scripts: `<script type="module" src="/modules/rwallet/folk-wallet-viewer.js"></script>`,
		styles: `<link rel="stylesheet" href="/modules/rwallet/wallet.css">`,
	}));
});

export const walletModule: RSpaceModule = {
	id: "rwallet",
	name: "rWallet",
	icon: "💰",
	description: "Multichain Safe wallet visualization and treasury management",
	scoping: { defaultScope: 'global', userConfigurable: false },
	routes,
	standaloneDomain: "rwallet.online",
	landingPage: renderLanding,
	feeds: [
		{
			id: "balances",
			name: "Token Balances",
			kind: "economic",
			description: "Multichain Safe token balances with USD valuations",
		},
		{
			id: "transfers",
			name: "Transfer History",
			kind: "economic",
			description: "Incoming and outgoing token transfers across chains",
		},
	],
	acceptsFeeds: ["economic", "governance"],
};
