-- ============================================
-- SALONOS - KIOSK IMPLEMENTATION
-- Agregar rol 'kiosk' y tabla kiosks al sistema
-- ============================================

-- ============================================
-- AGREGAR ROL 'kiosk' AL ENUM user_role
-- ============================================

DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumlabel = 'kiosk' AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'user_role')) THEN
        ALTER TYPE user_role ADD VALUE 'kiosk' BEFORE 'customer';
    END IF;
END $$;

-- ============================================
-- CREAR TABLA KIOSKS
-- ============================================

CREATE TABLE IF NOT EXISTS kiosks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    location_id UUID NOT NULL REFERENCES locations(id) ON DELETE CASCADE,
    device_name VARCHAR(100) NOT NULL UNIQUE,
    display_name VARCHAR(100) NOT NULL,
    api_key VARCHAR(64) UNIQUE NOT NULL,
    ip_address INET,
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================
-- CREAR ÍNDICES PARA KIOSKS
-- ============================================

CREATE INDEX IF NOT EXISTS idx_kiosks_location ON kiosks(location_id);
CREATE INDEX IF NOT EXISTS idx_kiosks_api_key ON kiosks(api_key);
CREATE INDEX IF NOT EXISTS idx_kiosks_active ON kiosks(is_active);
CREATE INDEX IF NOT EXISTS idx_kiosks_ip ON kiosks(ip_address);

-- ============================================
-- CREAR TRIGGER UPDATE_AT PARA KIOSKS
-- ============================================

DROP TRIGGER IF EXISTS kiosks_updated_at ON kiosks;
CREATE TRIGGER kiosks_updated_at BEFORE UPDATE ON kiosks
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

-- ============================================
-- FUNCIÓN PARA GENERAR API KEY
-- ============================================

CREATE OR REPLACE FUNCTION generate_kiosk_api_key()
RETURNS VARCHAR(64) AS $$
DECLARE
    chars VARCHAR(62) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    v_api_key VARCHAR(64);
    attempts INT := 0;
    max_attempts INT := 10;
BEGIN
    LOOP
        v_api_key := '';
        FOR i IN 1..64 LOOP
            v_api_key := v_api_key || substr(chars, floor(random() * 62 + 1)::INT, 1);
        END LOOP;

        IF NOT EXISTS (SELECT 1 FROM kiosks WHERE api_key = v_api_key) THEN
            RETURN v_api_key;
        END IF;

        attempts := attempts + 1;
        IF attempts >= max_attempts THEN
            RAISE EXCEPTION 'Failed to generate unique api_key after % attempts', max_attempts;
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- FUNCIÓN PARA OBTENER KIOSK ACTUAL
-- ============================================

CREATE OR REPLACE FUNCTION get_current_kiosk_id()
RETURNS UUID AS $$
    DECLARE
        current_kiosk_id UUID;
        api_key_param TEXT;
    BEGIN
        api_key_param := current_setting('app.kiosk_api_key', true);
        
        IF api_key_param IS NOT NULL THEN
            SELECT id INTO current_kiosk_id
            FROM kiosks
            WHERE api_key = api_key_param AND is_active = true
            LIMIT 1;
        END IF;
        
        RETURN current_kiosk_id;
    END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- FUNCIÓN HELPER is_kiosk()
-- ============================================

CREATE OR REPLACE FUNCTION is_kiosk()
RETURNS BOOLEAN AS $$
BEGIN
    RETURN get_current_kiosk_id() IS NOT NULL;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- FUNCIÓN PARA OBTENER LOCATION DEL KIOSK ACTUAL
-- ============================================

CREATE OR REPLACE FUNCTION get_current_kiosk_location_id()
RETURNS UUID AS $$
    DECLARE
        location_id UUID;
    BEGIN
        SELECT location_id INTO location_id
        FROM kiosks
        WHERE id = get_current_kiosk_id();
        
        RETURN location_id;
    END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- ENABLE RLS ON KIOSKS
-- ============================================

ALTER TABLE kiosks ENABLE ROW LEVEL SECURITY;

-- POLICY PARA KIOSKS: Solo admin/manager pueden ver/modificar
DROP POLICY IF EXISTS "kiosks_select_admin_manager" ON kiosks;
CREATE POLICY "kiosks_select_admin_manager" ON kiosks
    FOR SELECT
    USING (get_current_user_role() IN ('admin', 'manager'));

DROP POLICY IF EXISTS "kiosks_modify_admin_manager" ON kiosks;
CREATE POLICY "kiosks_modify_admin_manager" ON kiosks
    FOR ALL
    USING (get_current_user_role() IN ('admin', 'manager'));

-- ============================================
-- AUDIT LOG TRIGGER PARA KIOSKS
-- ============================================

DROP TRIGGER IF EXISTS audit_kiosks ON kiosks;
CREATE TRIGGER audit_kiosks AFTER INSERT OR UPDATE OR DELETE ON kiosks
    FOR EACH ROW EXECUTE FUNCTION log_audit();

-- ============================================
-- POLÍTICAS RLS PARA KIOSK EN OTRAS TABLAS
-- ============================================

-- BOOKINGS: Kiosk puede ver bookings de su location (limitado)
DROP POLICY IF EXISTS "bookings_select_kiosk" ON bookings;
CREATE POLICY "bookings_select_kiosk" ON bookings
    FOR SELECT
    USING (
        is_kiosk() AND
        location_id = get_current_kiosk_location_id() AND
        status IN ('pending', 'confirmed')
    );

DROP POLICY IF EXISTS "bookings_create_kiosk" ON bookings;
CREATE POLICY "bookings_create_kiosk" ON bookings
    FOR INSERT
    WITH CHECK (
        is_kiosk() AND
        location_id = get_current_kiosk_location_id()
    );

DROP POLICY IF EXISTS "bookings_confirm_kiosk" ON bookings;
CREATE POLICY "bookings_confirm_kiosk" ON bookings
    FOR UPDATE
    USING (
        is_kiosk() AND
        location_id = get_current_kiosk_location_id() AND
        status = 'pending'
    )
    WITH CHECK (
        is_kiosk() AND
        location_id = get_current_kiosk_location_id() AND
        status = 'confirmed'
    );

-- RESOURCES: Kiosk puede ver recursos disponibles de su location
DROP POLICY IF EXISTS "resources_select_kiosk" ON resources;
CREATE POLICY "resources_select_kiosk" ON resources
    FOR SELECT
    USING (
        is_kiosk() AND
        location_id = get_current_kiosk_location_id() AND
        is_active = true
    );

-- SERVICES: Kiosk puede ver servicios activos (policy ya existe, pero agregamos comentario)
-- La policy services_select_all permite a cualquier usuario ver servicios activos

-- LOCATIONS: Kiosk solo puede ver su propia location
DROP POLICY IF EXISTS "locations_select_kiosk" ON locations;
CREATE POLICY "locations_select_kiosk" ON locations
    FOR SELECT
    USING (
        is_kiosk() AND
        id = get_current_kiosk_location_id()
    );

-- CUSTOMERS: Kiosk NO puede ver datos de clientes (PII restriction)
-- No se crea policy, por lo que el acceso es denegado

-- ============================================
-- FUNCIÓN PARA CREAR KIOSK (para admin/manager)
-- ============================================

CREATE OR REPLACE FUNCTION create_kiosk(
    p_location_id UUID,
    p_device_name VARCHAR(100),
    p_display_name VARCHAR(100),
    p_ip_address INET DEFAULT NULL
)
RETURNS JSONB AS $$
DECLARE
    new_kiosk_id UUID;
    new_api_key VARCHAR(64);
BEGIN
    IF get_current_user_role() NOT IN ('admin', 'manager') THEN
        RAISE EXCEPTION 'Only admin or manager can create kiosks';
    END IF;

    new_api_key := generate_kiosk_api_key();

    INSERT INTO kiosks (location_id, device_name, display_name, api_key, ip_address)
    VALUES (p_location_id, p_device_name, p_display_name, new_api_key, p_ip_address)
    RETURNING id INTO new_kiosk_id;

    RETURN jsonb_build_object(
        'kiosk_id', new_kiosk_id,
        'api_key', new_api_key,
        'message', 'Kiosk created successfully. Save the API key securely as it will not be shown again.'
    )::JSONB;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- FUNCIÓN PARA OBTENER RECURSOS DISPONIBLES (CON PRIORIDAD)
-- ============================================

CREATE OR REPLACE FUNCTION get_available_resources_with_priority(
    p_location_id UUID,
    p_start_time TIMESTAMPTZ,
    p_end_time TIMESTAMPTZ
)
RETURNS TABLE (
    resource_id UUID,
    resource_name VARCHAR,
    resource_type resource_type,
    capacity INTEGER,
    priority INTEGER
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        r.id AS resource_id,
        r.name AS resource_name,
        r.type AS resource_type,
        r.capacity,
        CASE r.type
            WHEN 'station' THEN 1
            WHEN 'room' THEN 2
            WHEN 'equipment' THEN 3
        END AS priority
    FROM resources r
    WHERE r.location_id = p_location_id
    AND r.is_active = true
    AND NOT EXISTS (
        SELECT 1
        FROM bookings b
        WHERE b.resource_id = r.id
        AND b.status NOT IN ('cancelled', 'no_show')
        AND (
            (b.start_time_utc < p_end_time AND b.end_time_utc > p_start_time)
        )
    )
    ORDER BY priority, r.name;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- SEED DATA: KIOSKS DE PRUEBA
-- ============================================
-- Nota: Los kiosks se crearán manualmente vía UI de enrollment

-- ============================================
-- VERIFICACIÓN
-- ============================================

DO $$
BEGIN
    RAISE NOTICE '===========================================';
    RAISE NOTICE 'SALONOS - KIOSK IMPLEMENTATION COMPLETED';
    RAISE NOTICE '===========================================';
    RAISE NOTICE '✅ user_role enum updated with kiosk';
    RAISE NOTICE '✅ kiosks table created';
    RAISE NOTICE '✅ Indexes created';
    RAISE NOTICE '✅ Functions created:';
    RAISE NOTICE '   - generate_kiosk_api_key()';
    RAISE NOTICE '   - get_current_kiosk_id()';
    RAISE NOTICE '   - is_kiosk()';
    RAISE NOTICE '   - get_current_kiosk_location_id()';
    RAISE NOTICE '   - create_kiosk()';
    RAISE NOTICE '   - get_available_resources_with_priority()';
    RAISE NOTICE '✅ RLS policies created for kiosk';
    RAISE NOTICE '===========================================';
    RAISE NOTICE 'NEXT STEPS:';
    RAISE NOTICE '1. Create additional kiosks using:';
    RAISE NOTICE '   SELECT create_kiosk(location_id, device_name, display_name);';
    RAISE NOTICE '2. Test kiosk authentication via API';
    RAISE NOTICE '3. Implement API routes in Next.js';
    RAISE NOTICE '===========================================';
END
$$;
