-- ==========================================================================
-- Agencia PSI — Migracao: Intake abandonado vira lead no CRM (8.4)
-- ==========================================================================
-- Quando paciente abre o link de cadastro externo e preenche dados parciais
-- (ex: nome + telefone) mas nao finaliza, rodamos um cron periodico que:
--   1. Varre patient_intake_requests com status='in_progress' ha > N min
--      (default 30)
--   2. Pra cada, cria uma mensagem outbound placeholder no CRM anunciando:
--      "Paciente X preencheu parcialmente o cadastro e abandonou" + dados
--      coletados (nome, telefone, motivo se tiver)
--   3. Marca intake como status='abandoned_lead' pra nao reprocessar
--
-- Pre-requisito pro fluxo funcionar: o form de intake (CadastroPacienteExterno)
-- precisa chamar save-intake-progress em algum evento de progresso
-- (ex: ao preencher telefone). Sem isso, nenhum row fica 'in_progress'.
-- ==========================================================================

-- Expande CHECK de status pra incluir 'in_progress' e 'abandoned_lead'
ALTER TABLE public.patient_intake_requests
    DROP CONSTRAINT IF EXISTS chk_intakes_status;

ALTER TABLE public.patient_intake_requests
    ADD CONSTRAINT chk_intakes_status
    CHECK (status = ANY (ARRAY[
        'new'::text,
        'in_progress'::text,
        'converted'::text,
        'rejected'::text,
        'abandoned_lead'::text
    ]));

-- Timestamp da ultima atualizacao de progresso (autosave)
ALTER TABLE public.patient_intake_requests
    ADD COLUMN IF NOT EXISTS last_progress_at TIMESTAMPTZ;

-- Referencia pra mensagem/thread criada como lead (evita duplicacao)
ALTER TABLE public.patient_intake_requests
    ADD COLUMN IF NOT EXISTS lead_thread_key TEXT;

CREATE INDEX IF NOT EXISTS idx_intakes_progress_pending
    ON public.patient_intake_requests (last_progress_at)
    WHERE status = 'in_progress';

COMMENT ON COLUMN public.patient_intake_requests.last_progress_at IS
    'Ultima vez que o form salvou dados parciais. Cron usa pra detectar abandonados.';
COMMENT ON COLUMN public.patient_intake_requests.lead_thread_key IS
    'Thread key da conversa criada no CRM quando vira lead abandonado.';


-- ---------------------------------------------------------------------------
-- RPC: convert_abandoned_intake_to_lead
-- ---------------------------------------------------------------------------
-- Processa 1 intake abandonado: cria conversation_message (outbound placeholder)
-- + conversation_note + marca status. Retorna o thread_key gerado.
--
-- SECURITY DEFINER pra bypass RLS do conversation_messages/notes.
-- ---------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.convert_abandoned_intake_to_lead(p_intake_id UUID)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_intake RECORD;
    v_tenant_id UUID;
    v_thread_key TEXT;
    v_phone TEXT;
    v_note_body TEXT;
    v_admin_id UUID;
    v_msg_id BIGINT;
BEGIN
    SELECT * INTO v_intake FROM public.patient_intake_requests WHERE id = p_intake_id;
    IF NOT FOUND THEN RAISE EXCEPTION 'intake_not_found'; END IF;
    IF v_intake.status = 'abandoned_lead' THEN RETURN v_intake.lead_thread_key::UUID; END IF;

    -- Tenant_id vem via owner_id (tenant_members)
    SELECT tenant_id INTO v_tenant_id
        FROM public.tenant_members
        WHERE user_id = v_intake.owner_id
        ORDER BY CASE role WHEN 'tenant_admin' THEN 1 WHEN 'clinic_admin' THEN 2 ELSE 3 END
        LIMIT 1;

    IF v_tenant_id IS NULL THEN RAISE EXCEPTION 'tenant_not_resolved'; END IF;

    -- Normaliza telefone pra thread_key
    v_phone := regexp_replace(COALESCE(v_intake.telefone, ''), '\D', '', 'g');
    IF length(v_phone) BETWEEN 10 AND 11 THEN v_phone := '55' || v_phone; END IF;
    IF v_phone = '' THEN v_phone := 'unknown'; END IF;
    v_thread_key := 'anon:' || v_phone;

    -- Nota com dados coletados
    v_note_body := format(
        '📋 Lead abandonado (cadastro externo):%s%sNome: %s%sTelefone: %s%sE-mail: %s%sMotivo/Observacoes: %s%s%sIniciou em: %s · Ultima atualizacao: %s',
        E'\n', E'\n',
        COALESCE(v_intake.nome_completo, '—'),
        E'\n',
        COALESCE(v_intake.telefone, '—'),
        E'\n',
        COALESCE(v_intake.email_principal, '—'),
        E'\n',
        COALESCE(v_intake.onde_nos_conheceu, '—'),
        E'\n', E'\n',
        to_char(v_intake.created_at AT TIME ZONE 'America/Sao_Paulo', 'DD/MM HH24:MI'),
        to_char(COALESCE(v_intake.last_progress_at, v_intake.updated_at) AT TIME ZONE 'America/Sao_Paulo', 'DD/MM HH24:MI')
    );

    -- Pega 1 admin do tenant pra preencher created_by da nota
    SELECT user_id INTO v_admin_id
        FROM public.tenant_members
        WHERE tenant_id = v_tenant_id
          AND role IN ('tenant_admin', 'clinic_admin')
          AND status = 'active'
        LIMIT 1;

    IF v_admin_id IS NULL THEN
        v_admin_id := v_intake.owner_id;
    END IF;

    -- Cria mensagem placeholder (outbound sistema — entra no thread do CRM)
    INSERT INTO public.conversation_messages
        (tenant_id, channel, direction, from_number, to_number, body, provider,
         provider_raw, kanban_status)
    VALUES (
        v_tenant_id, 'whatsapp', 'inbound',
        CASE WHEN v_phone = 'unknown' THEN NULL ELSE v_phone END,
        NULL,
        format('🧾 Cadastro externo iniciado e não finalizado. %s entrou em contato via link público mas abandonou o formulário — ver nota interna.',
               COALESCE(v_intake.nome_completo, 'Visitante')),
        'system',
        jsonb_build_object('lead_from_abandoned_intake', true, 'intake_id', v_intake.id),
        'awaiting_us'
    ) RETURNING id INTO v_msg_id;

    -- Cria nota interna
    INSERT INTO public.conversation_notes
        (tenant_id, thread_key, contact_number, body, created_by)
    VALUES (
        v_tenant_id, v_thread_key,
        CASE WHEN v_phone = 'unknown' THEN NULL ELSE v_phone END,
        v_note_body, v_admin_id
    );

    -- Atualiza intake
    UPDATE public.patient_intake_requests
        SET status = 'abandoned_lead',
            lead_thread_key = v_thread_key,
            updated_at = now()
        WHERE id = p_intake_id;

    RETURN p_intake_id;
END;
$$;

REVOKE ALL ON FUNCTION public.convert_abandoned_intake_to_lead(UUID) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.convert_abandoned_intake_to_lead(UUID) TO service_role;

COMMENT ON FUNCTION public.convert_abandoned_intake_to_lead(UUID) IS
    'Transforma 1 intake abandonado em lead no CRM: cria mensagem placeholder + nota com dados + marca status.';
