-- =============================================================================
-- Migration: 20260419000014_financial_security_hardening
-- Sessão 6 — revisão Financeiro. Resolve V#1-V#5 (2 críticos + 3 altos).
-- V#6-V#11 adiados (médios/baixos com plano).
--
-- Auditoria prévia confirmou:
--   • 0 financial_records com tenant_id NULL
--   • 0 records com clinic_fee_amount > amount
-- → seguro aplicar NOT NULL e CHECK constraints.
-- =============================================================================

-- ─────────────────────────────────────────────────────────────────────────
-- V#1: billing_contracts policy granular
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS "billing_contracts: owner full access" ON public.billing_contracts;
DROP POLICY IF EXISTS "billing_contracts: select"            ON public.billing_contracts;
DROP POLICY IF EXISTS "billing_contracts: insert"            ON public.billing_contracts;
DROP POLICY IF EXISTS "billing_contracts: update"            ON public.billing_contracts;
DROP POLICY IF EXISTS "billing_contracts: delete"            ON public.billing_contracts;

CREATE POLICY "billing_contracts: select" ON public.billing_contracts
  FOR SELECT TO authenticated
  USING (
    owner_id = auth.uid()
    OR public.is_saas_admin()
    OR tenant_id IN (
        SELECT tm.tenant_id FROM public.tenant_members tm
        WHERE tm.user_id = auth.uid() AND tm.status = 'active'
    )
  );

CREATE POLICY "billing_contracts: insert" ON public.billing_contracts
  FOR INSERT TO authenticated
  WITH CHECK (
    owner_id = auth.uid()
    AND tenant_id IN (
        SELECT tm.tenant_id FROM public.tenant_members tm
        WHERE tm.user_id = auth.uid() AND tm.status = 'active'
    )
  );

CREATE POLICY "billing_contracts: update" ON public.billing_contracts
  FOR UPDATE TO authenticated
  USING (owner_id = auth.uid() OR public.is_saas_admin())
  WITH CHECK (owner_id = auth.uid() OR public.is_saas_admin());

CREATE POLICY "billing_contracts: delete" ON public.billing_contracts
  FOR DELETE TO authenticated
  USING (owner_id = auth.uid() OR public.is_saas_admin());

-- ─────────────────────────────────────────────────────────────────────────
-- V#2: financial_records.tenant_id NOT NULL + trigger backfill
-- (auditoria: 0 órfãos, seguro aplicar)
-- -----------------------------------------------------------------------------
ALTER TABLE public.financial_records ALTER COLUMN tenant_id SET NOT NULL;

-- Trigger defensivo: se tentar inserir sem tenant_id, busca via owner_id->tenant_members
CREATE OR REPLACE FUNCTION public.financial_records_inject_tenant()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
  IF NEW.tenant_id IS NULL AND NEW.owner_id IS NOT NULL THEN
    SELECT tm.tenant_id INTO NEW.tenant_id
    FROM public.tenant_members tm
    WHERE tm.user_id = NEW.owner_id AND tm.status = 'active'
    ORDER BY tm.created_at DESC
    LIMIT 1;
  END IF;
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_financial_records_inject_tenant ON public.financial_records;
CREATE TRIGGER trg_financial_records_inject_tenant
  BEFORE INSERT ON public.financial_records
  FOR EACH ROW EXECUTE FUNCTION public.financial_records_inject_tenant();

-- ─────────────────────────────────────────────────────────────────────────
-- V#5: financial_records CHECK contra net_amount negativo
-- -----------------------------------------------------------------------------
ALTER TABLE public.financial_records
  DROP CONSTRAINT IF EXISTS financial_records_fee_lte_amount_chk;

ALTER TABLE public.financial_records
  ADD CONSTRAINT financial_records_fee_lte_amount_chk
  CHECK (clinic_fee_amount IS NULL OR (clinic_fee_amount >= 0 AND clinic_fee_amount <= amount));

-- ─────────────────────────────────────────────────────────────────────────
-- V#3: payment_settings — adicionar SELECT pra tenant_admin
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS "payment_settings: tenant_admin read" ON public.payment_settings;
CREATE POLICY "payment_settings: tenant_admin read" ON public.payment_settings
  FOR SELECT TO authenticated
  USING (
    tenant_id IS NOT NULL
    AND tenant_id IN (
        SELECT tm.tenant_id FROM public.tenant_members tm
        WHERE tm.user_id = auth.uid() AND tm.status = 'active'
          AND tm.role IN ('tenant_admin','admin','owner')
    )
  );
-- (a policy ALL "owner full access" continua — owner mexe nos próprios)

-- ─────────────────────────────────────────────────────────────────────────
-- V#4: professional_pricing — adicionar SELECT pra tenant_admin
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS "professional_pricing: tenant_admin read" ON public.professional_pricing;
CREATE POLICY "professional_pricing: tenant_admin read" ON public.professional_pricing
  FOR SELECT TO authenticated
  USING (
    tenant_id IN (
        SELECT tm.tenant_id FROM public.tenant_members tm
        WHERE tm.user_id = auth.uid() AND tm.status = 'active'
          AND tm.role IN ('tenant_admin','admin','owner')
    )
  );
