import { json } from '@sveltejs/kit';
import type { RequestHandler } from '@sveltejs/kit';
import prisma from '$lib/server/prisma';
import { KEY } from '$env/static/private';
import { createHmac } from 'node:crypto';

export const POST: RequestHandler = async ({ request }) => {
  const raw = await request.text();

  const signatureHeader =
    request.headers.get('x-pesaflow-signature') ||
    request.headers.get('x-signature') ||
    request.headers.get('x-hub-signature') ||
    request.headers.get('x-pf-signature') ||
    null;

  if (!signatureHeader) return new Response('Missing signature', { status: 400 });

  const expected = createHmac('sha256', KEY || '').update(raw).digest('base64');
  if (expected !== signatureHeader) return new Response('Invalid signature', { status: 401 });

  let payload: any;
  try {
    payload = JSON.parse(raw);
  } catch {
    return new Response('Invalid JSON', { status: 400 });
  }

  const billRef =
    payload.billRefNumber ||
    payload.billRef ||
    payload.providerRef ||
    payload.ref ||
    payload.invoiceReference ||
    null;
  const status =
    (payload.status || payload.paymentStatus || payload.transactionStatus || '').toString().toLowerCase();

  if (!billRef) return new Response('Missing bill reference', { status: 400 });

  const payment = await prisma.payment.findFirst({ where: { providerRef: billRef } });
  if (!payment) return new Response('Payment not found', { status: 404 });

  // idempotent: already succeeded
  if (payment.status === 'SUCCEEDED') return json({ ok: true });

  const successTokens = ['success', 'paid', 'completed', 'settled', 'ok'];
  if (successTokens.includes(status)) {
    // merge provider response into rawPayload
    const mergedPayload = {
      ...(payment.rawPayload as Record<string, any> || {}),
      providerResponse: payload
    };

    await prisma.payment.update({
      where: { id: payment.id },
      data: {
        status: 'SUCCEEDED',
        rawPayload: mergedPayload
      }
    });

    const rp: any = mergedPayload || {};

    // Handle document purchase: map ProductDocument -> Document -> Entitlement
    if (rp.type === 'DOCUMENT_PURCHASE' && rp.documentId) {
      try {
        const productDocumentId = Number(rp.documentId);
        if (!Number.isFinite(productDocumentId) || productDocumentId <= 0) {
          console.error('entitlement skipped: invalid productDocument id', rp.documentId);
        } else {
          const pd = await prisma.productDocument.findUnique({ where: { id: productDocumentId } });
          if (!pd) {
            console.error('entitlement skipped: productDocument not found', productDocumentId);
          } else {
            // find or create linked secure Document record
            let secureDoc = null;
            if (pd.documentId) {
              secureDoc = await prisma.document.findUnique({ where: { id: pd.documentId } });
            }
            if (!secureDoc) {
              // create placeholder Document (wrappedKey is required by schema)
              secureDoc = await prisma.document.create({
                data: {
                  title: pd.originalName || `productdoc-${pd.id}`,
                  pageCount: pd.pageCount ?? 0,
                  wrappedKey: `auto-created-${Date.now()}`
                }
              });
              // persist link for idempotency
              try {
                await prisma.productDocument.update({ where: { id: pd.id }, data: { documentId: secureDoc.id } });
              } catch (updErr: any) {
                console.error('failed to link productDocument -> document', updErr?.message || updErr);
              }
            }

            // create entitlement (idempotent - unique constraint exists)
            try {
              await prisma.entitlement.create({
                data: {
                  userId: payment.userId,
                  documentId: secureDoc.id
                }
              });
            } catch (entErr: any) {
              console.error('entitlement create error (notification):', entErr?.message || entErr);
            }
          }
        }
      } catch (err: any) {
        console.error('entitlement create error (notification):', err?.message || err);
      }
    }

    // create an Order record for this payment so it appears on Purchases
    try {
      const existingOrder = await prisma.order.findFirst({ where: { billRefNumber: payment.providerRef ?? undefined } });
      if (!existingOrder) {
        // productId fallback: try rp.productId or rp.product?.id or productDocument -> productId
        let productId: number | null = null;
        if (rp.productId) productId = Number(rp.productId);
        else if (rp.product?.id) productId = Number(rp.product.id);
        else if (rp.documentId) {
          const pd = await prisma.productDocument.findUnique({ where: { id: Number(rp.documentId) } });
          if (pd) productId = pd.productId ?? null;
        }

        const total = Number(payment.amount ?? 0);

        const order = await prisma.order.create({
          data: {
            userId: payment.userId,
            totalPrice: total,
            status: 'COMPLETED',
            billRefNumber: payment.providerRef || String(payment.id),
            description: rp.type === 'DOCUMENT_PURCHASE' ? `Document purchase ${rp.documentId}` : undefined,
            ProductOnOrder: productId
              ? {
                  create: [
                    {
                      productId,
                      quantity: 1,
                      unitPrice: total
                    }
                  ]
                }
              : undefined
          }
        });

        // link payment -> order
        try {
          await prisma.payment.update({ where: { id: payment.id }, data: { orderId: order.id } });
        } catch (updErr: any) {
          console.error('failed to link payment -> order', updErr?.message || updErr);
        }
      }
    } catch (err: any) {
      console.error('order create error (notification):', err?.message || err);
    }

    return json({ ok: true });
  }

  // otherwise mark failed and attach provider response
  await prisma.payment.update({
    where: { id: payment.id },
    data: {
      status: 'FAILED',
      rawPayload: {
        ...(payment.rawPayload as Record<string, any> || {}),
        providerResponse: payload
      }
    }
  });

  return json({ ok: true });
};