import crypto from 'node:crypto';
import type { Prisma } from '@prisma/client';
import { prisma } from './db';
import { notifyAgent } from './notify';

export const STATUS_TR: Record<string, string> = {
  PENDING_PAYMENT: 'Ödeme bekleniyor', PAID: 'Ödendi', QUEUED: 'Kuyrukta', RENDERING: 'Üretiliyor', DELIVERED: 'Teslim edildi', FAILED: 'Hata', CANCELLED: 'İptal',
};
export function orderCode() { return 'PS-' + crypto.randomBytes(3).toString('hex').toUpperCase(); }

/** Transaction içinde siparişi kuyruğa alıp iş oluşturur. Zaten kuyrukta/üretimde/teslimdeyse dokunmaz ve false döner. */
export async function queueOrderTx(tx: Prisma.TransactionClient, orderId: string) {
  const r = await tx.order.updateMany({ where: { id: orderId, status: { notIn: ['QUEUED', 'RENDERING', 'DELIVERED'] } }, data: { status: 'QUEUED', progress: 0, progressMsg: 'Kuyrukta', error: null } });
  if (!r.count) return false;
  await tx.job.create({ data: { orderId } });
  return true;
}

export async function notifyQueued(orderId: string) {
  const o = await prisma.order.findUnique({ where: { id: orderId }, select: { id: true, code: true } });
  if (o) await notifyAgent('order.queued', o);
}

/** Ödenmiş siparişi kuyruğa alır (idempotent). */
export async function enqueueOrder(orderId: string) {
  if (await prisma.$transaction((tx) => queueOrderTx(tx, orderId))) await notifyQueued(orderId);
  return prisma.order.findUnique({ where: { id: orderId } });
}

class NoCredit extends Error {}
/** Kullanıcının kredisinden 1 düşüp siparişi kuyruğa alır. Yalnızca ödeme bekleyen siparişte çalışır; kredi ve sipariş birlikte değişir. */
export async function payWithCredit(userId: string, orderId: string) {
  try {
    const paid = await prisma.$transaction(async (tx) => {
      const o = await tx.order.updateMany({ where: { id: orderId, userId, status: 'PENDING_PAYMENT' }, data: { status: 'PAID' } });
      if (!o.count) return false;
      const c = await tx.user.updateMany({ where: { id: userId, credits: { gt: 0 } }, data: { credits: { decrement: 1 } } });
      if (!c.count) throw new NoCredit(); // sipariş güncellemesini geri al
      return queueOrderTx(tx, orderId);
    });
    if (paid) await notifyQueued(orderId);
    return paid;
  } catch (e) {
    if (e instanceof NoCredit) return false;
    throw e;
  }
}
