<?php
header("Content-Type: application/pdf");
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
header("Expires: 0");

require_once dirname(__DIR__) . '/vendor/tcpdf/tcpdf.php';
require_once dirname(__DIR__) . '/config/database.php';

$database = new Database();
$db = $database->getConnection();

$type = $_GET['type'] ?? 'ventas';
$allowed = ['ventas', 'clientes', 'servicios', 'inventario', 'impuestos'];
if (!in_array($type, $allowed, true)) $type = 'ventas';

$start = $_GET['start'] ?? date('Y-m-d', strtotime('-30 days'));
$end = $_GET['end'] ?? date('Y-m-d');
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $start)) $start = date('Y-m-d', strtotime('-30 days'));
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $end)) $end = date('Y-m-d');

$filters = [
    'search' => trim((string)($_GET['search'] ?? '')),
    'category' => trim((string)($_GET['category'] ?? '')),
    'lowStock' => (string)($_GET['lowStock'] ?? '') === '1',
];

$conf = [];
try {
    $rs = $db->query("SELECT clave, valor FROM configuracion");
    if ($rs) {
        while ($row = $rs->fetch(PDO::FETCH_ASSOC)) $conf[$row['clave']] = $row['valor'];
    }
} catch (Exception $e) {}

if (!empty($conf['zona_horaria'])) date_default_timezone_set($conf['zona_horaria']);
else date_default_timezone_set('America/Puerto_Rico');

$empresa = [
    'nombre' => $conf['empresa_nombre'] ?? 'Lavanderia',
    'telefono' => $conf['empresa_telefono'] ?? '',
    'email' => $conf['empresa_email'] ?? '',
    'direccion' => $conf['empresa_direccion'] ?? '',
];
$moneda = $conf['moneda'] ?? 'USD';
$fmt_fecha = $conf['formato_fecha'] ?? 'm/d/Y';

function money_fmt($value, $currency) {
    $symbol = $currency === 'EUR' ? 'EUR ' : '$';
    return $symbol . number_format((float)$value, 2);
}

function date_fmt($value, $format) {
    $time = strtotime((string)$value);
    return $time ? date($format, $time) : (string)$value;
}

function h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function get_taxes($conf) {
    $taxes = json_decode($conf['system_taxes'] ?? '[]', true);
    if (!is_array($taxes) || count($taxes) === 0) {
        $rate = (float)($conf['impuesto_porcentaje'] ?? 0);
        $taxes = [['name' => $conf['impuesto_descripcion'] ?? 'Impuesto', 'rate' => $rate]];
    }
    $clean = [];
    foreach ($taxes as $tax) {
        $rate = (float)($tax['rate'] ?? 0);
        if ($rate > 0) $clean[] = ['name' => $tax['name'] ?? 'Impuesto', 'rate' => $rate];
    }
    return count($clean) ? $clean : [['name' => 'Impuesto', 'rate' => 0]];
}

function table_exists($db, $name) {
    $stmt = $db->prepare("SHOW TABLES LIKE ?");
    $stmt->execute([$name]);
    return (bool)$stmt->fetch(PDO::FETCH_NUM);
}

function ensure_products_table($db) {
    $db->exec("
        CREATE TABLE IF NOT EXISTS products (
          id INT AUTO_INCREMENT PRIMARY KEY,
          product_code VARCHAR(50) NOT NULL UNIQUE,
          product_name VARCHAR(160) NOT NULL,
          categoria VARCHAR(100) NOT NULL DEFAULT 'General',
          stock DECIMAL(10,2) NOT NULL DEFAULT 0,
          min_stock DECIMAL(10,2) NOT NULL DEFAULT 0,
          unit_cost DECIMAL(10,2) NOT NULL DEFAULT 0,
          unit VARCHAR(30) NOT NULL DEFAULT 'unidad',
          supplier VARCHAR(160) NULL,
          is_active TINYINT(1) NOT NULL DEFAULT 1,
          created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
          updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
    ");
}

function sales_data($db, $start, $end) {
    $stmt = $db->prepare("
        SELECT o.id, o.order_number, o.created_at, o.status, o.subtotal, o.tax, o.discount, o.total,
               c.full_name AS customer_name,
               COALESCE(p.method, 'Pendiente') AS payment_method,
               p.id IS NOT NULL AS is_paid
        FROM orders o
        JOIN customers c ON c.id = o.customer_id
        LEFT JOIN (
            SELECT p1.*
            FROM payments p1
            JOIN (
                SELECT order_id, MAX(id) AS max_id
                FROM payments
                WHERE payment_status != 'void'
                GROUP BY order_id
            ) last_payment ON last_payment.max_id = p1.id
        ) p ON p.order_id = o.id
        WHERE DATE(o.created_at) BETWEEN ? AND ?
        ORDER BY o.created_at DESC, o.id DESC
    ");
    $stmt->execute([$start, $end]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

function inventory_status($row) {
    if (isset($row['is_active']) && (int)$row['is_active'] !== 1) return 'Inactivo';
    return (float)$row['current_stock'] <= (float)$row['min_stock'] ? 'Bajo stock' : 'Activo';
}

function report_data($db, $type, $start, $end, $conf, $filters = []) {
    if ($type === 'clientes') {
        $stmt = $db->prepare("
            SELECT c.id, c.full_name, c.email, c.phone, c.plan,
                   COUNT(o.id) AS total_orders, COALESCE(SUM(o.total), 0) AS total_spent
            FROM customers c
            JOIN orders o ON o.customer_id = c.id
            WHERE DATE(o.created_at) BETWEEN ? AND ? AND o.status != 'cancelled'
            GROUP BY c.id, c.full_name, c.email, c.phone, c.plan
            ORDER BY total_spent DESC, total_orders DESC
        ");
        $stmt->execute([$start, $end]);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $total = array_sum(array_map(fn($r) => (float)$r['total_spent'], $rows));
        return [
            'title' => 'REPORTE DE CLIENTES',
            'kpis' => [['Clientes', count($rows)], ['Ordenes', array_sum(array_map(fn($r) => (int)$r['total_orders'], $rows))], ['Total', $total]],
            'columns' => ['Cliente', 'Email', 'Telefono', 'Plan', 'Ordenes', 'Total'],
            'rows' => array_map(fn($r) => [h($r['full_name']), h($r['email'] ?: 'N/A'), h($r['phone'] ?: 'N/A'), h($r['plan']), (int)$r['total_orders'], money_fmt($r['total_spent'], $conf['moneda'] ?? 'USD')], $rows)
        ];
    }

    if ($type === 'servicios') {
        $stmt = $db->prepare("
            SELECT s.id, s.service_name, s.service_code, s.unit, s.price,
                   COALESCE(SUM(CASE WHEN o.status != 'cancelled' THEN oi.quantity ELSE 0 END), 0) AS quantity_sold,
                   COALESCE(SUM(CASE WHEN o.status != 'cancelled' THEN oi.line_total ELSE 0 END), 0) AS total_revenue
            FROM services s
            LEFT JOIN order_items oi ON oi.service_id = s.id
            LEFT JOIN orders o ON o.id = oi.order_id AND DATE(o.created_at) BETWEEN ? AND ?
            GROUP BY s.id, s.service_name, s.service_code, s.unit, s.price
            ORDER BY total_revenue DESC, quantity_sold DESC, s.service_name ASC
        ");
        $stmt->execute([$start, $end]);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return [
            'title' => 'REPORTE DE SERVICIOS',
            'kpis' => [['Servicios', count($rows)], ['Unidades', array_sum(array_map(fn($r) => (float)$r['quantity_sold'], $rows))], ['Recaudado', array_sum(array_map(fn($r) => (float)$r['total_revenue'], $rows))]],
            'columns' => ['Servicio', 'Codigo', 'Unidad', 'Precio', 'Cantidad', 'Recaudado'],
            'rows' => array_map(fn($r) => [h($r['service_name']), h($r['service_code']), h($r['unit']), money_fmt($r['price'], $conf['moneda'] ?? 'USD'), number_format((float)$r['quantity_sold'], 1), money_fmt($r['total_revenue'], $conf['moneda'] ?? 'USD')], $rows)
        ];
    }

    if ($type === 'inventario') {
        ensure_products_table($db);
        if (!table_exists($db, 'products') && !table_exists($db, 'productos')) {
            return [
                'title' => 'REPORTE DE INVENTARIO',
                'kpis' => [['Productos', 0], ['Stock bajo', 0], ['Valor', 0]],
                'columns' => ['Estado'],
                'rows' => [['No hay tabla de inventario configurada en esta instalacion.']]
            ];
        }
        $table = table_exists($db, 'products') ? 'products' : 'productos';
        $nameCol = $table === 'products' ? 'product_name' : 'nombre';
        $codeCol = $table === 'products' ? 'product_code' : 'codigo';
        $stockCol = $table === 'products' ? 'stock' : 'stock_actual';
        $minCol = $table === 'products' ? 'min_stock' : 'stock_minimo';
        $costCol = $table === 'products' ? 'unit_cost' : 'costo_unitario';
        $activeCol = $table === 'products' ? 'is_active' : '1';
        $where = [];
        $params = [];

        if (!empty($filters['search'])) {
            $supplierSearch = $table === 'products' ? " OR supplier LIKE ?" : "";
            $where[] = "($codeCol LIKE ? OR $nameCol LIKE ? OR categoria LIKE ?$supplierSearch)";
            $like = '%' . $filters['search'] . '%';
            $params[] = $like;
            $params[] = $like;
            $params[] = $like;
            if ($table === 'products') $params[] = $like;
        }
        if (!empty($filters['category'])) {
            $where[] = "categoria = ?";
            $params[] = $filters['category'];
        }
        if (!empty($filters['lowStock'])) {
            $where[] = "$stockCol <= $minCol";
        }

        $stmt = $db->prepare("
            SELECT id, $codeCol AS code, $nameCol AS name, categoria AS category,
                   $stockCol AS current_stock, $minCol AS min_stock, $costCol AS unit_cost,
                   ($stockCol * $costCol) AS stock_value, $activeCol AS is_active
            FROM $table
            " . (count($where) ? 'WHERE ' . implode(' AND ', $where) : '') . "
            ORDER BY category ASC, stock_value DESC, name ASC
        ");
        $stmt->execute($params);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $grouped = [];
        foreach ($rows as $row) {
            $cat = $row['category'] ?: 'Sin categoria';
            if (!isset($grouped[$cat])) $grouped[$cat] = ['stock' => 0, 'value' => 0, 'count' => 0, 'rows' => []];
            $grouped[$cat]['stock'] += (float)$row['current_stock'];
            $grouped[$cat]['value'] += (float)$row['stock_value'];
            $grouped[$cat]['count'] += 1;
            $grouped[$cat]['rows'][] = $row;
        }

        $bodyHtml = '';
        foreach ($grouped as $category => $summary) {
            $bodyHtml .= '<tr class="category-row"><td colspan="9">' . h($category) . ' - ' . $summary['count'] . ' productos | Stock: ' . number_format($summary['stock'], 1) . ' | Subtotal: ' . money_fmt($summary['value'], $conf['moneda'] ?? 'USD') . '</td></tr>';
            foreach ($summary['rows'] as $r) {
                $status = inventory_status($r);
                $statusClass = $status === 'Bajo stock' ? 'status-low' : ($status === 'Inactivo' ? 'status-off' : 'status-ok');
                $bodyHtml .= '<tr>
                    <td style="width:11%;">' . h($r['code'] ?: 'N/A') . '</td>
                    <td style="width:21%;">' . h($r['name']) . '</td>
                    <td style="width:12%;">' . h($r['category'] ?: 'N/A') . '</td>
                    <td class="right" style="width:9%;">' . number_format((float)$r['current_stock'], 1) . '</td>
                    <td class="right" style="width:9%;">' . number_format((float)$r['min_stock'], 1) . '</td>
                    <td class="right" style="width:11%;">' . money_fmt($r['unit_cost'], $conf['moneda'] ?? 'USD') . '</td>
                    <td class="right" style="width:11%;">' . money_fmt($r['stock_value'], $conf['moneda'] ?? 'USD') . '</td>
                    <td class="center ' . $statusClass . '" style="width:9%;">' . h($status) . '</td>
                    <td class="center" style="width:7%;">' . ((int)$r['is_active'] === 1 ? 'Si' : 'No') . '</td>
                </tr>';
            }
        }

        $filterText = [];
        if (!empty($filters['search'])) $filterText[] = 'Busqueda: ' . $filters['search'];
        if (!empty($filters['category'])) $filterText[] = 'Categoria: ' . $filters['category'];
        if (!empty($filters['lowStock'])) $filterText[] = 'Solo bajo stock';

        $headHtml = '<th style="width:11%;">Codigo</th><th style="width:21%;">Producto</th><th style="width:12%;">Categoria</th><th class="right" style="width:9%;">Stock</th><th class="right" style="width:9%;">Minimo</th><th class="right" style="width:11%;">Costo</th><th class="right" style="width:11%;">Valor</th><th class="center" style="width:9%;">Estado</th><th class="center" style="width:7%;">Activo</th>';
        $footerHtml = '<tr class="total-row"><td colspan="3">TOTAL GENERAL</td><td class="right">' . number_format(array_sum(array_map(fn($r) => (float)$r['current_stock'], $rows)), 1) . '</td><td></td><td></td><td class="right">' . money_fmt(array_sum(array_map(fn($r) => (float)$r['stock_value'], $rows)), $conf['moneda'] ?? 'USD') . '</td><td colspan="2"></td></tr>';

        return [
            'title' => 'REPORTE DE INVENTARIO',
            'subtitle' => count($filterText) ? implode(' | ', $filterText) : 'Todos los productos',
            'kpis' => [['Productos', count($rows)], ['Stock bajo', count(array_filter($rows, fn($r) => (float)$r['current_stock'] <= (float)$r['min_stock']))], ['Valor', array_sum(array_map(fn($r) => (float)$r['stock_value'], $rows))]],
            'columns' => ['Codigo', 'Producto', 'Categoria', 'Stock', 'Minimo', 'Costo', 'Valor', 'Estado', 'Activo'],
            'rows' => $rows,
            'headHtml' => $headHtml,
            'bodyHtml' => $bodyHtml,
            'footerHtml' => $footerHtml
        ];
    }

    $orders = sales_data($db, $start, $end);
    $total = array_sum(array_map(fn($r) => (float)$r['total'], $orders));
    $tax = array_sum(array_map(fn($r) => (float)$r['tax'], $orders));
    $discount = array_sum(array_map(fn($r) => (float)$r['discount'], $orders));

    if ($type === 'impuestos') {
        $taxes = get_taxes($conf);
        $columns = ['Fecha', 'Orden', 'Cliente', 'Subtotal', 'Base Gravable'];
        foreach ($taxes as $taxInfo) $columns[] = $taxInfo['name'] . ' (' . $taxInfo['rate'] . '%)';
        $columns[] = 'Total Imp.';
        $columns[] = 'Total';

        $rows = [];
        $subtotal_total = 0;
        $base_total = 0;
        $tax_totals = array_fill(0, count($taxes), 0.0);
        foreach ($orders as $order) {
            $base = max((float)$order['subtotal'] - (float)$order['discount'], 0);
            $subtotal_total += (float)$order['subtotal'];
            $base_total += $base;
            $row = [date_fmt($order['created_at'], $conf['formato_fecha'] ?? 'm/d/Y'), h($order['order_number']), h($order['customer_name']), money_fmt($order['subtotal'], $conf['moneda'] ?? 'USD'), money_fmt($base, $conf['moneda'] ?? 'USD')];
            foreach ($taxes as $index => $taxInfo) {
                $amount = round($base * ((float)$taxInfo['rate'] / 100), 2);
                $tax_totals[$index] += $amount;
                $row[] = money_fmt($amount, $conf['moneda'] ?? 'USD');
            }
            $row[] = money_fmt($order['tax'], $conf['moneda'] ?? 'USD');
            $row[] = money_fmt($order['total'], $conf['moneda'] ?? 'USD');
            $rows[] = $row;
        }
        $footer = ['TOTALES', '', '', money_fmt($subtotal_total, $conf['moneda'] ?? 'USD'), money_fmt($base_total, $conf['moneda'] ?? 'USD')];
        foreach ($tax_totals as $tax_total) $footer[] = money_fmt($tax_total, $conf['moneda'] ?? 'USD');
        $footer[] = money_fmt($tax, $conf['moneda'] ?? 'USD');
        $footer[] = money_fmt($total, $conf['moneda'] ?? 'USD');

        return [
            'title' => 'REPORTE DE IMPUESTOS',
            'kpis' => [['Ordenes', count($orders)], ['Impuestos', $tax], ['Total', $total]],
            'columns' => $columns,
            'rows' => $rows,
            'footer' => $footer
        ];
    }

    return [
        'title' => 'REPORTE DE VENTAS',
        'kpis' => [['Ordenes', count($orders)], ['Ingresos', $total], ['Impuestos', $tax], ['Descuentos', $discount]],
        'columns' => ['Fecha', 'Orden', 'Cliente', 'Metodo', 'Subtotal', 'Impuesto', 'Descuento', 'Total', 'Estado'],
        'rows' => array_map(fn($r) => [date_fmt($r['created_at'], $conf['formato_fecha'] ?? 'm/d/Y'), h($r['order_number']), h($r['customer_name']), h($r['payment_method']), money_fmt($r['subtotal'], $conf['moneda'] ?? 'USD'), money_fmt($r['tax'], $conf['moneda'] ?? 'USD'), money_fmt($r['discount'], $conf['moneda'] ?? 'USD'), money_fmt($r['total'], $conf['moneda'] ?? 'USD'), h($r['status'])], $orders)
    ];
}

$report = report_data($db, $type, $start, $end, array_merge($conf, ['moneda' => $moneda, 'formato_fecha' => $fmt_fecha]), $filters);

$pdf = new TCPDF('L', 'mm', 'A4', true, 'UTF-8', false);
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetTitle($report['title']);
$pdf->SetMargins(10, 10, 10);
$pdf->SetAutoPageBreak(true, 14);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->AddPage();

$period = $type === 'inventario' ? 'Actualizado: ' . date($fmt_fecha . ' h:i A') : 'Periodo: ' . date_fmt($start, $fmt_fecha) . ' - ' . date_fmt($end, $fmt_fecha);
$kpiHtml = '';
$kpiWidth = count($report['kpis']) > 0 ? (100 / count($report['kpis'])) : 33.33;
foreach ($report['kpis'] as $kpi) {
    $value = is_numeric($kpi[1]) && stripos($kpi[0], 'orden') === false && stripos($kpi[0], 'producto') === false && stripos($kpi[0], 'stock') === false && stripos($kpi[0], 'servicio') === false && stripos($kpi[0], 'cliente') === false && stripos($kpi[0], 'unidad') === false
        ? money_fmt($kpi[1], $moneda)
        : $kpi[1];
    $kpiHtml .= '<td class="kpi" style="width:' . $kpiWidth . '%;"><table class="kpi-inner" cellpadding="0" cellspacing="0"><tr><td class="kpi-label">' . h($kpi[0]) . '</td></tr><tr><td class="kpi-value">' . h($value) . '</td></tr></table></td>';
}

$headHtml = $report['headHtml'] ?? '';
if (!$headHtml) {
    foreach ($report['columns'] as $col) $headHtml .= '<th>' . h($col) . '</th>';
}

$bodyHtml = $report['bodyHtml'] ?? '';
if (!$bodyHtml && count($report['rows']) === 0) {
    $bodyHtml = '<tr><td colspan="' . count($report['columns']) . '" class="empty">No hay datos para este reporte.</td></tr>';
} elseif (!$bodyHtml) {
    foreach ($report['rows'] as $row) {
        $bodyHtml .= '<tr>';
        foreach ($row as $cell) $bodyHtml .= '<td>' . $cell . '</td>';
        $bodyHtml .= '</tr>';
    }
}

$footerHtml = $report['footerHtml'] ?? '';
if (!empty($report['footer'])) {
    $footerHtml .= '<tr class="total-row">';
    foreach ($report['footer'] as $cell) $footerHtml .= '<td>' . $cell . '</td>';
    $footerHtml .= '</tr>';
}

$html = '
<style>
  body { color: #0f172a; font-family: freesans; }
  .header { background-color: #0f1b2a; color: #ffffff; padding: 14px 18px; }
  .company { font-size: 16px; font-weight: bold; }
  .meta { font-size: 8px; color: #b7c6d9; }
  .title { font-size: 18px; font-weight: bold; text-align: right; }
  .subtitle { margin: 8px 0 2px; color: #64748b; font-size: 8px; font-weight: bold; }
  .kpis { width: 100%; margin: 10px 0 14px; border-collapse: separate; border-spacing: 6px; }
  .kpi { background-color: #eef6ff; border-left: 3px solid #0877ff; padding: 8px 10px; }
  .kpi-inner { width: 100%; }
  .kpi-label { color: #64748b; font-size: 8px; font-weight: bold; text-transform: uppercase; text-align: center; padding-bottom: 3px; }
  .kpi-value { color: #0f172a; font-size: 14px; font-weight: bold; text-align: center; white-space: nowrap; }
  table.data { width: 100%; border-collapse: collapse; font-size: 7.5px; }
  table.data th { background-color: #0f1b2a; color: #ffffff; border: 1px solid #0f1b2a; padding: 5px; font-weight: bold; }
  table.data td { border-bottom: 1px solid #e2e8f0; padding: 4px; }
  table.data tr:nth-child(even) td { background-color: #f8fbff; }
  table.data .total-row td { background-color: #0f1b2a; color: #ffffff; font-weight: bold; border-bottom: 0; }
  table.data .category-row td { background-color: #eaf4ff; color: #0f1b2a; font-weight: bold; border-top: 1px solid #bfd8f5; border-bottom: 1px solid #bfd8f5; }
  table.data th.right, table.data td.right { text-align: right; }
  table.data th.center, table.data td.center { text-align: center; }
  .status-ok { color: #0f7a43; font-weight: bold; }
  .status-low { color: #c2410c; font-weight: bold; }
  .status-off { color: #b91c1c; font-weight: bold; }
  .empty { text-align: center; color: #64748b; padding: 18px; }
</style>
<table class="header" cellpadding="4">
  <tr>
    <td style="width: 55%;">
      <div class="company">' . h($empresa['nombre']) . '</div>
      <div class="meta">' . h($empresa['direccion']) . '<br />Tel: ' . h($empresa['telefono']) . ' | ' . h($empresa['email']) . '</div>
    </td>
    <td style="width: 45%; text-align: right;">
      <div class="title">' . h($report['title']) . '</div>
      <div class="meta">' . h($period) . '<br />Generado: ' . h(date($fmt_fecha . ' h:i A')) . '</div>
    </td>
  </tr>
</table>
' . (!empty($report['subtitle']) ? '<div class="subtitle">' . h($report['subtitle']) . '</div>' : '') . '
<table class="kpis" cellpadding="0" cellspacing="0"><tr>' . $kpiHtml . '</tr></table>
<table class="data" cellpadding="4">
  <thead><tr>' . $headHtml . '</tr></thead>
  <tbody>' . $bodyHtml . $footerHtml . '</tbody>
</table>';

$pdf->writeHTML($html, true, false, true, false, '');
$pdf->Output('Reporte_' . ucfirst($type) . '_' . $start . '_' . $end . '.pdf', 'I');
exit;
?>
