'use server'

import { createClient } from '@/lib/supabase/server';
import { createHash } from 'crypto';
import { buildCustomerSnapshot, buildOrderSnapshot } from '@/lib/license-transform';
import { getProducts, getCategories } from '@/lib/actions/products';
import { sendMail } from '@/utils/mail';
import { renderToBuffer } from '@react-pdf/renderer';
import React from 'react';
import { InvoicePDF } from '@/components/invoice-pdf';

function generateOrderNumber(prefix: 'BE' | 'AE' = 'AE'): string {
  const year = new Date().getFullYear();
  const rand = Math.floor(10000 + Math.random() * 90000);
  return `${prefix}-${year}-${rand}`;
}

function hashOrderPayload(endCustomerId: string, items: any[]): string {
  const str = endCustomerId + JSON.stringify(items);
  return createHash('sha256').update(str).digest('hex');
}

// Asynchroner Hintergrund-Worker für Post-Processing (PDF-Erstellung und E-Mail)
async function triggerPostProcessing(orderId: string, supabase: any, customerSnapshot: any, orderSnapshot: any, type: string, email: string) {
  try {
    const { data: order, error } = await supabase
      .from('orders')
      .select('*')
      .eq('id', orderId)
      .single();

    if (error || !order) {
      console.error(`Post-Processing failed: Order ${orderId} not found`);
      return;
    }

    // PDF generieren
    const buffer = await renderToBuffer(
      React.createElement(InvoicePDF, {
        order,
        customer: customerSnapshot,
        orderSnapshot,
      })
    );

    const fileName = `ab_${order.id}.pdf`;
    const { error: uploadError } = await supabase
      .storage
      .from('invoices')
      .upload(fileName, buffer, { contentType: 'application/pdf', upsert: true });

    if (!uploadError) {
      await supabase.from('orders').update({ pdf_url: fileName }).eq('id', order.id);
    } else {
      console.error(`PDF Upload failed for order ${orderId}:`, uploadError);
    }

    // E-Mail versenden
    if (email) {
      await sendMail({
        to: email,
        subject: `Bestätigung Ihrer CASPOS-Anfrage ${order.order_number}`,
        text: `Vielen Dank für Ihre Anfrage ${order.order_number}.`,
        html: `<p>Vielen Dank für Ihre Anfrage <strong>${order.order_number}</strong>.</p>`
      });
    }
  } catch (err) {
    console.error(`Error in post-processing for order ${orderId}:`, err);
  }
}

export async function checkoutAction(params: {
  items: any[];
  endCustomerId: string;
  customerProfile?: any;
}) {
  const { items, endCustomerId, customerProfile } = params;
  const supabase = await createClient();

  // 1. Session & Auth Check
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) {
    throw new Error('Not authenticated');
  }

  const { data: dbUser } = await supabase
    .from('users')
    .select('role, company_id')
    .eq('id', user.id)
    .single();

  const isAdminUser = dbUser?.role === 'admin';
  if (!isAdminUser && !dbUser?.company_id) {
    throw new Error('Kein Unternehmen zugewiesen. Zugriff verweigert.');
  }

  // 2. Idempotency Guard
  const orderHash = hashOrderPayload(endCustomerId, items);
  const fiveMinutesAgo = new Date(Date.now() - 5 * 60_000).toISOString();

  const { data: existingOrders } = await supabase
    .from('orders')
    .select('id')
    .eq('user_id', user.id)
    .eq('order_hash', orderHash)
    .gte('created_at', fiveMinutesAgo);

  if (existingOrders && existingOrders.length > 0) {
    return { success: true, orderIds: existingOrders.map(o => o.id), duplicated: true };
  }

  // Fetch End Customer Stammdaten
  const { data: endCustomer, error: customerErr } = await supabase
    .from('end_customers')
    .select('*')
    .eq('id', endCustomerId)
    .single();

  if (customerErr || !endCustomer) {
    throw new Error('Endkunde nicht gefunden.');
  }

  const customerSnapshot = buildCustomerSnapshot(customerProfile || {}, endCustomer);

  const products = await getProducts();
  const categories = await getCategories();

  // 3. Checkout Split
  const purchaseItems = items.filter(
    (item: any) => item.billingInterval === 'one_time' || item.billingType === 'purchase'
  );
  const subscriptionItems = items.filter(
    (item: any) => item.billingInterval === 'monthly' || item.billingType === 'subscription'
  );

  const orderIds: string[] = [];

  const createOrderGroup = async (groupItems: any[], type: 'purchase' | 'subscription', paymentMethod: string) => {
    if (groupItems.length === 0) return;

    const orderItemsList: any[] = [];
    let total = 0;

    for (const item of groupItems) {
      const itemSnapshot = buildOrderSnapshot(
        item.selections,
        products,
        categories,
        type === 'purchase' ? 'one_time' : 'monthly',
        item.moduleQuantities
      );
      const itemsWithDevice = itemSnapshot.items.map(i => ({
        ...i,
        device_name: item.deviceName
      }));
      orderItemsList.push(...itemsWithDevice);
      total += itemSnapshot.total;
    }

    const orderSnapshot = {
      schema_version: 1,
      billing_cycle: type === 'purchase' ? 'one_time' : 'monthly',
      items: orderItemsList,
      total: total,
      tax_rate: 19,
      tax_amount: Math.round(total * 0.19 * 100) / 100,
      subtotal: Math.round((total / 1.19) * 100) / 100
    };

    const orderNumber = generateOrderNumber(type === 'purchase' ? 'AE' : 'BE');

    const { data: order, error: orderError } = await supabase
      .from('orders')
      .insert([{
        user_id: user.id,
        company_id: dbUser?.company_id || null,
        order_number: orderNumber,
        order_hash: orderHash,
        end_customer_id: endCustomerId,
        total_price: total,
        customer_data: customerSnapshot,
        order_data: orderSnapshot,
        type: type,
        payment_method: paymentMethod,
        status: 'pending'
      }])
      .select()
      .single();

    if (orderError) throw orderError;
    orderIds.push(order.id);

    // Entkoppeltes Post-Processing (asynchroner Aufruf)
    if (user.email) {
      Promise.resolve().then(() => {
        triggerPostProcessing(order.id, supabase, customerSnapshot, orderSnapshot, type, user.email!);
      });
    }
  };

  await createOrderGroup(purchaseItems, 'purchase', 'invoice');
  await createOrderGroup(subscriptionItems, 'subscription', 'sepa');

  return { success: true, orderIds, duplicated: false };
}
