<?php

declare(strict_types=1);

namespace App\Models;

class Invoice extends BaseModel
{
    protected string $table = 'facturas';

    public function findBySaleId(int $companyId, int $saleId): ?array
    {
        return $this->findMainBySaleId($companyId, $saleId);
    }

    public function details(int $invoiceId): array
    {
        $stmt = $this->db()->prepare(
            'SELECT
                fd.id,
                fd.producto_id,
                fd.descripcion,
                fd.cantidad,
                fd.precio_unitario,
                fd.impuesto,
                fd.total_linea
             FROM factura_detalles fd
             WHERE fd.factura_id = :factura_id
             ORDER BY fd.id ASC'
        );
        $stmt->execute([':factura_id' => $invoiceId]);

        return $stmt->fetchAll() ?: [];
    }

    public function findMainBySaleId(int $companyId, int $saleId): ?array
    {
        $stmt = $this->db()->prepare(
            'SELECT
                f.*,
                fr.numero AS documento_referencia_numero,
                c.nombre AS cliente_nombre,
                c.documento AS cliente_documento,
                c.email AS cliente_email,
                c.telefono AS cliente_telefono,
                s.nombre AS sucursal_nombre,
                e.nombre AS empresa_nombre,
                e.nit AS empresa_nit,
                e.email AS empresa_email,
                e.telefono AS empresa_telefono,
                e.direccion AS empresa_direccion,
                e.logo AS empresa_logo,
                v.fecha AS venta_fecha,
                v.subtotal AS venta_subtotal,
                v.descuento AS venta_descuento,
                v.impuestos AS venta_impuestos,
                v.total AS venta_total,
                (
                    SELECT GROUP_CONCAT(DISTINCT vp.metodo_pago ORDER BY vp.metodo_pago SEPARATOR ", ")
                    FROM venta_pagos vp
                    WHERE vp.venta_id = v.id
                      AND vp.empresa_id = v.empresa_id
                ) AS metodos_pago,
                (
                    SELECT COALESCE(SUM(vp2.monto), 0)
                    FROM venta_pagos vp2
                    WHERE vp2.venta_id = v.id
                      AND vp2.empresa_id = v.empresa_id
                ) AS total_pagado,
                u.nombre AS cajero,
                ua.nombre AS anulado_por_nombre
             FROM facturas f
             LEFT JOIN facturas fr ON fr.id = f.documento_referencia_id
             LEFT JOIN clientes c ON c.id = f.cliente_id
             LEFT JOIN sucursales s ON s.id = f.sucursal_id
             LEFT JOIN empresas e ON e.id = f.empresa_id
             LEFT JOIN ventas v ON v.id = f.venta_id
             LEFT JOIN usuarios u ON u.id = v.usuario_id
             LEFT JOIN usuarios ua ON ua.id = f.anulado_por_usuario_id
             WHERE f.empresa_id = :empresa_id
               AND f.venta_id = :venta_id
               AND f.tipo_documento = "factura"
             ORDER BY f.id DESC
             LIMIT 1'
        );
        $stmt->execute([
            ':empresa_id' => $companyId,
            ':venta_id' => $saleId,
        ]);

        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function findByIdWithRelations(int $companyId, int $documentId): ?array
    {
        $stmt = $this->db()->prepare(
            'SELECT
                f.*,
                fr.numero AS documento_referencia_numero,
                c.nombre AS cliente_nombre,
                c.documento AS cliente_documento,
                c.email AS cliente_email,
                c.telefono AS cliente_telefono,
                s.nombre AS sucursal_nombre,
                e.nombre AS empresa_nombre,
                e.nit AS empresa_nit,
                e.email AS empresa_email,
                e.telefono AS empresa_telefono,
                e.direccion AS empresa_direccion,
                e.logo AS empresa_logo,
                v.fecha AS venta_fecha,
                v.subtotal AS venta_subtotal,
                v.descuento AS venta_descuento,
                v.impuestos AS venta_impuestos,
                v.total AS venta_total,
                (
                    SELECT GROUP_CONCAT(DISTINCT vp.metodo_pago ORDER BY vp.metodo_pago SEPARATOR ", ")
                    FROM venta_pagos vp
                    WHERE vp.venta_id = v.id
                      AND vp.empresa_id = v.empresa_id
                ) AS metodos_pago,
                (
                    SELECT COALESCE(SUM(vp2.monto), 0)
                    FROM venta_pagos vp2
                    WHERE vp2.venta_id = v.id
                      AND vp2.empresa_id = v.empresa_id
                ) AS total_pagado,
                u.nombre AS cajero,
                ua.nombre AS anulado_por_nombre
             FROM facturas f
             LEFT JOIN facturas fr ON fr.id = f.documento_referencia_id
             LEFT JOIN clientes c ON c.id = f.cliente_id
             LEFT JOIN sucursales s ON s.id = f.sucursal_id
             LEFT JOIN empresas e ON e.id = f.empresa_id
             LEFT JOIN ventas v ON v.id = f.venta_id
             LEFT JOIN usuarios u ON u.id = v.usuario_id
             LEFT JOIN usuarios ua ON ua.id = f.anulado_por_usuario_id
             WHERE f.empresa_id = :empresa_id
               AND f.id = :documento_id
             LIMIT 1'
        );
        $stmt->execute([
            ':empresa_id' => $companyId,
            ':documento_id' => $documentId,
        ]);

        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function listBySaleId(int $companyId, int $saleId): array
    {
        $stmt = $this->db()->prepare(
            'SELECT
                f.id,
                f.venta_id,
                f.tipo_documento,
                f.numero,
                f.subtotal,
                f.impuestos,
                f.total,
                f.estado,
                f.motivo_documento,
                f.anulado_motivo,
                f.anulado_at,
                f.fecha_emision,
                f.documento_referencia_id,
                fr.numero AS documento_referencia_numero
             FROM facturas f
             LEFT JOIN facturas fr ON fr.id = f.documento_referencia_id
             WHERE f.empresa_id = :empresa_id
               AND f.venta_id = :venta_id
             ORDER BY f.id ASC'
        );
        $stmt->execute([
            ':empresa_id' => $companyId,
            ':venta_id' => $saleId,
        ]);

        return $stmt->fetchAll() ?: [];
    }

    public function trailTotalsBySaleId(int $companyId, int $saleId): array
    {
        $stmt = $this->db()->prepare(
            'SELECT
                COALESCE(SUM(
                    CASE
                        WHEN tipo_documento = "factura" AND estado <> "anulada" THEN total
                        ELSE 0
                    END
                ), 0) AS total_facturado,
                COALESCE(SUM(
                    CASE
                        WHEN tipo_documento = "nota_credito" AND estado <> "anulada" THEN total
                        ELSE 0
                    END
                ), 0) AS total_notas_credito,
                COALESCE(SUM(
                    CASE
                        WHEN tipo_documento = "nota_debito" AND estado <> "anulada" THEN total
                        ELSE 0
                    END
                ), 0) AS total_notas_debito
             FROM facturas
             WHERE empresa_id = :empresa_id
               AND venta_id = :venta_id'
        );
        $stmt->execute([
            ':empresa_id' => $companyId,
            ':venta_id' => $saleId,
        ]);

        $row = $stmt->fetch() ?: [];
        $facturado = (float) ($row['total_facturado'] ?? 0);
        $credito = (float) ($row['total_notas_credito'] ?? 0);
        $debito = (float) ($row['total_notas_debito'] ?? 0);

        return [
            'total_facturado' => $facturado,
            'total_notas_credito' => $credito,
            'total_notas_debito' => $debito,
            'total_neto_documental' => $facturado + $debito - $credito,
        ];
    }
}
