"""add full text search vector to messages and extracted_text to attachments

Revision ID: 0008
Revises: 0007
Create Date: 2026-03-25
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

revision = '0008'
down_revision = '0007'
branch_labels = None
depends_on = None


def upgrade() -> None:
    # 1. Aggiunge colonna search_vector a messages
    op.add_column(
        'messages',
        sa.Column('search_vector', postgresql.TSVECTOR(), nullable=True),
    )

    # 2. Aggiunge colonna extracted_text ad attachments (testo estratto da PDF/DOCX)
    op.add_column(
        'attachments',
        sa.Column('extracted_text', sa.Text(), nullable=True),
    )

    # 3. Indice GIN per ricerca full-text veloce
    op.execute(
        "CREATE INDEX idx_messages_fts ON messages USING gin(search_vector) "
        "WHERE search_vector IS NOT NULL"
    )

    # 4. Funzione trigger che aggiorna search_vector quando cambiano i campi testuali
    op.execute("""
        CREATE OR REPLACE FUNCTION messages_search_vector_update() RETURNS trigger AS $$
        BEGIN
            NEW.search_vector :=
                setweight(to_tsvector('italian', coalesce(NEW.subject, '')), 'A') ||
                setweight(to_tsvector('simple',  coalesce(NEW.from_address, '')), 'B') ||
                setweight(to_tsvector('simple',
                    coalesce(array_to_string(NEW.to_addresses, ' '), '')), 'B') ||
                setweight(to_tsvector('italian', coalesce(NEW.body_text, '')), 'C');
            RETURN NEW;
        END;
        $$ LANGUAGE plpgsql;
    """)

    # 5. Crea trigger (si attiva su INSERT e UPDATE dei campi rilevanti)
    op.execute("""
        CREATE TRIGGER trg_messages_search_vector
        BEFORE INSERT OR UPDATE OF subject, from_address, to_addresses, body_text
        ON messages
        FOR EACH ROW EXECUTE FUNCTION messages_search_vector_update();
    """)

    # 6. Backfill: popola search_vector per i messaggi esistenti
    op.execute("""
        UPDATE messages SET search_vector =
            setweight(to_tsvector('italian', coalesce(subject, '')), 'A') ||
            setweight(to_tsvector('simple',  coalesce(from_address, '')), 'B') ||
            setweight(to_tsvector('simple',
                coalesce(array_to_string(to_addresses, ' '), '')), 'B') ||
            setweight(to_tsvector('italian', coalesce(body_text, '')), 'C')
        WHERE search_vector IS NULL
    """)


def downgrade() -> None:
    op.execute("DROP TRIGGER IF EXISTS trg_messages_search_vector ON messages")
    op.execute("DROP FUNCTION IF EXISTS messages_search_vector_update()")
    op.execute("DROP INDEX IF EXISTS idx_messages_fts")
    op.drop_column('attachments', 'extracted_text')
    op.drop_column('messages', 'search_vector')
