import "server-only";
import { after } from "next/server";
import { and, eq } from "drizzle-orm";
import { appDb, schema } from "./appdb";
import { grantCredits, URUNLER } from "./credits";
import { retrieveCheckoutForm } from "./iyzico";
import { sunucuOlayi } from "./analitik-sunucu";

const { orders } = schema;

/**
 * Token'la iyzico'dan sonucu çeker ve başarılıysa krediyi İDEMPOTENT tanımlar.
 * Hem callback route'u hem /odeme/sonuc self-healing fallback'i bunu kullanır.
 * Dönen değer: siparişin son durumu.
 */
export async function odemeyiSonuclandir(
  orderId: string,
): Promise<"paid" | "pending" | "failed" | "not_found"> {
  const order = await appDb.query.orders.findFirst({
    where: eq(orders.id, orderId),
  });
  if (!order) return "not_found";
  if (order.status === "paid") return "paid";
  if (!order.iyzicoToken) return order.status;

  let sonuc;
  try {
    sonuc = await retrieveCheckoutForm(order.iyzicoToken);
  } catch {
    return order.status; // iyzico'ya ulaşılamadı; durumu değiştirme
  }

  if (sonuc.status !== "success" || sonuc.paymentStatus !== "SUCCESS") {
    await appDb
      .update(orders)
      .set({ status: "failed" })
      .where(and(eq(orders.id, orderId), eq(orders.status, "pending")));
    return "failed";
  }
  if (sonuc.conversationId && sonuc.conversationId !== order.id) {
    return order.status; // conversationId uyuşmazlığı: işleme
  }

  // pending -> paid koşullu geçiş: 0 satır = başka istek zaten işledi
  const res = await appDb
    .update(orders)
    .set({
      status: "paid",
      iyzicoPaymentId: sonuc.paymentId ?? null,
      paidAt: new Date(),
    })
    .where(and(eq(orders.id, orderId), eq(orders.status, "pending")));
  if (res.rowsAffected === 0) return "paid";

  // UNIQUE(reason, refId) ikinci katman güvence
  await grantCredits({
    userId: order.userId,
    delta: order.credits,
    reason: order.product === "paket" ? "purchase" : "topup",
    refId: order.id,
    setHasPaket: order.product === "paket",
  });

  // Dönüşüm kaydı. Koşullu geçişin ardında olduğu için sipariş başına tam bir
  // kez düşer (self-healing fallback tekrar çağrılsa da rowsAffected 0 döner).
  // after(): yanıt gönderildikten sonra koşar — callback redirect'ini ve
  // /odeme/sonuc render'ını Rybbit'in 3 sn'lik timeout'u bloklayamaz.
  after(() =>
    sunucuOlayi("odeme_tamamlandi", {
      kullaniciId: order.userId,
      pathname: "/odeme/sonuc",
      ozellikler: {
        urun: order.product,
        kredi: order.credits,
        tutar: order.amountKurus / 100,
      },
    }),
  );
  return "paid";
}

export { URUNLER };