#!/usr/bin/env python3
"""
Weekly health report script.

Generates a Slack-formatted summary of the previous week's health data
and posts it to the configured Slack channel.

Usage:
    python scripts/weekly_report.py

Cron example (every Monday at 11:00 AM):
    0 11 * * 1 cd /root/projects/butler && /root/projects/butler/venv/bin/python /root/projects/butler/scripts/weekly_report.py >> /root/projects/butler/logs/cron.log 2>&1

Required env vars:
    SLACK_BOT_TOKEN      - Slack bot OAuth token (xoxb-...)
    SLACK_REPORT_CHANNEL - Target channel ID (C0XXXXXXXXX)
"""

import os
import sys
from datetime import date, timedelta
from pathlib import Path

# Add project root to path
sys.path.insert(0, str(Path(__file__).parent.parent))

from health.analytics.weekly_report import WeeklyReportGenerator
from health.utils.env_loader import load_env_with_extras
from health.utils.logging_config import setup_logger

logger = setup_logger(__name__, log_file="weekly_report.log")

_MAX_SLACK_MESSAGE_LEN = 3900


def _last_monday() -> date:
    """Return the Monday of the previous week.

    Always returns the most recently completed Monday (never today),
    so the full 7-day week is available.

    Returns:
        Date of last Monday.
    """
    today = date.today()
    # days_since_monday: 0=Mon, 1=Tue, ..., 6=Sun
    days_since_monday = today.weekday()
    # Go back to this week's Monday, then subtract 7 more days
    this_monday = today - timedelta(days=days_since_monday)
    return this_monday - timedelta(days=7)


def _split_message(text: str, max_len: int = _MAX_SLACK_MESSAGE_LEN) -> list[str]:
    """Split a long message into chunks that fit within Slack's limits.

    Splits on newline boundaries when possible.

    Args:
        text: Full message text.
        max_len: Maximum characters per chunk.

    Returns:
        List of message chunks.
    """
    if len(text) <= max_len:
        return [text]

    chunks: list[str] = []
    current_lines: list[str] = []
    current_len = 0

    for line in text.splitlines(keepends=True):
        if current_len + len(line) > max_len and current_lines:
            chunks.append("".join(current_lines))
            current_lines = []
            current_len = 0
        current_lines.append(line)
        current_len += len(line)

    if current_lines:
        chunks.append("".join(current_lines))

    return chunks


def main() -> int:
    """Generate and post the weekly health report.

    Returns:
        Exit code: 0 for success, 1 for failure.
    """
    from datetime import datetime

    start_time = datetime.now()
    logger.info("=" * 60)
    logger.info(f"Weekly Report Started: {start_time.isoformat()}")
    logger.info("=" * 60)

    load_env_with_extras()

    slack_token = os.environ.get("SLACK_BOT_TOKEN")
    report_channel = os.environ.get("SLACK_REPORT_CHANNEL")

    if not slack_token:
        logger.error("SLACK_BOT_TOKEN is not set in environment")
        return 1
    if not report_channel:
        logger.error("SLACK_REPORT_CHANNEL is not set in environment")
        return 1

    week_start = _last_monday()
    logger.info(f"Generating report for week starting {week_start}")

    try:
        report_text = WeeklyReportGenerator().generate(week_start)
    except Exception as e:
        logger.exception(f"Report generation failed: {e}")
        return 1

    logger.info(f"Report generated ({len(report_text)} chars)")

    try:
        from slack_sdk import WebClient

        client = WebClient(token=slack_token)
        chunks = _split_message(report_text)
        logger.info(f"Sending {len(chunks)} message chunk(s) to {report_channel}")

        for i, chunk in enumerate(chunks):
            client.chat_postMessage(channel=report_channel, text=chunk)
            logger.info(f"Chunk {i + 1}/{len(chunks)} sent")

    except Exception as e:
        logger.exception(f"Failed to send Slack message: {e}")
        return 1

    end_time = datetime.now()
    duration = (end_time - start_time).total_seconds()
    logger.info(f"Weekly report complete. Duration: {duration:.2f}s")
    logger.info("=" * 60)

    return 0


if __name__ == "__main__":
    sys.exit(main())
