import { prisma } from "@/lib/prisma";

type Bucket = {
  usdc: number;
  fiat: number;
};

function emptyBucket(): Bucket {
  return { usdc: 0, fiat: 0 };
}

function asRecord(value: unknown) {
  return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : {};
}

function numberValue(value: unknown) {
  const parsed = typeof value === "number" ? value : Number.parseInt(String(value || ""), 10);
  return Number.isFinite(parsed) ? Math.floor(parsed) : 0;
}

function stringValue(value: unknown) {
  return typeof value === "string" ? value : "";
}

function bucketKeyFromMetadata(metadata: Record<string, unknown>): keyof Bucket {
  const currency = stringValue(metadata.currency).toUpperCase();
  const paymentProvider = stringValue(metadata.payment_provider).toLowerCase();
  const withdrawalType = stringValue(metadata.type).toUpperCase();
  if (currency === "USDC" || paymentProvider === "wallet" || withdrawalType === "CRYPTO") {
    return "usdc";
  }
  return "fiat";
}

function addToBucket(bucket: Bucket, key: keyof Bucket, amount: number) {
  bucket[key] += amount;
}

function subtractBucket(left: Bucket, right: Bucket): Bucket {
  return {
    usdc: left.usdc - right.usdc,
    fiat: left.fiat - right.fiat,
  };
}

export async function getTreasurySnapshot() {
  const [
    allTasks,
    completedTasks,
    arbitrationCount,
    proposalFeeEvents,
    withdrawalEvents,
    recentAuditEvents,
  ] = await Promise.all([
    prisma.task.findMany({
      select: { reward_amount: true, reward_currency: true },
    }),
    prisma.task.findMany({
      where: { status: "COMPLETED" },
      select: { reward_amount: true, reward_currency: true },
    }),
    prisma.arbitration.count(),
    prisma.auditEvent.findMany({
      where: { action: "DEMAND_PROPOSAL_FEE_CAPTURED" },
      select: { id: true, entityId: true, metadata: true, createdAt: true },
      orderBy: { createdAt: "desc" },
    }),
    prisma.auditEvent.findMany({
      where: { action: "TREASURY_WITHDRAWAL" },
      select: { metadata: true },
    }),
    prisma.auditEvent.findMany({
      where: {
        action: {
          in: [
            "DEMAND_PROPOSAL_FEE_CAPTURED",
            "TREASURY_WITHDRAWAL",
            "TREASURY_WITHDRAWAL_REQUESTED",
          ],
        },
      },
      select: { id: true, action: true, entityId: true, metadata: true, createdAt: true },
      orderBy: { createdAt: "desc" },
      take: 20,
    }),
  ]);

  const gmv = emptyBucket();
  const taskPlatformFees = emptyBucket();
  const proposalFeeRevenue = emptyBucket();
  const arbitrationRevenue = emptyBucket();
  const withdrawn = emptyBucket();

  for (const task of allTasks) {
    addToBucket(gmv, task.reward_currency === "USDC" ? "usdc" : "fiat", task.reward_amount);
  }

  for (const task of completedTasks) {
    addToBucket(taskPlatformFees, task.reward_currency === "USDC" ? "usdc" : "fiat", Math.floor(task.reward_amount * 0.05));
  }

  addToBucket(arbitrationRevenue, "usdc", arbitrationCount * 5000);

  for (const event of proposalFeeEvents) {
    const metadata = asRecord(event.metadata);
    const amount = numberValue(metadata.fee_cents);
    if (amount <= 0) continue;
    addToBucket(proposalFeeRevenue, bucketKeyFromMetadata(metadata), amount);
  }

  for (const event of withdrawalEvents) {
    const metadata = asRecord(event.metadata);
    const amount = numberValue(metadata.amount);
    if (amount <= 0) continue;
    addToBucket(withdrawn, bucketKeyFromMetadata(metadata), amount);
  }

  const revenue = {
    usdc: taskPlatformFees.usdc + proposalFeeRevenue.usdc + arbitrationRevenue.usdc,
    fiat: taskPlatformFees.fiat + proposalFeeRevenue.fiat + arbitrationRevenue.fiat,
  };

  const recentTransactions = recentAuditEvents.map((event) => {
    const metadata = asRecord(event.metadata);
    const isOutflow = event.action.startsWith("TREASURY_WITHDRAWAL");
    const amount = numberValue(metadata.amount) || numberValue(metadata.fee_cents);
    const currency = bucketKeyFromMetadata(metadata) === "usdc" ? "USDC" : "USD";
    const provider = stringValue(metadata.payment_provider);
    const reference = stringValue(metadata.payment_reference) || stringValue(metadata.txHash) || stringValue(metadata.destination);
    const source =
      event.action === "DEMAND_PROPOSAL_FEE_CAPTURED"
        ? `Proposal ${event.entityId}`
        : reference || "Treasury";

    return {
      id: event.id,
      type: event.action === "DEMAND_PROPOSAL_FEE_CAPTURED"
        ? `${provider || "proposal"}_proposal_fee`
        : event.action.toLowerCase(),
      source,
      amount,
      currency,
      direction: isOutflow ? "out" : "in",
      date: event.createdAt.toISOString(),
    };
  });

  return {
    gmv,
    revenue,
    withdrawn,
    available: subtractBucket(revenue, withdrawn),
    proposal_fee_revenue: proposalFeeRevenue,
    task_platform_fee_revenue: taskPlatformFees,
    arbitration_fee_revenue: arbitrationRevenue,
    recent_transactions: recentTransactions,
  };
}
