-- ============================================================
-- SUPERVISOR — Fase 1
-- Aplicar no Supabase SQL Editor (em ordem)
-- ============================================================


-- ────────────────────────────────────────────────────────────
-- 1. tenants.kind → adiciona 'supervisor'
-- ────────────────────────────────────────────────────────────
ALTER TABLE public.tenants
  DROP CONSTRAINT IF EXISTS tenants_kind_check;

ALTER TABLE public.tenants
  ADD CONSTRAINT tenants_kind_check
  CHECK (kind = ANY (ARRAY[
    'therapist',
    'clinic_coworking',
    'clinic_reception',
    'clinic_full',
    'clinic',
    'saas',
    'supervisor'          -- ← novo
  ]));


-- ────────────────────────────────────────────────────────────
-- 2. plans.target → adiciona 'supervisor'
-- ────────────────────────────────────────────────────────────
ALTER TABLE public.plans
  DROP CONSTRAINT IF EXISTS plans_target_check;

ALTER TABLE public.plans
  ADD CONSTRAINT plans_target_check
  CHECK (target = ANY (ARRAY[
    'patient',
    'therapist',
    'clinic',
    'supervisor'          -- ← novo
  ]));


-- ────────────────────────────────────────────────────────────
-- 3. plans.max_supervisees — limite de supervisionados
-- ────────────────────────────────────────────────────────────
ALTER TABLE public.plans
  ADD COLUMN IF NOT EXISTS max_supervisees integer DEFAULT NULL;

COMMENT ON COLUMN public.plans.max_supervisees IS
  'Limite de terapeutas que podem ser supervisionados. Apenas para planos target=supervisor. NULL = sem limite.';


-- ────────────────────────────────────────────────────────────
-- 4. Planos supervisor_free e supervisor_pro
-- ────────────────────────────────────────────────────────────
INSERT INTO public.plans (key, name, description, target, is_active, max_supervisees)
VALUES
  (
    'supervisor_free',
    'Supervisor Free',
    'Plano gratuito de supervisão. Até 3 terapeutas supervisionados.',
    'supervisor',
    true,
    3
  ),
  (
    'supervisor_pro',
    'Supervisor PRO',
    'Plano profissional de supervisão. Até 20 terapeutas supervisionados.',
    'supervisor',
    true,
    20
  )
ON CONFLICT (key) DO UPDATE
  SET
    name            = EXCLUDED.name,
    description     = EXCLUDED.description,
    target          = EXCLUDED.target,
    is_active       = EXCLUDED.is_active,
    max_supervisees = EXCLUDED.max_supervisees;


-- ────────────────────────────────────────────────────────────
-- 5. Features de supervisor
-- ────────────────────────────────────────────────────────────
INSERT INTO public.features (key, name, descricao)
VALUES
  (
    'supervisor.access',
    'Acesso à Supervisão',
    'Acesso básico ao espaço de supervisão (sala, lista de supervisionados).'
  ),
  (
    'supervisor.invite',
    'Convidar Supervisionados',
    'Permite convidar terapeutas para participar da sala de supervisão.'
  ),
  (
    'supervisor.sessions',
    'Sessões de Supervisão',
    'Agendamento e registro de sessões de supervisão.'
  ),
  (
    'supervisor.reports',
    'Relatórios de Supervisão',
    'Relatórios avançados de progresso e evolução dos supervisionados.'
  )
ON CONFLICT (key) DO UPDATE
  SET
    name     = EXCLUDED.name,
    descricao = EXCLUDED.descricao;


-- ────────────────────────────────────────────────────────────
-- 6. plan_features — vincula features aos planos supervisor
-- ────────────────────────────────────────────────────────────
DO $$
DECLARE
  v_free_id  uuid;
  v_pro_id   uuid;
  v_f_access   uuid;
  v_f_invite   uuid;
  v_f_sessions uuid;
  v_f_reports  uuid;
BEGIN
  SELECT id INTO v_free_id FROM public.plans WHERE key = 'supervisor_free';
  SELECT id INTO v_pro_id  FROM public.plans WHERE key = 'supervisor_pro';

  SELECT id INTO v_f_access   FROM public.features WHERE key = 'supervisor.access';
  SELECT id INTO v_f_invite   FROM public.features WHERE key = 'supervisor.invite';
  SELECT id INTO v_f_sessions FROM public.features WHERE key = 'supervisor.sessions';
  SELECT id INTO v_f_reports  FROM public.features WHERE key = 'supervisor.reports';

  -- supervisor_free: access + invite (limitado por max_supervisees=3)
  INSERT INTO public.plan_features (plan_id, feature_id)
  VALUES
    (v_free_id, v_f_access),
    (v_free_id, v_f_invite)
  ON CONFLICT DO NOTHING;

  -- supervisor_pro: tudo
  INSERT INTO public.plan_features (plan_id, feature_id)
  VALUES
    (v_pro_id, v_f_access),
    (v_pro_id, v_f_invite),
    (v_pro_id, v_f_sessions),
    (v_pro_id, v_f_reports)
  ON CONFLICT DO NOTHING;
END;
$$;


-- ────────────────────────────────────────────────────────────
-- 7. activate_subscription_from_intent — suporte a supervisor
--    Supervisor = pessoal (user_id), sem tenant_id (igual therapist)
-- ────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION public.activate_subscription_from_intent(p_intent_id uuid)
RETURNS public.subscriptions
LANGUAGE plpgsql SECURITY DEFINER
AS $$
declare
  v_intent record;
  v_sub public.subscriptions;
  v_days int;
  v_user_id uuid;
  v_plan_id uuid;
  v_target text;
begin
  -- lê pela VIEW unificada
  select * into v_intent
  from public.subscription_intents
  where id = p_intent_id;

  if not found then
    raise exception 'Intent não encontrado: %', p_intent_id;
  end if;

  if v_intent.status <> 'paid' then
    raise exception 'Intent precisa estar paid para ativar assinatura';
  end if;

  -- resolve target e plan_id via plans.key
  select p.id, p.target
    into v_plan_id, v_target
  from public.plans p
  where p.key = v_intent.plan_key
  limit 1;

  if v_plan_id is null then
    raise exception 'Plano não encontrado em plans.key = %', v_intent.plan_key;
  end if;

  v_target := lower(coalesce(v_target, ''));

  -- ✅ supervisor adicionado
  if v_target not in ('clinic', 'therapist', 'supervisor') then
    raise exception 'Target inválido em plans.target: %', v_target;
  end if;

  -- regra por target
  if v_target = 'clinic' then
    if v_intent.tenant_id is null then
      raise exception 'Intent sem tenant_id';
    end if;
  else
    -- therapist ou supervisor: vinculado ao user
    v_user_id := v_intent.user_id;
    if v_user_id is null then
      v_user_id := v_intent.created_by_user_id;
    end if;
  end if;

  if v_target in ('therapist', 'supervisor') and v_user_id is null then
    raise exception 'Não foi possível determinar user_id para assinatura %.', v_target;
  end if;

  -- cancela assinatura ativa anterior
  if v_target = 'clinic' then
    update public.subscriptions
    set status = 'cancelled',
        cancelled_at = now()
    where tenant_id = v_intent.tenant_id
      and plan_id = v_plan_id
      and status = 'active';
  else
    -- therapist ou supervisor
    update public.subscriptions
    set status = 'cancelled',
        cancelled_at = now()
    where user_id = v_user_id
      and plan_id = v_plan_id
      and status = 'active'
      and tenant_id is null;
  end if;

  -- duração do plano (30 dias para mensal)
  v_days := case
    when lower(coalesce(v_intent.interval, 'month')) = 'year' then 365
    else 30
  end;

  -- cria nova assinatura
  insert into public.subscriptions (
    user_id,
    plan_id,
    status,
    started_at,
    expires_at,
    cancelled_at,
    activated_at,
    tenant_id,
    plan_key,
    interval,
    source,
    created_at,
    updated_at
  )
  values (
    case when v_target = 'clinic' then null else v_user_id end,
    v_plan_id,
    'active',
    now(),
    now() + make_interval(days => v_days),
    null,
    now(),
    case when v_target = 'clinic' then v_intent.tenant_id else null end,
    v_intent.plan_key,
    v_intent.interval,
    'manual',
    now(),
    now()
  )
  returning * into v_sub;

  -- grava vínculo intent → subscription
  if v_target = 'clinic' then
    update public.subscription_intents_tenant
    set subscription_id = v_sub.id
    where id = p_intent_id;
  else
    update public.subscription_intents_personal
    set subscription_id = v_sub.id
    where id = p_intent_id;
  end if;

  return v_sub;
end;
$$;


-- ────────────────────────────────────────────────────────────
-- 8. subscriptions_validate_scope — suporte a supervisor
-- ────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION public.subscriptions_validate_scope()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  v_target text;
BEGIN
  SELECT lower(p.target) INTO v_target
  FROM public.plans p
  WHERE p.id = NEW.plan_id;

  IF v_target IS NULL THEN
    RAISE EXCEPTION 'Plano inválido (target nulo).';
  END IF;

  IF v_target = 'clinic' THEN
    IF NEW.tenant_id IS NULL THEN
      RAISE EXCEPTION 'Assinatura clinic exige tenant_id.';
    END IF;
    IF NEW.user_id IS NOT NULL THEN
      RAISE EXCEPTION 'Assinatura clinic não pode ter user_id (XOR).';
    END IF;

  ELSIF v_target IN ('therapist', 'supervisor') THEN
    -- supervisor é pessoal como therapist
    IF NEW.tenant_id IS NOT NULL THEN
      RAISE EXCEPTION 'Assinatura % não deve ter tenant_id.', v_target;
    END IF;
    IF NEW.user_id IS NULL THEN
      RAISE EXCEPTION 'Assinatura % exige user_id.', v_target;
    END IF;

  ELSIF v_target = 'patient' THEN
    IF NEW.tenant_id IS NOT NULL THEN
      RAISE EXCEPTION 'Assinatura patient não deve ter tenant_id.';
    END IF;
    IF NEW.user_id IS NULL THEN
      RAISE EXCEPTION 'Assinatura patient exige user_id.';
    END IF;

  ELSE
    RAISE EXCEPTION 'Target de plano inválido: %', v_target;
  END IF;

  RETURN NEW;
END;
$$;


-- ────────────────────────────────────────────────────────────
-- 9. subscription_intents_view_insert — suporte a supervisor
--    supervisor é roteado como therapist (tabela personal)
-- ────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION public.subscription_intents_view_insert()
RETURNS trigger
LANGUAGE plpgsql SECURITY DEFINER
AS $$
declare
  v_target text;
  v_plan_id uuid;
begin
  select p.id, p.target into v_plan_id, v_target
  from public.plans p
  where p.key = new.plan_key;

  if v_plan_id is null then
    raise exception 'Plano inválido: plan_key=%', new.plan_key;
  end if;

  if lower(v_target) = 'clinic' then
    if new.tenant_id is null then
      raise exception 'Intenção clinic exige tenant_id.';
    end if;

    insert into public.subscription_intents_tenant (
      id, tenant_id, created_by_user_id, email,
      plan_id, plan_key, interval, amount_cents, currency,
      status, source, notes, created_at, paid_at
    ) values (
      coalesce(new.id, gen_random_uuid()),
      new.tenant_id, new.created_by_user_id, new.email,
      v_plan_id, new.plan_key, coalesce(new.interval,'month'),
      new.amount_cents, coalesce(new.currency,'BRL'),
      coalesce(new.status,'pending'), coalesce(new.source,'manual'),
      new.notes, coalesce(new.created_at, now()), new.paid_at
    );

    new.plan_target := 'clinic';
    return new;
  end if;

  -- therapist ou supervisor → tabela personal
  if lower(v_target) in ('therapist', 'supervisor') then
    insert into public.subscription_intents_personal (
      id, user_id, created_by_user_id, email,
      plan_id, plan_key, interval, amount_cents, currency,
      status, source, notes, created_at, paid_at
    ) values (
      coalesce(new.id, gen_random_uuid()),
      new.user_id, new.created_by_user_id, new.email,
      v_plan_id, new.plan_key, coalesce(new.interval,'month'),
      new.amount_cents, coalesce(new.currency,'BRL'),
      coalesce(new.status,'pending'), coalesce(new.source,'manual'),
      new.notes, coalesce(new.created_at, now()), new.paid_at
    );

    new.plan_target := lower(v_target); -- 'therapist' ou 'supervisor'
    return new;
  end if;

  raise exception 'Target de plano não suportado: %', v_target;
end;
$$;


-- ────────────────────────────────────────────────────────────
-- FIM — verificação rápida
-- ────────────────────────────────────────────────────────────
SELECT key, name, target, max_supervisees
FROM public.plans
WHERE target = 'supervisor'
ORDER BY key;
