import { NextResponse } from "next/server";
import { createAdminClient } from "@/lib/supabase-admin";
import { buildPublicUrl, resolvePublicOrigin } from "@/lib/request-origin";
import {
  detectDocumentType,
  extractMercadoPagoQrData,
  fetchMercadoPagoApi,
  getActiveMercadoPagoCredentials,
  getMercadoPagoIntegration,
  normalizeMercadoPagoPaymentMethod,
  normalizeMercadoPagoPaymentStatus,
  parseMercadoPagoSettings,
  splitPersonName,
} from "@/lib/mercado-pago";
import { mapPaymentLinkRecord, normalizeText, type PaymentLinkRecord } from "@/lib/payment-links";
import { applyApprovedPaymentLinkPayment } from "@/lib/payment-link-processing";

type PaymentSubmitBody = {
  code?: string;
  paymentId?: string;
  paymentType?: string;
  selectedPaymentMethod?: string;
  formData?: Record<string, unknown>;
  additionalData?: Record<string, unknown> | null;
};

type MercadoPagoPaymentResponse = Record<string, unknown> & {
  id?: unknown;
  status?: unknown;
  status_detail?: unknown;
  payment_method_id?: unknown;
  payment_type_id?: unknown;
  date_of_expiration?: unknown;
};

function isLocalNotificationOrigin(origin: string) {
  try {
    const url = new URL(origin);
    const hostname = url.hostname.trim().toLowerCase();
    return hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".localhost");
  } catch {
    return true;
  }
}

export async function POST(request: Request) {
  try {
    const body = (await request.json().catch(() => null)) as PaymentSubmitBody | null;
    const code = normalizeText(body?.code).toUpperCase();
    const paymentId = normalizeText(body?.paymentId);
    if (!code || !paymentId) {
      return NextResponse.json({ error: "Dados do pagamento invalidos." }, { status: 400 });
    }

    const admin = createAdminClient();
    const [{ data: rawLink, error: linkError }, { data: localPayment, error: localPaymentError }] = await Promise.all([
      admin.from("payment_links").select("*").eq("code", code).maybeSingle(),
      admin
        .from("payment_link_payments")
        .select("id,user_id,integration_id,status,amount,currency,payer_name,payer_email,payer_document,raw_request")
        .eq("id", paymentId)
        .maybeSingle(),
    ]);

    if (linkError || !rawLink) {
      return NextResponse.json({ error: "Link de pagamento nao encontrado." }, { status: 404 });
    }
    if (localPaymentError || !localPayment?.id) {
      return NextResponse.json({ error: "Recebimento nao encontrado para este link." }, { status: 404 });
    }

    const link = mapPaymentLinkRecord(rawLink as PaymentLinkRecord);
    if (link.type !== "one_time") {
      return NextResponse.json({ error: "Este link utiliza o fluxo de assinatura." }, { status: 400 });
    }
    const paymentRequest =
      localPayment.raw_request && typeof localPayment.raw_request === "object" && !Array.isArray(localPayment.raw_request)
        ? (localPayment.raw_request as Record<string, unknown>)
        : {};
    const clientProfile =
      paymentRequest.client_profile &&
      typeof paymentRequest.client_profile === "object" &&
      !Array.isArray(paymentRequest.client_profile)
        ? (paymentRequest.client_profile as Record<string, unknown>)
        : {};
    if (localPayment.status === "approved") {
      return NextResponse.json({ error: "Este recebimento ja foi aprovado." }, { status: 400 });
    }

    const integration = await getMercadoPagoIntegration(admin as never, String(localPayment.user_id));
    if (!integration || integration.active === false) {
      return NextResponse.json({ error: "A loja nao possui Mercado Pago configurado." }, { status: 400 });
    }

    const settings = parseMercadoPagoSettings(integration.settings);
    const credentials = getActiveMercadoPagoCredentials(settings);
    if (!credentials) {
      return NextResponse.json({ error: "As credenciais do Mercado Pago desta loja estao incompletas." }, { status: 400 });
    }

    const formData = body?.formData && typeof body.formData === "object" ? body.formData : {};
    const payerInput =
      formData.payer && typeof formData.payer === "object" && !Array.isArray(formData.payer)
        ? (formData.payer as Record<string, unknown>)
        : {};
    const payerIdentification =
      payerInput.identification && typeof payerInput.identification === "object" && !Array.isArray(payerInput.identification)
        ? (payerInput.identification as Record<string, unknown>)
        : {};
    const customerName = normalizeText(localPayment.payer_name || clientProfile.name || "Cliente");
    const email = normalizeText(payerInput.email || localPayment.payer_email || clientProfile.email);
    const document = normalizeText(payerIdentification.number || localPayment.payer_document || clientProfile.document).replace(/\D/g, "");

    if (!email) {
      return NextResponse.json({ error: "Informe um e-mail valido para pagar." }, { status: 400 });
    }
    if (!document) {
      return NextResponse.json({ error: "Informe um CPF/CNPJ valido para pagar." }, { status: 400 });
    }

    const { firstName, lastName } = splitPersonName(customerName);
    const amount = Number(formData?.transaction_amount || localPayment.amount || 0);
    if (!Number.isFinite(amount) || amount <= 0) {
      return NextResponse.json({ error: "Valor invalido para pagamento." }, { status: 400 });
    }

    const normalizedMethod = normalizeMercadoPagoPaymentMethod(formData?.payment_method_id, body?.paymentType);
    const methodAllowed =
      normalizedMethod === "credit_card"
        ? link.allowCreditCard
        : normalizedMethod === "pix"
          ? link.allowPix
          : normalizedMethod === "ticket"
            ? link.allowBoleto
            : false;
    if (!methodAllowed) {
      return NextResponse.json({ error: "Este meio de pagamento nao esta habilitado para este link." }, { status: 400 });
    }

    const idempotencyKey = crypto.randomUUID();
    const externalReference = `payment_link:${link.id}:payment:${localPayment.id}:attempt:${idempotencyKey}`;
    const now = new Date().toISOString();
    const publicOrigin = resolvePublicOrigin(request);
    const notificationUrl = isLocalNotificationOrigin(publicOrigin)
      ? null
      : buildPublicUrl(request, "/api/webhooks/mercado-pago").toString();

    const requestPayload: Record<string, unknown> = {
      transaction_amount: amount,
      description: `Link de pagamento ${link.code} - ${link.title}`,
      payment_method_id: normalizeText(formData?.payment_method_id || ""),
      payer: {
        email,
        first_name: firstName,
        last_name: lastName,
        identification: {
          type: detectDocumentType(document),
          number: document,
        },
      },
      external_reference: externalReference,
      metadata: {
        payment_link_id: link.id,
        payment_link_code: link.code,
        payment_link_payment_id: localPayment.id,
      },
    };

    if (notificationUrl) {
      requestPayload.notification_url = notificationUrl;
    }

    if (settings.statement_descriptor) {
      requestPayload.statement_descriptor = settings.statement_descriptor;
    }

    if (normalizeText(formData?.token)) requestPayload.token = normalizeText(formData.token);
    if (normalizeText(formData?.issuer_id)) requestPayload.issuer_id = normalizeText(formData.issuer_id);
    if (Number(formData?.installments) > 0) requestPayload.installments = Number(formData.installments);
    if (normalizeText(formData?.processing_mode)) requestPayload.processing_mode = normalizeText(formData.processing_mode);

    const mercadoPagoPayment = await fetchMercadoPagoApi<MercadoPagoPaymentResponse>("/v1/payments", credentials.accessToken, {
      method: "POST",
      body: JSON.stringify(requestPayload),
      idempotencyKey,
    });

    const providerStatus = normalizeMercadoPagoPaymentStatus(mercadoPagoPayment.status);
    const providerMethod = normalizeMercadoPagoPaymentMethod(
      mercadoPagoPayment.payment_method_id,
      mercadoPagoPayment.payment_type_id
    );
    const qrData = extractMercadoPagoQrData(mercadoPagoPayment);
    const approvedAt = providerStatus === "approved" ? new Date().toISOString() : null;

    await admin
      .from("payment_link_payments")
      .update({
        integration_id: integration.id,
        status: providerStatus,
        provider_status: normalizeText(mercadoPagoPayment.status) || null,
        provider_status_detail: normalizeText(mercadoPagoPayment.status_detail) || null,
        provider_payment_id: normalizeText(mercadoPagoPayment.id),
        payment_method: providerMethod,
        payment_type: normalizeText(mercadoPagoPayment.payment_type_id) || null,
        approved_at: approvedAt,
        rejected_at: providerStatus === "rejected" ? new Date().toISOString() : null,
        cancelled_at: providerStatus === "cancelled" ? new Date().toISOString() : null,
        expires_at: normalizeText(mercadoPagoPayment.date_of_expiration) || null,
        qr_code: qrData.qrCode,
        qr_code_base64: qrData.qrCodeBase64,
        ticket_url: qrData.ticketUrl,
        external_reference: externalReference,
        checkout_environment: credentials.environment,
        amount,
        currency: normalizeText(localPayment.currency) || "BRL",
        payer_name: customerName,
        payer_email: email,
        payer_document: document,
        payer_document_type: detectDocumentType(document),
        idempotency_key: idempotencyKey,
        notification_url: notificationUrl,
        metadata: {
          slug: link.slug,
          payment_link_id: link.id,
          payment_link_code: link.code,
          bank_account_id: settings.bank_account_id,
        },
        raw_request: {
          client_profile: clientProfile,
          paymentType: body?.paymentType || null,
          selectedPaymentMethod: body?.selectedPaymentMethod || null,
          formData,
          additionalData: body?.additionalData || null,
        },
        raw_response: mercadoPagoPayment,
        updated_at: new Date().toISOString(),
      })
      .eq("id", localPayment.id);
    if (providerStatus === "approved") {
      await admin
        .from("payment_links")
        .update({ last_paid_at: new Date().toISOString(), updated_at: new Date().toISOString() })
        .eq("id", link.id);

      await applyApprovedPaymentLinkPayment(admin as never, String(localPayment.id));
    }

    return NextResponse.json({
      ok: true,
      payment_id: localPayment.id,
      provider_payment_id: normalizeText(mercadoPagoPayment.id) || null,
      status: providerStatus,
      status_detail: normalizeText(mercadoPagoPayment.status_detail) || null,
      payment_method: providerMethod,
      qr_code: qrData.qrCode,
      qr_code_base64: qrData.qrCodeBase64,
      ticket_url: qrData.ticketUrl,
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "Nao foi possivel processar o pagamento.";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
