-- Migration 002: collectives, collective_members, collective_invitations

-- ── Enums ─────────────────────────────────────────────────────────────────────

CREATE TYPE public.member_role AS ENUM ('admin', 'member', 'guest');

-- ── collectives ───────────────────────────────────────────────────────────────

CREATE TABLE public.collectives (
    id         uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    name       text        NOT NULL,
    emoji      text        NOT NULL DEFAULT '🏠',
    created_by uuid        NOT NULL REFERENCES public.users(id) ON DELETE RESTRICT,
    created_at timestamptz NOT NULL DEFAULT now()
);

ALTER TABLE public.collectives ENABLE ROW LEVEL SECURITY;

-- ── collective_members ────────────────────────────────────────────────────────

CREATE TABLE public.collective_members (
    collective_id uuid              NOT NULL REFERENCES public.collectives(id) ON DELETE CASCADE,
    user_id       uuid              NOT NULL REFERENCES public.users(id)       ON DELETE CASCADE,
    role          public.member_role NOT NULL DEFAULT 'member',
    joined_at     timestamptz       NOT NULL DEFAULT now(),
    PRIMARY KEY (collective_id, user_id)
);

ALTER TABLE public.collective_members ENABLE ROW LEVEL SECURITY;

CREATE INDEX collective_members_user_idx ON public.collective_members (user_id);

-- ── collective_invitations ────────────────────────────────────────────────────

CREATE TABLE public.collective_invitations (
    id            uuid              PRIMARY KEY DEFAULT gen_random_uuid(),
    collective_id uuid              NOT NULL REFERENCES public.collectives(id) ON DELETE CASCADE,
    token         uuid              NOT NULL UNIQUE DEFAULT gen_random_uuid(),
    role          public.member_role NOT NULL DEFAULT 'member',
    created_by    uuid              NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
    created_at    timestamptz       NOT NULL DEFAULT now(),
    expires_at    timestamptz       NOT NULL DEFAULT (now() + INTERVAL '7 days'),
    accepted_at   timestamptz       NULL,
    accepted_by   uuid              NULL REFERENCES public.users(id) ON DELETE SET NULL
);

ALTER TABLE public.collective_invitations ENABLE ROW LEVEL SECURITY;

CREATE INDEX collective_invitations_token_idx     ON public.collective_invitations (token);
CREATE INDEX collective_invitations_collective_idx ON public.collective_invitations (collective_id);

-- ── Trigger: auto-promote oldest member when last admin deletes account ────────
-- Fires BEFORE DELETE on public.users. If the departing user is the sole admin
-- of any collective, the longest-standing member (by joined_at) is promoted to
-- admin before the delete proceeds, satisfying business rule RN-10.

CREATE OR REPLACE FUNCTION public.promote_oldest_member_on_admin_leave()
RETURNS TRIGGER
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    r RECORD;
BEGIN
    -- For each collective where the departing user is an admin:
    FOR r IN
        SELECT cm.collective_id
        FROM   public.collective_members cm
        WHERE  cm.user_id = OLD.id
        AND    cm.role = 'admin'
        -- Only act when this is the SOLE remaining admin
        AND    (
            SELECT count(*)
            FROM   public.collective_members
            WHERE  collective_id = cm.collective_id
            AND    role = 'admin'
        ) = 1
    LOOP
        -- Promote the earliest-joined non-admin member in that collective
        UPDATE public.collective_members
        SET    role = 'admin'
        WHERE  (collective_id, user_id) = (
            SELECT collective_id, user_id
            FROM   public.collective_members
            WHERE  collective_id = r.collective_id
            AND    user_id <> OLD.id
            ORDER  BY joined_at ASC
            LIMIT  1
        );
    END LOOP;

    RETURN OLD;
END;
$$;

CREATE TRIGGER promote_on_admin_leave
    BEFORE DELETE ON public.users
    FOR EACH ROW EXECUTE FUNCTION public.promote_oldest_member_on_admin_leave();
