"""Centralized SQL for mail_summary."""


class Schema:
    ENSURE_ANALYSIS_JOBS = """
    CREATE TABLE IF NOT EXISTS analysis_jobs (
        id                   BIGSERIAL PRIMARY KEY,
        status               TEXT NOT NULL DEFAULT 'pending',
        mailbox_scope        TEXT NOT NULL DEFAULT 'both',
        date_from            DATE NOT NULL,
        date_to              DATE NOT NULL,
        model                TEXT NOT NULL DEFAULT '',
        inbox_zip_name       TEXT,
        sent_zip_name        TEXT,
        inbox_count          INTEGER NOT NULL DEFAULT 0,
        sent_count           INTEGER NOT NULL DEFAULT 0,
        filtered_inbox_count INTEGER NOT NULL DEFAULT 0,
        filtered_sent_count  INTEGER NOT NULL DEFAULT 0,
        progress_pct         INTEGER NOT NULL DEFAULT 0,
        progress_label       TEXT NOT NULL DEFAULT '',
        progress_detail      TEXT NOT NULL DEFAULT '',
        error_message        TEXT,
        created_at           TIMESTAMPTZ NOT NULL DEFAULT NOW(),
        started_at           TIMESTAMPTZ,
        completed_at         TIMESTAMPTZ,
        CONSTRAINT analysis_jobs_status_chk CHECK (
            status IN ('pending', 'extracting', 'filtering', 'analyzing', 'completed', 'failed')
        ),
        CONSTRAINT analysis_jobs_scope_chk CHECK (
            mailbox_scope IN ('inbox', 'sent', 'both')
        ),
        CONSTRAINT analysis_jobs_date_chk CHECK (date_from <= date_to)
    )
    """
    ADD_PROGRESS_PCT = """
    ALTER TABLE analysis_jobs
    ADD COLUMN IF NOT EXISTS progress_pct INTEGER NOT NULL DEFAULT 0
    """
    ADD_PROGRESS_LABEL = """
    ALTER TABLE analysis_jobs
    ADD COLUMN IF NOT EXISTS progress_label TEXT NOT NULL DEFAULT ''
    """
    ADD_PROGRESS_DETAIL = """
    ALTER TABLE analysis_jobs
    ADD COLUMN IF NOT EXISTS progress_detail TEXT NOT NULL DEFAULT ''
    """
    IDX_ANALYSIS_JOBS_CREATED_AT = """
    CREATE INDEX IF NOT EXISTS idx_analysis_jobs_created_at
        ON analysis_jobs (created_at DESC)
    """
    IDX_ANALYSIS_JOBS_STATUS = """
    CREATE INDEX IF NOT EXISTS idx_analysis_jobs_status
        ON analysis_jobs (status)
    """

    ENSURE_MAILS = """
    CREATE TABLE IF NOT EXISTS mails (
        id                BIGSERIAL PRIMARY KEY,
        job_id            BIGINT NOT NULL REFERENCES analysis_jobs(id) ON DELETE CASCADE,
        mailbox           TEXT NOT NULL,
        message_id        TEXT,
        thread_key        TEXT,
        subject           TEXT NOT NULL DEFAULT '',
        from_addr         TEXT NOT NULL DEFAULT '',
        to_addrs          TEXT NOT NULL DEFAULT '',
        cc_addrs          TEXT NOT NULL DEFAULT '',
        mailed_at         TIMESTAMPTZ,
        attachment_names  JSONB NOT NULL DEFAULT '[]'::jsonb,
        body_text         TEXT,
        body_purged       BOOLEAN NOT NULL DEFAULT FALSE,
        summary           JSONB,
        created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
        CONSTRAINT mails_mailbox_chk CHECK (mailbox IN ('inbox', 'sent'))
    )
    """

    IDX_MAILS_JOB_ID = "CREATE INDEX IF NOT EXISTS idx_mails_job_id ON mails (job_id)"
    IDX_MAILS_JOB_MAILED_AT = (
        "CREATE INDEX IF NOT EXISTS idx_mails_job_mailed_at ON mails (job_id, mailed_at)"
    )
    IDX_MAILS_THREAD_KEY = (
        "CREATE INDEX IF NOT EXISTS idx_mails_thread_key ON mails (job_id, thread_key)"
    )
    IDX_MAILS_MESSAGE_ID = (
        "CREATE INDEX IF NOT EXISTS idx_mails_message_id ON mails (job_id, message_id)"
    )

    ENSURE_WEEKLY_REPORTS = """
    CREATE TABLE IF NOT EXISTS weekly_reports (
        id              BIGSERIAL PRIMARY KEY,
        job_id          BIGINT NOT NULL UNIQUE REFERENCES analysis_jobs(id) ON DELETE CASCADE,
        model           TEXT NOT NULL DEFAULT '',
        scope_note      TEXT NOT NULL DEFAULT '',
        report          JSONB NOT NULL DEFAULT '{}'::jsonb,
        report_markdown TEXT,
        created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
        updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
    """

    IDX_WEEKLY_REPORTS_CREATED_AT = """
    CREATE INDEX IF NOT EXISTS idx_weekly_reports_created_at
        ON weekly_reports (created_at DESC)
    """

class Jobs:
    INSERT = """
    INSERT INTO analysis_jobs (
        status, mailbox_scope, date_from, date_to, model,
        inbox_zip_name, sent_zip_name
    )
    VALUES (
        'pending', %(mailbox_scope)s, %(date_from)s, %(date_to)s, %(model)s,
        %(inbox_zip_name)s, %(sent_zip_name)s
    )
    RETURNING id, status, mailbox_scope, date_from, date_to, model,
              inbox_zip_name, sent_zip_name,
              inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
              progress_pct, progress_label, progress_detail,
              error_message, created_at, started_at, completed_at
    """

    GET_BY_ID = """
    SELECT id, status, mailbox_scope, date_from, date_to, model,
           inbox_zip_name, sent_zip_name,
           inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
           progress_pct, progress_label, progress_detail,
           error_message, created_at, started_at, completed_at
    FROM analysis_jobs
    WHERE id = %(job_id)s
    """

    LIST_RECENT = """
    SELECT id, status, mailbox_scope, date_from, date_to, model,
           inbox_zip_name, sent_zip_name,
           inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
           progress_pct, progress_label, progress_detail,
           error_message, created_at, started_at, completed_at
    FROM analysis_jobs
    ORDER BY created_at DESC
    LIMIT %(limit)s
    """

    UPDATE = """
    UPDATE analysis_jobs
    SET
        status = COALESCE(%(status)s, status),
        inbox_count = COALESCE(%(inbox_count)s, inbox_count),
        sent_count = COALESCE(%(sent_count)s, sent_count),
        filtered_inbox_count = COALESCE(%(filtered_inbox_count)s, filtered_inbox_count),
        filtered_sent_count = COALESCE(%(filtered_sent_count)s, filtered_sent_count),
        progress_pct = COALESCE(%(progress_pct)s, progress_pct),
        progress_label = COALESCE(%(progress_label)s, progress_label),
        progress_detail = COALESCE(%(progress_detail)s, progress_detail),
        error_message = COALESCE(%(error_message)s, error_message),
        started_at = CASE
            WHEN %(set_started)s THEN COALESCE(started_at, NOW())
            ELSE started_at
        END,
        completed_at = CASE
            WHEN %(set_completed)s THEN NOW()
            ELSE completed_at
        END
    WHERE id = %(job_id)s
    RETURNING id, status, mailbox_scope, date_from, date_to, model,
              inbox_zip_name, sent_zip_name,
              inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
              progress_pct, progress_label, progress_detail,
              error_message, created_at, started_at, completed_at
    """


class Mails:
    INSERT = """
    INSERT INTO mails (
        job_id, mailbox, message_id, thread_key, subject,
        from_addr, to_addrs, cc_addrs, mailed_at,
        attachment_names, body_text
    )
    VALUES (
        %(job_id)s, %(mailbox)s, %(message_id)s, %(thread_key)s, %(subject)s,
        %(from_addr)s, %(to_addrs)s, %(cc_addrs)s, %(mailed_at)s,
        %(attachment_names)s, %(body_text)s
    )
    RETURNING id
    """

    LIST_BY_JOB = """
    SELECT id, job_id, mailbox, message_id, thread_key, subject,
           from_addr, to_addrs, cc_addrs, mailed_at,
           attachment_names, body_text, body_purged, summary, created_at
    FROM mails
    WHERE job_id = %(job_id)s
    ORDER BY mailed_at NULLS LAST, id
    """

    UPDATE_SUMMARY = """
    UPDATE mails
    SET summary = %(summary)s
    WHERE id = %(mail_id)s
    """

    PURGE_BODIES = """
    UPDATE mails
    SET body_text = NULL, body_purged = TRUE
    WHERE job_id = %(job_id)s
    """


class Reports:
    GET_BY_JOB = """
    SELECT id, job_id, model, scope_note, report, report_markdown,
           created_at, updated_at
    FROM weekly_reports
    WHERE job_id = %(job_id)s
    """

    UPSERT = """
    INSERT INTO weekly_reports (job_id, model, scope_note, report, report_markdown)
    VALUES (
        %(job_id)s, %(model)s, %(scope_note)s,
        %(report)s, %(report_markdown)s
    )
    ON CONFLICT (job_id) DO UPDATE SET
        model = EXCLUDED.model,
        scope_note = EXCLUDED.scope_note,
        report = EXCLUDED.report,
        report_markdown = EXCLUDED.report_markdown,
        updated_at = NOW()
    RETURNING id, job_id, model, scope_note, report, report_markdown,
              created_at, updated_at
    """
