-- ============================================
-- MCH-028: Marketplace de Proveedores
-- Schema: marketplace
-- Tablas: suppliers, supplier_products, supplier_orders, supplier_order_items, supplier_reviews
-- ============================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS marketplace;

-- ============================================
-- SUPPLIERS (Proveedores)
-- ============================================

CREATE TABLE IF NOT EXISTS marketplace.suppliers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Datos basicos
    name VARCHAR(200) NOT NULL,
    legal_name VARCHAR(300),
    rfc VARCHAR(13),

    -- Categorias que maneja (ej: bebidas, botanas, lacteos)
    categories TEXT[] DEFAULT '{}',

    -- Zonas de cobertura (codigos postales o zonas)
    coverage_zones TEXT[] DEFAULT '{}',

    -- Contacto
    contact_name VARCHAR(200),
    contact_phone VARCHAR(20),
    contact_email VARCHAR(200),
    contact_whatsapp VARCHAR(20),

    -- Direccion
    address TEXT,
    city VARCHAR(100),
    state VARCHAR(100),
    zip_code VARCHAR(10),

    -- Branding
    logo_url TEXT,
    banner_url TEXT,
    description TEXT,

    -- Configuracion
    min_order_amount DECIMAL(10, 2) DEFAULT 0,
    delivery_fee DECIMAL(10, 2) DEFAULT 0,
    free_delivery_min DECIMAL(10, 2),
    delivery_days TEXT[] DEFAULT '{}', -- Dias de entrega
    lead_time_days INT DEFAULT 1, -- Dias para entrega

    -- Verificacion y rating
    verified BOOLEAN DEFAULT FALSE,
    verified_at TIMESTAMPTZ,
    rating DECIMAL(2, 1) DEFAULT 0,
    total_reviews INT DEFAULT 0,
    total_orders INT DEFAULT 0,

    -- Estado
    status VARCHAR(20) DEFAULT 'pending', -- pending, active, suspended, inactive

    -- Usuario asociado (para portal de proveedor)
    user_id UUID,

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_suppliers_status ON marketplace.suppliers(status);
CREATE INDEX IF NOT EXISTS idx_suppliers_categories ON marketplace.suppliers USING GIN(categories);
CREATE INDEX IF NOT EXISTS idx_suppliers_coverage ON marketplace.suppliers USING GIN(coverage_zones);
CREATE INDEX IF NOT EXISTS idx_suppliers_rating ON marketplace.suppliers(rating DESC);

-- ============================================
-- SUPPLIER_PRODUCTS (Productos de Proveedores)
-- ============================================

CREATE TABLE IF NOT EXISTS marketplace.supplier_products (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    supplier_id UUID NOT NULL REFERENCES marketplace.suppliers(id) ON DELETE CASCADE,

    -- Datos del producto
    name VARCHAR(300) NOT NULL,
    description TEXT,
    sku VARCHAR(100),
    barcode VARCHAR(50),

    -- Categoria
    category VARCHAR(100),
    subcategory VARCHAR(100),

    -- Imagen
    image_url TEXT,

    -- Precios (para mayoreo)
    unit_price DECIMAL(10, 2) NOT NULL,
    unit_type VARCHAR(50) DEFAULT 'pieza', -- pieza, caja, paquete, kg, litro

    -- Cantidad minima de pedido
    min_quantity INT DEFAULT 1,

    -- Precios escalonados (JSON)
    tiered_pricing JSONB DEFAULT '[]', -- [{min: 10, price: 15.00}, {min: 50, price: 14.00}]

    -- Disponibilidad
    in_stock BOOLEAN DEFAULT TRUE,
    stock_quantity INT,

    -- Estado
    active BOOLEAN DEFAULT TRUE,

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_supplier_products_supplier ON marketplace.supplier_products(supplier_id);
CREATE INDEX IF NOT EXISTS idx_supplier_products_category ON marketplace.supplier_products(category);
CREATE INDEX IF NOT EXISTS idx_supplier_products_barcode ON marketplace.supplier_products(barcode) WHERE barcode IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_supplier_products_active ON marketplace.supplier_products(active);

-- ============================================
-- SUPPLIER_ORDERS (Pedidos a Proveedores)
-- ============================================

CREATE TABLE IF NOT EXISTS marketplace.supplier_orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    supplier_id UUID NOT NULL REFERENCES marketplace.suppliers(id),

    -- Numero de orden
    order_number SERIAL,

    -- Estado del pedido
    status VARCHAR(30) DEFAULT 'pending',
    -- pending, confirmed, preparing, shipped, delivered, cancelled, rejected

    -- Montos
    subtotal DECIMAL(12, 2) NOT NULL,
    delivery_fee DECIMAL(10, 2) DEFAULT 0,
    discount DECIMAL(10, 2) DEFAULT 0,
    total DECIMAL(12, 2) NOT NULL,

    -- Entrega
    delivery_address TEXT NOT NULL,
    delivery_city VARCHAR(100),
    delivery_zip VARCHAR(10),
    delivery_phone VARCHAR(20),
    delivery_contact VARCHAR(200),

    -- Programacion
    requested_date DATE,
    confirmed_date DATE,
    estimated_delivery TIMESTAMPTZ,
    delivered_at TIMESTAMPTZ,

    -- Notas
    notes TEXT,
    supplier_notes TEXT,

    -- Cancelacion
    cancelled_at TIMESTAMPTZ,
    cancel_reason TEXT,
    cancelled_by VARCHAR(20), -- tenant, supplier

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_supplier_orders_tenant ON marketplace.supplier_orders(tenant_id);
CREATE INDEX IF NOT EXISTS idx_supplier_orders_supplier ON marketplace.supplier_orders(supplier_id);
CREATE INDEX IF NOT EXISTS idx_supplier_orders_status ON marketplace.supplier_orders(status);
CREATE INDEX IF NOT EXISTS idx_supplier_orders_created ON marketplace.supplier_orders(created_at DESC);

-- ============================================
-- SUPPLIER_ORDER_ITEMS (Items de Pedidos)
-- ============================================

CREATE TABLE IF NOT EXISTS marketplace.supplier_order_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_id UUID NOT NULL REFERENCES marketplace.supplier_orders(id) ON DELETE CASCADE,
    product_id UUID NOT NULL REFERENCES marketplace.supplier_products(id),

    -- Snapshot del producto al momento del pedido
    product_name VARCHAR(300) NOT NULL,
    product_sku VARCHAR(100),

    -- Cantidad y precios
    quantity INT NOT NULL,
    unit_price DECIMAL(10, 2) NOT NULL,
    total DECIMAL(12, 2) NOT NULL,

    -- Notas
    notes TEXT,

    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_supplier_order_items_order ON marketplace.supplier_order_items(order_id);
CREATE INDEX IF NOT EXISTS idx_supplier_order_items_product ON marketplace.supplier_order_items(product_id);

-- ============================================
-- SUPPLIER_REVIEWS (Resenas de Proveedores)
-- ============================================

CREATE TABLE IF NOT EXISTS marketplace.supplier_reviews (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    supplier_id UUID NOT NULL REFERENCES marketplace.suppliers(id) ON DELETE CASCADE,
    order_id UUID REFERENCES marketplace.supplier_orders(id),

    -- Rating
    rating INT NOT NULL CHECK (rating >= 1 AND rating <= 5),

    -- Comentario
    title VARCHAR(200),
    comment TEXT,

    -- Aspectos especificos (1-5)
    rating_quality INT CHECK (rating_quality >= 1 AND rating_quality <= 5),
    rating_delivery INT CHECK (rating_delivery >= 1 AND rating_delivery <= 5),
    rating_price INT CHECK (rating_price >= 1 AND rating_price <= 5),

    -- Respuesta del proveedor
    supplier_response TEXT,
    responded_at TIMESTAMPTZ,

    -- Estado
    verified BOOLEAN DEFAULT FALSE, -- Review de compra verificada
    status VARCHAR(20) DEFAULT 'active', -- active, hidden, flagged

    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_supplier_reviews_supplier ON marketplace.supplier_reviews(supplier_id);
CREATE INDEX IF NOT EXISTS idx_supplier_reviews_tenant ON marketplace.supplier_reviews(tenant_id);
CREATE INDEX IF NOT EXISTS idx_supplier_reviews_rating ON marketplace.supplier_reviews(rating);

-- Constraint: una review por orden
CREATE UNIQUE INDEX IF NOT EXISTS idx_supplier_reviews_order_unique
ON marketplace.supplier_reviews(order_id) WHERE order_id IS NOT NULL;

-- ============================================
-- FAVORITOS
-- ============================================

CREATE TABLE IF NOT EXISTS marketplace.supplier_favorites (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    supplier_id UUID NOT NULL REFERENCES marketplace.suppliers(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW(),

    UNIQUE(tenant_id, supplier_id)
);

CREATE INDEX IF NOT EXISTS idx_supplier_favorites_tenant ON marketplace.supplier_favorites(tenant_id);

-- ============================================
-- FUNCIONES
-- ============================================

-- Actualizar rating del proveedor
CREATE OR REPLACE FUNCTION marketplace.update_supplier_rating()
RETURNS TRIGGER AS $$
BEGIN
    UPDATE marketplace.suppliers
    SET
        rating = (
            SELECT COALESCE(AVG(rating), 0)
            FROM marketplace.supplier_reviews
            WHERE supplier_id = COALESCE(NEW.supplier_id, OLD.supplier_id)
            AND status = 'active'
        ),
        total_reviews = (
            SELECT COUNT(*)
            FROM marketplace.supplier_reviews
            WHERE supplier_id = COALESCE(NEW.supplier_id, OLD.supplier_id)
            AND status = 'active'
        ),
        updated_at = NOW()
    WHERE id = COALESCE(NEW.supplier_id, OLD.supplier_id);

    RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_update_supplier_rating ON marketplace.supplier_reviews;
CREATE TRIGGER trg_update_supplier_rating
AFTER INSERT OR UPDATE OR DELETE ON marketplace.supplier_reviews
FOR EACH ROW EXECUTE FUNCTION marketplace.update_supplier_rating();

-- Actualizar conteo de ordenes del proveedor
CREATE OR REPLACE FUNCTION marketplace.update_supplier_orders_count()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.status = 'delivered' AND (OLD IS NULL OR OLD.status != 'delivered') THEN
        UPDATE marketplace.suppliers
        SET
            total_orders = total_orders + 1,
            updated_at = NOW()
        WHERE id = NEW.supplier_id;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_update_supplier_orders_count ON marketplace.supplier_orders;
CREATE TRIGGER trg_update_supplier_orders_count
AFTER INSERT OR UPDATE ON marketplace.supplier_orders
FOR EACH ROW EXECUTE FUNCTION marketplace.update_supplier_orders_count();

-- Funcion para buscar proveedores por zona
CREATE OR REPLACE FUNCTION marketplace.find_suppliers_by_zone(
    p_zip_code VARCHAR(10),
    p_category VARCHAR(100) DEFAULT NULL,
    p_limit INT DEFAULT 20
)
RETURNS TABLE (
    id UUID,
    name VARCHAR(200),
    logo_url TEXT,
    rating DECIMAL(2, 1),
    total_reviews INT,
    min_order_amount DECIMAL(10, 2),
    delivery_fee DECIMAL(10, 2),
    categories TEXT[]
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        s.id,
        s.name,
        s.logo_url,
        s.rating,
        s.total_reviews,
        s.min_order_amount,
        s.delivery_fee,
        s.categories
    FROM marketplace.suppliers s
    WHERE s.status = 'active'
    AND (p_zip_code = ANY(s.coverage_zones) OR s.coverage_zones = '{}')
    AND (p_category IS NULL OR p_category = ANY(s.categories))
    ORDER BY s.rating DESC, s.total_orders DESC
    LIMIT p_limit;
END;
$$ LANGUAGE plpgsql;

-- Funcion para obtener estadisticas del marketplace (para admin)
CREATE OR REPLACE FUNCTION marketplace.get_marketplace_stats()
RETURNS TABLE (
    total_suppliers BIGINT,
    active_suppliers BIGINT,
    total_products BIGINT,
    total_orders BIGINT,
    total_gmv DECIMAL(14, 2),
    avg_rating DECIMAL(2, 1)
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        (SELECT COUNT(*) FROM marketplace.suppliers),
        (SELECT COUNT(*) FROM marketplace.suppliers WHERE status = 'active'),
        (SELECT COUNT(*) FROM marketplace.supplier_products WHERE active = true),
        (SELECT COUNT(*) FROM marketplace.supplier_orders),
        (SELECT COALESCE(SUM(total), 0) FROM marketplace.supplier_orders WHERE status = 'delivered'),
        (SELECT COALESCE(AVG(s.rating), 0) FROM marketplace.suppliers s WHERE s.status = 'active');
END;
$$ LANGUAGE plpgsql;

-- Permisos
GRANT USAGE ON SCHEMA marketplace TO michangarrito_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA marketplace TO michangarrito_app;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA marketplace TO michangarrito_app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA marketplace TO michangarrito_app;

COMMENT ON SCHEMA marketplace IS 'MCH-028: Marketplace B2B de proveedores';
COMMENT ON TABLE marketplace.suppliers IS 'Proveedores/distribuidores registrados';
COMMENT ON TABLE marketplace.supplier_products IS 'Catalogo de productos de cada proveedor';
COMMENT ON TABLE marketplace.supplier_orders IS 'Pedidos de tiendas a proveedores';
COMMENT ON TABLE marketplace.supplier_order_items IS 'Items de cada pedido';
COMMENT ON TABLE marketplace.supplier_reviews IS 'Resenas y calificaciones de proveedores';
