-- Migration 026: item_frequency.weight column + admin-only RPCs (Fase 15.1)
--
-- Adds a curation knob on top of the existing `use_count` suggestion ordering.
-- Admins can promote (positive weight) or hide (negative weight) specific
-- items in the per-collective suggestion dropdown. The client UI exposes a
-- 3-way Hide / Normal / Boost control mapped to -50 / 0 / 50, but the column
-- accepts any integer so future granularity (e.g. "strong boost") does not
-- require a schema migration.
--
-- Write path: same all-deny RLS as migration 006 — clients never UPDATE the
-- column directly. The two SECURITY DEFINER RPCs below are the only entry
-- points. Both gate on `collective_members.role = 'admin'`.

ALTER TABLE public.item_frequency
    ADD COLUMN weight integer NOT NULL DEFAULT 0;

-- Re-create the suggestion index to include weight first. The old index was a
-- prefix of this one — drop it so we don't carry two overlapping indexes.
DROP INDEX IF EXISTS public.item_frequency_collective_count_idx;

CREATE INDEX item_frequency_collective_order_idx
    ON public.item_frequency (collective_id, weight DESC, use_count DESC, last_used_at DESC);

-- ── RPC: admin upsert of weight ─────────────────────────────────────────────
-- Upsert semantics: if the (collective_id, name) row doesn't exist yet,
-- insert it with use_count=0 and the requested weight. Useful for seeding
-- the catalog before any list actually mentions the item.

CREATE OR REPLACE FUNCTION public.set_item_frequency_weight(
    p_collective_id uuid,
    p_name          text,
    p_weight        integer
) RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public, auth
AS $$
DECLARE
    v_role text;
    v_norm text := lower(trim(p_name));
BEGIN
    IF auth.uid() IS NULL THEN
        RAISE EXCEPTION 'not authenticated' USING ERRCODE = 'P0001';
    END IF;
    IF v_norm = '' THEN
        RAISE EXCEPTION 'name must not be empty' USING ERRCODE = 'P0001';
    END IF;

    SELECT role INTO v_role
    FROM   public.collective_members
    WHERE  collective_id = p_collective_id
    AND    user_id       = auth.uid();

    IF v_role IS DISTINCT FROM 'admin' THEN
        RAISE EXCEPTION 'only admins can manage common items' USING ERRCODE = 'P0002';
    END IF;

    INSERT INTO public.item_frequency (collective_id, name, use_count, weight, last_used_at)
    VALUES (p_collective_id, v_norm, 0, p_weight, now())
    ON CONFLICT (collective_id, name) DO UPDATE SET
        weight = EXCLUDED.weight;
END;
$$;

GRANT EXECUTE ON FUNCTION public.set_item_frequency_weight(uuid, text, integer)
    TO authenticated;

-- ── RPC: admin purge ────────────────────────────────────────────────────────
-- Removes the row from item_frequency only. Does NOT touch shopping_items
-- (the existing items in lists stay; future inserts will recreate this row
-- with weight=0 via the existing trigger).

CREATE OR REPLACE FUNCTION public.purge_item_frequency(
    p_collective_id uuid,
    p_name          text
) RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public, auth
AS $$
DECLARE
    v_role text;
    v_norm text := lower(trim(p_name));
BEGIN
    IF auth.uid() IS NULL THEN
        RAISE EXCEPTION 'not authenticated' USING ERRCODE = 'P0001';
    END IF;

    SELECT role INTO v_role
    FROM   public.collective_members
    WHERE  collective_id = p_collective_id
    AND    user_id       = auth.uid();

    IF v_role IS DISTINCT FROM 'admin' THEN
        RAISE EXCEPTION 'only admins can purge common items' USING ERRCODE = 'P0002';
    END IF;

    DELETE FROM public.item_frequency
    WHERE collective_id = p_collective_id
    AND   name          = v_norm;
END;
$$;

GRANT EXECUTE ON FUNCTION public.purge_item_frequency(uuid, text) TO authenticated;
