-- ==========================================================================
-- Agencia PSI — Migracao: Emails polimorficos com tipo + principal
-- ==========================================================================
-- Criado por: Leonardo Nohama
-- Data: 2026-04-21 · Sao Carlos/SP — Brasil
--
-- Mesmo padrao dos telefones (migration 20260421000008):
--   - contact_email_types  → tipos configuraveis (Principal, Comercial, Pessoal, ...)
--   - contact_emails       → emails polimorficos (entity_type + entity_id)
--
-- Triggers mantem patients.email_principal/email_alternativo e medicos.email
-- sincronizados pra nao quebrar codigo legado.
-- ==========================================================================

-- ---------------------------------------------------------------------------
-- Tabela: contact_email_types
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS public.contact_email_types (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID REFERENCES public.tenants(id) ON DELETE CASCADE,
    name TEXT NOT NULL CHECK (length(name) > 0 AND length(name) <= 40),
    slug TEXT NOT NULL CHECK (slug ~ '^[a-z0-9_-]{1,40}$'),
    icon TEXT,
    is_system BOOLEAN NOT NULL DEFAULT false,
    position INT NOT NULL DEFAULT 100,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX IF NOT EXISTS uq_contact_email_types_tenant_slug
    ON public.contact_email_types (tenant_id, slug)
    WHERE tenant_id IS NOT NULL;

CREATE UNIQUE INDEX IF NOT EXISTS uq_contact_email_types_system_slug
    ON public.contact_email_types (slug)
    WHERE tenant_id IS NULL;

CREATE INDEX IF NOT EXISTS idx_contact_email_types_tenant
    ON public.contact_email_types (tenant_id, position);

DROP TRIGGER IF EXISTS trg_contact_email_types_updated_at ON public.contact_email_types;
CREATE TRIGGER trg_contact_email_types_updated_at
    BEFORE UPDATE ON public.contact_email_types
    FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

COMMENT ON TABLE public.contact_email_types IS
    'Tipos de email (Principal, Comercial, Pessoal, ...). System (tenant_id NULL) + custom.';

-- Seed
INSERT INTO public.contact_email_types (tenant_id, name, slug, icon, is_system, position) VALUES
    (NULL, 'Principal',    'principal',    'pi pi-envelope',       true, 10),
    (NULL, 'Pessoal',      'pessoal',      'pi pi-user',           true, 20),
    (NULL, 'Comercial',    'comercial',    'pi pi-building',       true, 30),
    (NULL, 'Faturamento',  'faturamento',  'pi pi-dollar',         true, 40),
    (NULL, 'Alternativo',  'alternativo',  'pi pi-reply',          true, 50)
ON CONFLICT DO NOTHING;

-- ---------------------------------------------------------------------------
-- Tabela: contact_emails (polimorfica)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS public.contact_emails (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,

    entity_type TEXT NOT NULL CHECK (entity_type IN ('patient', 'medico')),
    entity_id UUID NOT NULL,

    contact_email_type_id UUID NOT NULL REFERENCES public.contact_email_types(id) ON DELETE RESTRICT,

    email TEXT NOT NULL CHECK (email ~* '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'),
    is_primary BOOLEAN NOT NULL DEFAULT false,

    notes TEXT,
    position INT NOT NULL DEFAULT 100,

    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_contact_emails_entity
    ON public.contact_emails (tenant_id, entity_type, entity_id, position);

CREATE INDEX IF NOT EXISTS idx_contact_emails_email
    ON public.contact_emails (tenant_id, email);

CREATE UNIQUE INDEX IF NOT EXISTS uq_contact_emails_primary
    ON public.contact_emails (entity_type, entity_id)
    WHERE is_primary = true;

DROP TRIGGER IF EXISTS trg_contact_emails_updated_at ON public.contact_emails;
CREATE TRIGGER trg_contact_emails_updated_at
    BEFORE UPDATE ON public.contact_emails
    FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

COMMENT ON TABLE public.contact_emails IS
    'Emails polimorficos (patients, medicos, ...). Max 1 primary por entidade. Triggers sincronizam campos legados.';

-- ---------------------------------------------------------------------------
-- Trigger: sincroniza campos legados apos mudanca
-- ---------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.sync_legacy_email_fields() RETURNS TRIGGER
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_entity_type TEXT;
    v_entity_id UUID;
    v_primary TEXT;
    v_secondary TEXT;
BEGIN
    IF TG_OP = 'DELETE' THEN
        v_entity_type := OLD.entity_type;
        v_entity_id := OLD.entity_id;
    ELSE
        v_entity_type := NEW.entity_type;
        v_entity_id := NEW.entity_id;
    END IF;

    SELECT email INTO v_primary
        FROM public.contact_emails
        WHERE entity_type = v_entity_type AND entity_id = v_entity_id
        ORDER BY is_primary DESC, position ASC, created_at ASC
        LIMIT 1;

    SELECT email INTO v_secondary
        FROM public.contact_emails
        WHERE entity_type = v_entity_type AND entity_id = v_entity_id
          AND is_primary = false
        ORDER BY position ASC, created_at ASC
        OFFSET 0
        LIMIT 1;

    IF v_entity_type = 'patient' THEN
        UPDATE public.patients
            SET email_principal = v_primary,
                email_alternativo = v_secondary
            WHERE id = v_entity_id;
    ELSIF v_entity_type = 'medico' THEN
        UPDATE public.medicos
            SET email = v_primary
            WHERE id = v_entity_id;
    END IF;

    IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF;
END;
$$;

DROP TRIGGER IF EXISTS trg_contact_emails_sync_legacy ON public.contact_emails;
CREATE TRIGGER trg_contact_emails_sync_legacy
    AFTER INSERT OR UPDATE OR DELETE ON public.contact_emails
    FOR EACH ROW EXECUTE FUNCTION public.sync_legacy_email_fields();

-- ---------------------------------------------------------------------------
-- Backfill: migra emails existentes
-- ---------------------------------------------------------------------------
DO $$
DECLARE
    v_principal_id UUID;
    v_alternativo_id UUID;
BEGIN
    SELECT id INTO v_principal_id FROM public.contact_email_types WHERE slug = 'principal' AND tenant_id IS NULL LIMIT 1;
    SELECT id INTO v_alternativo_id FROM public.contact_email_types WHERE slug = 'alternativo' AND tenant_id IS NULL LIMIT 1;

    -- Patients.email_principal → Principal primary
    INSERT INTO public.contact_emails (tenant_id, entity_type, entity_id, contact_email_type_id, email, is_primary, position)
    SELECT
        p.tenant_id, 'patient', p.id, v_principal_id, lower(trim(p.email_principal)), true, 10
    FROM public.patients p
    WHERE p.email_principal IS NOT NULL
      AND trim(p.email_principal) ~* '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'
      AND NOT EXISTS (
        SELECT 1 FROM public.contact_emails ce
        WHERE ce.entity_type = 'patient' AND ce.entity_id = p.id
    )
    ON CONFLICT DO NOTHING;

    -- Patients.email_alternativo → Alternativo
    INSERT INTO public.contact_emails (tenant_id, entity_type, entity_id, contact_email_type_id, email, is_primary, position)
    SELECT
        p.tenant_id, 'patient', p.id, v_alternativo_id, lower(trim(p.email_alternativo)), false, 20
    FROM public.patients p
    WHERE p.email_alternativo IS NOT NULL
      AND trim(p.email_alternativo) ~* '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'
      AND NOT EXISTS (
        SELECT 1 FROM public.contact_emails ce
        WHERE ce.entity_type = 'patient' AND ce.entity_id = p.id
          AND ce.email = lower(trim(p.email_alternativo))
    )
    ON CONFLICT DO NOTHING;

    -- Medicos.email → Principal primary
    INSERT INTO public.contact_emails (tenant_id, entity_type, entity_id, contact_email_type_id, email, is_primary, position)
    SELECT
        m.tenant_id, 'medico', m.id, v_principal_id, lower(trim(m.email)), true, 10
    FROM public.medicos m
    WHERE m.email IS NOT NULL
      AND trim(m.email) ~* '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'
      AND NOT EXISTS (
        SELECT 1 FROM public.contact_emails ce
        WHERE ce.entity_type = 'medico' AND ce.entity_id = m.id
    )
    ON CONFLICT DO NOTHING;
END $$;

-- ---------------------------------------------------------------------------
-- RLS
-- ---------------------------------------------------------------------------
ALTER TABLE public.contact_email_types ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.contact_emails ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "contact_email_types: select" ON public.contact_email_types;
CREATE POLICY "contact_email_types: select"
    ON public.contact_email_types FOR SELECT TO authenticated
    USING (
        tenant_id IS NULL
        OR public.is_saas_admin()
        OR EXISTS (
            SELECT 1 FROM public.tenant_members tm
            WHERE tm.user_id = auth.uid() AND tm.tenant_id = contact_email_types.tenant_id AND tm.status = 'active'
        )
    );

DROP POLICY IF EXISTS "contact_email_types: manage custom" ON public.contact_email_types;
CREATE POLICY "contact_email_types: manage custom"
    ON public.contact_email_types FOR ALL TO authenticated
    USING (
        is_system = false AND tenant_id IS NOT NULL AND (
            public.is_saas_admin()
            OR EXISTS (
                SELECT 1 FROM public.tenant_members tm
                WHERE tm.user_id = auth.uid() AND tm.tenant_id = contact_email_types.tenant_id AND tm.status = 'active'
            )
        )
    )
    WITH CHECK (
        is_system = false AND tenant_id IS NOT NULL AND (
            public.is_saas_admin()
            OR EXISTS (
                SELECT 1 FROM public.tenant_members tm
                WHERE tm.user_id = auth.uid() AND tm.tenant_id = contact_email_types.tenant_id AND tm.status = 'active'
            )
        )
    );

DROP POLICY IF EXISTS "contact_emails: all tenant" ON public.contact_emails;
CREATE POLICY "contact_emails: all tenant"
    ON public.contact_emails FOR ALL TO authenticated
    USING (
        public.is_saas_admin()
        OR EXISTS (
            SELECT 1 FROM public.tenant_members tm
            WHERE tm.user_id = auth.uid() AND tm.tenant_id = contact_emails.tenant_id AND tm.status = 'active'
        )
    )
    WITH CHECK (
        public.is_saas_admin()
        OR EXISTS (
            SELECT 1 FROM public.tenant_members tm
            WHERE tm.user_id = auth.uid() AND tm.tenant_id = contact_emails.tenant_id AND tm.status = 'active'
        )
    );

-- ==========================================================================
-- FIM DA MIGRACAO
-- ==========================================================================
