import { NextResponse } from "next/server";
import { createPublicClient, formatEther, http } from "viem";
import {
  EXPLORER_URL,
  PONS_FACTORY,
  PONS_FACTORY_START_BLOCK,
  ROBINHOOD_RPC_URL,
  robinhoodChain,
  tokenLaunchedEvent,
  tokenMetadataAbi,
} from "@/lib/pons";

export const dynamic = "force-dynamic";

const client = createPublicClient({
  chain: robinhoodChain,
  transport: http(ROBINHOOD_RPC_URL, { timeout: 12_000, retryCount: 2 }),
  batch: { multicall: true },
});

type LaunchesPayload = {
  source: string;
  chainId: number;
  latestBlock: number;
  scannedFromBlock: number;
  factory: string;
  launches: Array<{
    token: string;
    deployer: string;
    pool: string;
    pairToken: string;
    name: string;
    symbol: string;
    initialBuyEth: string;
    blockNumber: number;
    timestamp: number;
    txHash: string;
    explorerUrl: string;
  }>;
  updatedAt: string;
};

let cache: { payload: LaunchesPayload; expiresAt: number } | null = null;
const CACHE_TTL_MS = 10_000;

export async function GET() {
  if (cache && cache.expiresAt > Date.now()) {
    return NextResponse.json(cache.payload, {
      headers: { "Cache-Control": "public, max-age=5, stale-while-revalidate=20", "X-Data-Status": "fresh-cache" },
    });
  }

  try {
    const latestBlock = await client.getBlockNumber();
    const fromBlock = latestBlock - 2_000n > PONS_FACTORY_START_BLOCK
      ? latestBlock - 2_000n
      : PONS_FACTORY_START_BLOCK;

    const logs = await client.getLogs({
      address: PONS_FACTORY,
      event: tokenLaunchedEvent,
      fromBlock,
      toBlock: latestBlock,
    });

    const recentLogs = logs.slice(-12).reverse();
    const launches = await Promise.all(
      recentLogs.map(async (log) => {
        const token = log.args.token!;
        const [nameResult, symbolResult, block] = await Promise.all([
          client.readContract({ address: token, abi: tokenMetadataAbi, functionName: "name" }).catch(() => "Unknown token"),
          client.readContract({ address: token, abi: tokenMetadataAbi, functionName: "symbol" }).catch(() => "UNKNOWN"),
          client.getBlock({ blockNumber: log.blockNumber }),
        ]);

        return {
          token,
          deployer: log.args.deployer!,
          pool: log.args.pool!,
          pairToken: log.args.pairToken!,
          name: nameResult,
          symbol: symbolResult,
          initialBuyEth: formatEther(log.args.initialBuyAmount ?? 0n),
          blockNumber: Number(log.blockNumber),
          timestamp: Number(block.timestamp) * 1000,
          txHash: log.transactionHash,
          explorerUrl: `${EXPLORER_URL}/tx/${log.transactionHash}`,
        };
      }),
    );

    const payload: LaunchesPayload = {
      source: "Robinhood Chain",
      chainId: robinhoodChain.id,
      latestBlock: Number(latestBlock),
      scannedFromBlock: Number(fromBlock),
      factory: PONS_FACTORY,
      launches,
      updatedAt: new Date().toISOString(),
    };

    cache = { payload, expiresAt: Date.now() + CACHE_TTL_MS };

    return NextResponse.json(payload, {
      headers: { "Cache-Control": "public, max-age=5, stale-while-revalidate=20", "X-Data-Status": "live" },
    });
  } catch (error) {
    if (cache) {
      return NextResponse.json(cache.payload, {
        headers: { "Cache-Control": "public, max-age=5", "X-Data-Status": "stale-cache" },
      });
    }

    const message = error instanceof Error ? error.message : "Unknown RPC error";
    return NextResponse.json({ error: message }, { status: 502 });
  }
}
