-- =============================================================================
-- MICHANGARRITO - 02 FUNCTIONS
-- =============================================================================
-- Funciones utilitarias del sistema
-- =============================================================================

-- Función para actualizar updated_at automáticamente
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Función IMMUTABLE para convertir TIMESTAMPTZ a DATE
-- Necesaria para índices funcionales sobre campos de fecha
-- Usa timezone fijo America/Mexico_City para consistencia
CREATE OR REPLACE FUNCTION public.timestamptz_to_date(ts TIMESTAMPTZ)
RETURNS DATE AS $$
    SELECT (ts AT TIME ZONE 'America/Mexico_City')::date;
$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;

COMMENT ON FUNCTION public.timestamptz_to_date IS 'Convierte TIMESTAMPTZ a DATE usando timezone America/Mexico_City (IMMUTABLE para indices)';

-- Función para generar número de ticket
CREATE OR REPLACE FUNCTION sales.generate_ticket_number(p_tenant_id UUID)
RETURNS VARCHAR(20) AS $$
DECLARE
    v_date TEXT;
    v_sequence INTEGER;
    v_ticket VARCHAR(20);
BEGIN
    v_date := TO_CHAR(CURRENT_DATE, 'YYMMDD');

    SELECT COALESCE(MAX(
        CAST(SUBSTRING(ticket_number FROM 8) AS INTEGER)
    ), 0) + 1
    INTO v_sequence
    FROM sales.sales
    WHERE tenant_id = p_tenant_id
      AND ticket_number LIKE v_date || '-%';

    v_ticket := v_date || '-' || LPAD(v_sequence::TEXT, 4, '0');

    RETURN v_ticket;
END;
$$ LANGUAGE plpgsql;

-- Función para generar número de pedido
CREATE OR REPLACE FUNCTION orders.generate_order_number(p_tenant_id UUID)
RETURNS VARCHAR(20) AS $$
DECLARE
    v_date TEXT;
    v_sequence INTEGER;
    v_order VARCHAR(20);
BEGIN
    v_date := TO_CHAR(CURRENT_DATE, 'YYMMDD');

    SELECT COALESCE(MAX(
        CAST(SUBSTRING(order_number FROM 8) AS INTEGER)
    ), 0) + 1
    INTO v_sequence
    FROM orders.orders
    WHERE tenant_id = p_tenant_id
      AND order_number LIKE 'P' || v_date || '-%';

    v_order := 'P' || v_date || '-' || LPAD(v_sequence::TEXT, 4, '0');

    RETURN v_order;
END;
$$ LANGUAGE plpgsql;

-- Función para actualizar balance de fiados del cliente
CREATE OR REPLACE FUNCTION customers.update_customer_fiado_balance()
RETURNS TRIGGER AS $$
BEGIN
    UPDATE customers.customers
    SET current_fiado_balance = (
        SELECT COALESCE(SUM(remaining_amount), 0)
        FROM customers.fiados
        WHERE customer_id = COALESCE(NEW.customer_id, OLD.customer_id)
          AND status IN ('pending', 'partial', 'overdue')
    ),
    updated_at = NOW()
    WHERE id = COALESCE(NEW.customer_id, OLD.customer_id);

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Función para actualizar stock después de venta
CREATE OR REPLACE FUNCTION inventory.update_stock_on_sale()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        -- Registrar movimiento de inventario
        INSERT INTO inventory.inventory_movements (
            tenant_id, product_id, movement_type, quantity,
            previous_stock, new_stock, reference_type, reference_id
        )
        SELECT
            s.tenant_id,
            NEW.product_id,
            'sale',
            -NEW.quantity,
            p.stock_quantity,
            p.stock_quantity - NEW.quantity,
            'sale',
            NEW.sale_id
        FROM sales.sales s
        JOIN catalog.products p ON p.id = NEW.product_id
        WHERE s.id = NEW.sale_id;

        -- Actualizar stock del producto
        UPDATE catalog.products
        SET stock_quantity = stock_quantity - NEW.quantity,
            updated_at = NOW()
        WHERE id = NEW.product_id;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
