-- Perfis
CREATE TABLE public.perfis (
  id uuid PRIMARY KEY,
  email text NOT NULL,
  aprovado boolean NOT NULL DEFAULT false,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

GRANT SELECT, INSERT, UPDATE ON public.perfis TO authenticated;
GRANT ALL ON public.perfis TO service_role;
ALTER TABLE public.perfis ENABLE ROW LEVEL SECURITY;

-- Papeis
CREATE TYPE public.app_role AS ENUM ('admin', 'user');

CREATE TABLE public.papeis_usuario (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id uuid NOT NULL,
  role public.app_role NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE (user_id, role)
);

GRANT SELECT ON public.papeis_usuario TO authenticated;
GRANT ALL ON public.papeis_usuario TO service_role;
ALTER TABLE public.papeis_usuario ENABLE ROW LEVEL SECURITY;

CREATE OR REPLACE FUNCTION public.has_role(_user_id uuid, _role public.app_role)
RETURNS boolean
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
  SELECT EXISTS (
    SELECT 1 FROM public.papeis_usuario WHERE user_id = _user_id AND role = _role
  )
$$;

CREATE OR REPLACE FUNCTION public.is_aprovado(_user_id uuid)
RETURNS boolean
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
  SELECT EXISTS (
    SELECT 1 FROM public.perfis WHERE id = _user_id AND aprovado = true
  )
$$;

-- Policies perfis
CREATE POLICY "Ver proprio perfil" ON public.perfis
  FOR SELECT TO authenticated USING (id = auth.uid());
CREATE POLICY "Admins veem todos os perfis" ON public.perfis
  FOR SELECT TO authenticated USING (public.has_role(auth.uid(), 'admin'));
CREATE POLICY "Criar proprio perfil" ON public.perfis
  FOR INSERT TO authenticated WITH CHECK (id = auth.uid());
CREATE POLICY "Admins atualizam perfis" ON public.perfis
  FOR UPDATE TO authenticated
  USING (public.has_role(auth.uid(), 'admin'))
  WITH CHECK (public.has_role(auth.uid(), 'admin'));

-- Policies papeis
CREATE POLICY "Ver proprios papeis" ON public.papeis_usuario
  FOR SELECT TO authenticated USING (user_id = auth.uid());
CREATE POLICY "Admins veem todos os papeis" ON public.papeis_usuario
  FOR SELECT TO authenticated USING (public.has_role(auth.uid(), 'admin'));

-- Registro de perfil: primeiro usuario vira admin aprovado
CREATE OR REPLACE FUNCTION public.registrar_perfil()
RETURNS public.perfis
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_uid uuid := auth.uid();
  v_email text;
  v_primeiro boolean;
  v_perfil public.perfis;
BEGIN
  IF v_uid IS NULL THEN
    RAISE EXCEPTION 'Nao autenticado';
  END IF;

  SELECT * INTO v_perfil FROM public.perfis WHERE id = v_uid;
  IF FOUND THEN
    RETURN v_perfil;
  END IF;

  SELECT email INTO v_email FROM auth.users WHERE id = v_uid;
  SELECT NOT EXISTS (SELECT 1 FROM public.perfis) INTO v_primeiro;

  INSERT INTO public.perfis (id, email, aprovado)
  VALUES (v_uid, coalesce(v_email, ''), v_primeiro)
  RETURNING * INTO v_perfil;

  IF v_primeiro THEN
    INSERT INTO public.papeis_usuario (user_id, role) VALUES (v_uid, 'admin')
    ON CONFLICT DO NOTHING;
  END IF;

  RETURN v_perfil;
END;
$$;

GRANT EXECUTE ON FUNCTION public.registrar_perfil() TO authenticated;

CREATE OR REPLACE FUNCTION public.set_updated_at()
RETURNS TRIGGER
LANGUAGE plpgsql
SET search_path = public
AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$;

CREATE TRIGGER perfis_updated_at BEFORE UPDATE ON public.perfis
FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

-- Coletas: apenas usuarios logados e aprovados
DROP POLICY IF EXISTS "Coletas sao visiveis publicamente" ON public.coletas;
DROP POLICY IF EXISTS "Qualquer um pode atualizar coleta" ON public.coletas;
DROP POLICY IF EXISTS "Qualquer um pode criar coleta" ON public.coletas;

REVOKE ALL ON public.coletas FROM anon;
GRANT SELECT, INSERT, UPDATE ON public.coletas TO authenticated;
GRANT ALL ON public.coletas TO service_role;

CREATE POLICY "Aprovados veem coletas" ON public.coletas
  FOR SELECT TO authenticated USING (public.is_aprovado(auth.uid()));
CREATE POLICY "Aprovados criam coletas" ON public.coletas
  FOR INSERT TO authenticated WITH CHECK (public.is_aprovado(auth.uid()));
CREATE POLICY "Aprovados atualizam coletas" ON public.coletas
  FOR UPDATE TO authenticated
  USING (public.is_aprovado(auth.uid()))
  WITH CHECK (public.is_aprovado(auth.uid()));