-- ============================================
-- MCH-016: Entregas a Domicilio
-- Schema: delivery
-- Version: 1.0.0
-- Created: 2026-01-18
-- ============================================

-- Create schema if not exists
CREATE SCHEMA IF NOT EXISTS delivery;

-- ============================================
-- Table: delivery_zones
-- Delivery zone configuration (radius or polygon)
-- ============================================

CREATE TABLE IF NOT EXISTS delivery.delivery_zones (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES core.tenants(id) ON DELETE CASCADE,
    name VARCHAR(100) NOT NULL,
    type VARCHAR(20) NOT NULL DEFAULT 'radius' CHECK (type IN ('radius', 'polygon')),
    coordinates JSONB,
    delivery_fee DECIMAL(10,2) NOT NULL DEFAULT 0,
    min_order DECIMAL(10,2) NOT NULL DEFAULT 0,
    estimated_time_minutes INTEGER NOT NULL DEFAULT 30,
    active BOOLEAN NOT NULL DEFAULT true,
    priority INTEGER NOT NULL DEFAULT 0,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Indexes for delivery_zones
CREATE INDEX IF NOT EXISTS idx_delivery_zones_tenant_active
    ON delivery.delivery_zones(tenant_id, active);

CREATE INDEX IF NOT EXISTS idx_delivery_zones_priority
    ON delivery.delivery_zones(tenant_id, priority);

-- Comments
COMMENT ON TABLE delivery.delivery_zones IS 'Delivery zone configuration with coverage areas';
COMMENT ON COLUMN delivery.delivery_zones.type IS 'Zone type: radius or polygon';
COMMENT ON COLUMN delivery.delivery_zones.coordinates IS 'JSON: center+radiusKm for radius, polygon array for polygon, colonias list for colonia-based';
COMMENT ON COLUMN delivery.delivery_zones.priority IS 'Lower number = higher priority for overlapping zones';

-- ============================================
-- Table: deliveries
-- Delivery tracking for orders
-- ============================================

CREATE TABLE IF NOT EXISTS delivery.deliveries (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES core.tenants(id) ON DELETE CASCADE,
    order_id UUID NOT NULL REFERENCES orders.orders(id) ON DELETE CASCADE,
    zone_id UUID REFERENCES delivery.delivery_zones(id) ON DELETE SET NULL,

    -- Assignment
    assigned_to UUID,
    assigned_to_name VARCHAR(100),

    -- Status
    status VARCHAR(20) NOT NULL DEFAULT 'pending'
        CHECK (status IN ('pending', 'assigned', 'picked_up', 'in_transit', 'arrived', 'delivered', 'failed', 'cancelled')),

    -- Delivery info
    delivery_address TEXT NOT NULL,
    delivery_coordinates JSONB,
    delivery_notes TEXT,
    customer_phone VARCHAR(20),
    delivery_fee DECIMAL(10,2) NOT NULL DEFAULT 0,
    estimated_minutes INTEGER,

    -- Timestamps for tracking
    assigned_at TIMESTAMPTZ,
    picked_up_at TIMESTAMPTZ,
    in_transit_at TIMESTAMPTZ,
    arrived_at TIMESTAMPTZ,
    delivered_at TIMESTAMPTZ,

    -- Proof of delivery
    proof_photo_url TEXT,
    signature_url TEXT,
    recipient_name VARCHAR(100),

    -- Failure handling
    failure_reason TEXT,
    retry_count INTEGER NOT NULL DEFAULT 0,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Indexes for deliveries
CREATE INDEX IF NOT EXISTS idx_deliveries_tenant_status
    ON delivery.deliveries(tenant_id, status);

CREATE INDEX IF NOT EXISTS idx_deliveries_order
    ON delivery.deliveries(order_id);

CREATE INDEX IF NOT EXISTS idx_deliveries_assigned
    ON delivery.deliveries(assigned_to, status);

CREATE INDEX IF NOT EXISTS idx_deliveries_created
    ON delivery.deliveries(tenant_id, created_at DESC);

-- Unique constraint: one delivery per order
CREATE UNIQUE INDEX IF NOT EXISTS idx_deliveries_order_unique
    ON delivery.deliveries(order_id);

-- Comments
COMMENT ON TABLE delivery.deliveries IS 'Delivery tracking for orders with status history';
COMMENT ON COLUMN delivery.deliveries.status IS 'Delivery status: pending->assigned->picked_up->in_transit->arrived->delivered';
COMMENT ON COLUMN delivery.deliveries.delivery_coordinates IS 'JSON with lat/lng for delivery location';
COMMENT ON COLUMN delivery.deliveries.proof_photo_url IS 'Photo proof of delivery';
COMMENT ON COLUMN delivery.deliveries.signature_url IS 'Digital signature from recipient';

-- ============================================
-- Table: delivery_status_history
-- Audit trail for delivery status changes
-- ============================================

CREATE TABLE IF NOT EXISTS delivery.delivery_status_history (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    delivery_id UUID NOT NULL REFERENCES delivery.deliveries(id) ON DELETE CASCADE,
    status VARCHAR(20) NOT NULL,
    previous_status VARCHAR(20),
    changed_by UUID,
    changed_by_name VARCHAR(100),
    notes TEXT,
    location JSONB,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Indexes for status history
CREATE INDEX IF NOT EXISTS idx_delivery_status_history_delivery
    ON delivery.delivery_status_history(delivery_id, created_at DESC);

-- Comments
COMMENT ON TABLE delivery.delivery_status_history IS 'Audit trail for delivery status changes';
COMMENT ON COLUMN delivery.delivery_status_history.location IS 'GPS coordinates when status changed';

-- ============================================
-- Table: drivers
-- Driver registry for delivery assignments
-- ============================================

CREATE TABLE IF NOT EXISTS delivery.drivers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES core.tenants(id) ON DELETE CASCADE,
    user_id UUID,
    name VARCHAR(100) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    vehicle_type VARCHAR(50),
    vehicle_plate VARCHAR(20),
    photo_url TEXT,
    status VARCHAR(20) NOT NULL DEFAULT 'available'
        CHECK (status IN ('available', 'busy', 'offline', 'inactive')),
    current_location JSONB,
    last_seen_at TIMESTAMPTZ,
    active BOOLEAN NOT NULL DEFAULT true,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Indexes for drivers
CREATE INDEX IF NOT EXISTS idx_drivers_tenant_status
    ON delivery.drivers(tenant_id, status);

CREATE INDEX IF NOT EXISTS idx_drivers_tenant_active
    ON delivery.drivers(tenant_id, active);

-- Comments
COMMENT ON TABLE delivery.drivers IS 'Driver registry for delivery operations';
COMMENT ON COLUMN delivery.drivers.vehicle_type IS 'Type of vehicle: moto, bici, auto, pie';
COMMENT ON COLUMN delivery.drivers.current_location IS 'Last known GPS location';

-- ============================================
-- Triggers for updated_at
-- ============================================

-- delivery_zones
CREATE OR REPLACE FUNCTION delivery.update_delivery_zones_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trigger_delivery_zones_updated_at ON delivery.delivery_zones;
CREATE TRIGGER trigger_delivery_zones_updated_at
    BEFORE UPDATE ON delivery.delivery_zones
    FOR EACH ROW EXECUTE FUNCTION delivery.update_delivery_zones_updated_at();

-- deliveries
CREATE OR REPLACE FUNCTION delivery.update_deliveries_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trigger_deliveries_updated_at ON delivery.deliveries;
CREATE TRIGGER trigger_deliveries_updated_at
    BEFORE UPDATE ON delivery.deliveries
    FOR EACH ROW EXECUTE FUNCTION delivery.update_deliveries_updated_at();

-- drivers
CREATE OR REPLACE FUNCTION delivery.update_drivers_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trigger_drivers_updated_at ON delivery.drivers;
CREATE TRIGGER trigger_drivers_updated_at
    BEFORE UPDATE ON delivery.drivers
    FOR EACH ROW EXECUTE FUNCTION delivery.update_drivers_updated_at();

-- ============================================
-- Trigger for automatic status history
-- ============================================

CREATE OR REPLACE FUNCTION delivery.log_delivery_status_change()
RETURNS TRIGGER AS $$
BEGIN
    IF OLD.status IS DISTINCT FROM NEW.status THEN
        INSERT INTO delivery.delivery_status_history (
            delivery_id,
            status,
            previous_status,
            changed_by,
            notes
        ) VALUES (
            NEW.id,
            NEW.status,
            OLD.status,
            NULL, -- Would need to get from context
            CASE
                WHEN NEW.status = 'failed' THEN NEW.failure_reason
                ELSE NULL
            END
        );
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trigger_delivery_status_history ON delivery.deliveries;
CREATE TRIGGER trigger_delivery_status_history
    AFTER UPDATE ON delivery.deliveries
    FOR EACH ROW EXECUTE FUNCTION delivery.log_delivery_status_change();

-- ============================================
-- Default zone templates for new tenants
-- ============================================

-- This function can be called to set up default zones for a tenant
CREATE OR REPLACE FUNCTION delivery.setup_default_zones(p_tenant_id UUID, p_center_lat DECIMAL, p_center_lng DECIMAL)
RETURNS void AS $$
BEGIN
    -- Zone 1: Centro (0-2 km) - Free delivery
    INSERT INTO delivery.delivery_zones (tenant_id, name, type, coordinates, delivery_fee, min_order, estimated_time_minutes, priority)
    VALUES (
        p_tenant_id,
        'Centro (0-2 km)',
        'radius',
        jsonb_build_object('center', jsonb_build_object('lat', p_center_lat, 'lng', p_center_lng), 'radiusKm', 2),
        0,
        0,
        15,
        1
    );

    -- Zone 2: Cercano (2-5 km) - $20 delivery
    INSERT INTO delivery.delivery_zones (tenant_id, name, type, coordinates, delivery_fee, min_order, estimated_time_minutes, priority)
    VALUES (
        p_tenant_id,
        'Cercano (2-5 km)',
        'radius',
        jsonb_build_object('center', jsonb_build_object('lat', p_center_lat, 'lng', p_center_lng), 'radiusKm', 5),
        20,
        50,
        25,
        2
    );

    -- Zone 3: Lejano (5-10 km) - $35 delivery
    INSERT INTO delivery.delivery_zones (tenant_id, name, type, coordinates, delivery_fee, min_order, estimated_time_minutes, priority)
    VALUES (
        p_tenant_id,
        'Lejano (5-10 km)',
        'radius',
        jsonb_build_object('center', jsonb_build_object('lat', p_center_lat, 'lng', p_center_lng), 'radiusKm', 10),
        35,
        100,
        40,
        3
    );
END;
$$ LANGUAGE plpgsql;

-- ============================================
-- Grant permissions
-- ============================================

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

-- ============================================
-- Version tracking
-- ============================================

COMMENT ON SCHEMA delivery IS 'MCH-016: Delivery management - zones, tracking, drivers. Version 1.0.0';
