import { NextRequest, NextResponse } from "next/server";
import { WebhookVerificationError } from "@polar-sh/sdk/webhooks";
import { Query } from "node-appwrite";

import { logAudit } from "@/lib/appwrite/audit";
import { DATABASE_ID, TABLES, type SubscriptionPayment } from "@/lib/appwrite/schema";
import { createAdminClient } from "@/lib/appwrite/server";
import { verifyAndParsePolarWebhook } from "@/lib/payments/polar";

const PRO_VALIDITY_DAYS = 30;

export async function POST(req: NextRequest): Promise<NextResponse> {
  let rawBody: string;
  try {
    rawBody = await req.text();
  } catch {
    return NextResponse.json({ error: "invalid body" }, { status: 400 });
  }

  const headers: Record<string, string> = {};
  req.headers.forEach((value, key) => { headers[key] = value; });

  let event: ReturnType<typeof verifyAndParsePolarWebhook>;
  try {
    event = verifyAndParsePolarWebhook(headers, rawBody);
  } catch (e) {
    if (e instanceof WebhookVerificationError) {
      console.error("[polar/callback] signature mismatch");
      return NextResponse.json({ error: "signature mismatch" }, { status: 403 });
    }
    return NextResponse.json({ error: "invalid payload" }, { status: 400 });
  }

  // order.created veya checkout.updated (status=confirmed) eventlerini işle
  const isOrderCreated = event.type === "order.created";
  const isCheckoutConfirmed =
    event.type === "checkout.updated" && event.data.status === "confirmed";

  if (!isOrderCreated && !isCheckoutConfirmed) {
    return new NextResponse("OK", { status: 200 });
  }

  const metadata = (event.data.metadata ?? {}) as Record<string, string>;
  const crmOrderId = metadata.crm_order_id ?? "";

  if (!crmOrderId) {
    console.error("[polar/callback] no crm_order_id in metadata", event.type);
    return new NextResponse("OK", { status: 200 });
  }

  const { tablesDB } = createAdminClient();

  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.subscriptionPayments,
    queries: [
      Query.equal("orderId", crmOrderId),
      Query.equal("provider", "polar"),
      Query.limit(1),
    ],
  });

  const payment = result.rows[0] as unknown as SubscriptionPayment | undefined;
  if (!payment) {
    console.error("[polar/callback] payment not found", crmOrderId);
    return new NextResponse("OK", { status: 200 });
  }

  if (payment.status === "success" || payment.status === "failed") {
    return new NextResponse("OK", { status: 200 });
  }

  const now = new Date();
  const expires = new Date(now.getTime() + PRO_VALIDITY_DAYS * 24 * 60 * 60 * 1000);

  await tablesDB.updateRow(DATABASE_ID, TABLES.subscriptionPayments, payment.$id, {
    status: "success",
    processedAt: now.toISOString(),
    providerPayload: JSON.stringify({ polar: true, eventType: event.type, ...metadata }),
  });

  const settingsResult = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.tenantSettings,
    queries: [Query.equal("tenantId", payment.tenantId), Query.limit(1)],
  });
  const settings = settingsResult.rows[0] as unknown as { $id: string } | undefined;

  if (settings) {
    await tablesDB.updateRow(DATABASE_ID, TABLES.tenantSettings, settings.$id, {
      plan: payment.plan,
      planStartedAt: now.toISOString(),
      planExpiresAt: expires.toISOString(),
      lastPaymentId: payment.$id,
    });
  }

  await logAudit({
    tenantId: payment.tenantId,
    userId: payment.createdBy,
    action: "update",
    entityType: "subscription_payment",
    entityId: payment.$id,
    changes: { provider: "polar", status: "success", plan: payment.plan },
  });

  return new NextResponse("OK", { status: 200 });
}
