
-- Per-bill, per-board-member secure approval tokens for email approve/deny
CREATE TABLE IF NOT EXISTS public.bill_approval_email_tokens (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  bill_id uuid NOT NULL REFERENCES public.bills(id) ON DELETE CASCADE,
  board_member_id uuid NOT NULL REFERENCES public.board_members(id) ON DELETE CASCADE,
  token uuid NOT NULL DEFAULT gen_random_uuid() UNIQUE,
  email text NOT NULL,
  member_name text,
  sent_at timestamptz,
  acted_at timestamptz,
  action text CHECK (action IN ('approved','denied')),
  notes text,
  created_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE (bill_id, board_member_id)
);
CREATE INDEX IF NOT EXISTS idx_baet_token ON public.bill_approval_email_tokens(token);
CREATE INDEX IF NOT EXISTS idx_baet_bill ON public.bill_approval_email_tokens(bill_id);

ALTER TABLE public.bill_approval_email_tokens ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Staff manage bill approval tokens" ON public.bill_approval_email_tokens
  TO authenticated
  USING (has_role(auth.uid(),'admin') OR has_role(auth.uid(),'manager'))
  WITH CHECK (has_role(auth.uid(),'admin') OR has_role(auth.uid(),'manager'));

-- Lookup RPC for the public page (anonymous-friendly, security definer)
CREATE OR REPLACE FUNCTION public.lookup_bill_approval_by_token(p_token uuid)
RETURNS TABLE (
  bill_id uuid,
  member_name text,
  member_email text,
  acted_at timestamptz,
  action text,
  vendor_name text,
  invoice_number text,
  bill_date date,
  due_date date,
  amount numeric,
  description text,
  attachment_url text,
  bill_status text,
  association_name text
)
LANGUAGE sql STABLE SECURITY DEFINER SET search_path = public
AS $$
  SELECT t.bill_id, t.member_name, t.email AS member_email, t.acted_at, t.action,
         v.name AS vendor_name, b.invoice_number, b.bill_date, b.due_date, b.amount,
         b.description, b.attachment_url, b.status AS bill_status, a.name AS association_name
  FROM bill_approval_email_tokens t
  JOIN bills b ON b.id = t.bill_id
  LEFT JOIN vendors v ON v.id = b.vendor_id
  LEFT JOIN associations a ON a.id = b.association_id
  WHERE t.token = p_token;
$$;
GRANT EXECUTE ON FUNCTION public.lookup_bill_approval_by_token(uuid) TO anon, authenticated;

-- Record action via token
CREATE OR REPLACE FUNCTION public.record_bill_approval_by_token(p_token uuid, p_action text, p_notes text DEFAULT NULL)
RETURNS jsonb
LANGUAGE plpgsql SECURITY DEFINER SET search_path = public
AS $$
DECLARE
  tok record;
  bill record;
BEGIN
  IF p_action NOT IN ('approved','denied') THEN
    RETURN jsonb_build_object('ok', false, 'error', 'Invalid action');
  END IF;

  SELECT * INTO tok FROM bill_approval_email_tokens WHERE token = p_token;
  IF NOT FOUND THEN
    RETURN jsonb_build_object('ok', false, 'error', 'Invalid token');
  END IF;
  IF tok.acted_at IS NOT NULL THEN
    RETURN jsonb_build_object('ok', false, 'already_voted', true, 'error', 'You have already responded', 'action', tok.action);
  END IF;

  SELECT * INTO bill FROM bills WHERE id = tok.bill_id;
  IF NOT FOUND THEN
    RETURN jsonb_build_object('ok', false, 'error', 'Bill not found');
  END IF;

  INSERT INTO bill_approvals (bill_id, association_id, vendor_name, amount, status, notes, approved_date)
  VALUES (tok.bill_id, bill.association_id, COALESCE(tok.member_name,'Board Member'), bill.amount,
          p_action, p_notes, CURRENT_DATE);

  UPDATE bills SET status = p_action, updated_at = now() WHERE id = tok.bill_id;

  UPDATE bill_approval_email_tokens
  SET acted_at = now(), action = p_action, notes = p_notes
  WHERE token = p_token;

  RETURN jsonb_build_object('ok', true, 'action', p_action);
END;
$$;
GRANT EXECUTE ON FUNCTION public.record_bill_approval_by_token(uuid, text, text) TO anon, authenticated;
