"""Tool: archive_campaign — Mark a campaign as completed/archived.

Archived campaigns stop receiving outreach and move to completed status.
They remain viewable via show_status(campaign_id=...) for historical reference.
"""

from __future__ import annotations

import logging

from ..db.queries import (
    count_open_outreaches,
    get_campaign,
    get_setting,
    list_campaigns,
    log_action,
    skip_pending_outreaches,
    update_campaign,
)

logger = logging.getLogger(__name__)


async def run_archive_campaign(campaign_id: str = "", force: bool = False) -> str:
    """Archive a campaign, setting its status to 'completed'.

    If no campaign_id is provided, archives the first non-completed campaign found.
    If connected/invited prospects remain un-messaged, returns a warning unless
    force=True is passed.
    """

    setup_done = get_setting("setup_complete", False)
    if not setup_done:
        return (
            "Setup required before managing campaigns.\n\n"
            "Please run setup_profile first."
        )

    # Find the campaign to archive
    if campaign_id:
        campaign = get_campaign(campaign_id)
        if not campaign:
            return f"Campaign not found: {campaign_id}"
    else:
        campaigns = list_campaigns()
        # Pick the first non-completed campaign
        candidates = [c for c in campaigns if c.get("status") != "completed"]
        if not candidates:
            return (
                "No campaigns available to archive.\n\n"
                "All campaigns are already archived, or no campaigns exist.\n"
                "Use show_status() to see all campaigns."
            )
        campaign = candidates[0]
        campaign_id = campaign["id"]

    # Check current status
    status = campaign.get("status", "")
    if status == "completed":
        return (
            f"Campaign '{campaign['name']}' is already archived.\n\n"
            f"View it with: show_status(campaign_id=\"{campaign_id}\")"
        )

    # Warn about un-messaged prospects unless force=True
    open_counts = count_open_outreaches(campaign_id)
    total_open = sum(open_counts.values())
    if total_open > 0 and not force:
        parts = [f"{cnt} {status}" for status, cnt in sorted(open_counts.items())]
        warning = " + ".join(parts)
        return (
            f"Cannot archive '{campaign['name']}' — {warning} prospects "
            f"still have pending work.\n\n"
            f"These prospects accepted invitations or are connected but haven't "
            f"received a DM yet. Archiving will silently abandon them.\n\n"
            f"Options:\n"
            f"- Keep the campaign active so the scheduler finishes outreach\n"
            f"- Run archive_campaign(campaign_id=\"{campaign_id}\", force=True) "
            f"to archive anyway\n"
        )

    # Archive it and skip pending outreaches
    skipped = skip_pending_outreaches(campaign_id)
    update_campaign(campaign_id, status="completed")

    log_details: dict = {
        "campaign_id": campaign_id,
        "campaign_name": campaign["name"],
        "previous_status": status,
        "pending_skipped": skipped,
    }
    if total_open > 0:
        log_details["open_outreaches_abandoned"] = open_counts
        log_action(
            "campaign_archived_with_open_work",
            details=log_details,
        )
    else:
        log_action("campaign_archived", details=log_details)
    logger.info(f"Archived campaign {campaign_id}: {campaign['name']}")

    result = (
        f"Campaign '{campaign['name']}' has been archived.\n\n"
        f"{skipped} pending outreaches marked as skipped.\n"
    )
    if total_open > 0:
        parts = [f"{cnt} {status}" for status, cnt in sorted(open_counts.items())]
        result += f"Warning: {' + '.join(parts)} prospects were abandoned without messaging.\n"
    result += (
        "No further outreach will be sent for this campaign.\n\n"
        f"To view archived campaign details: show_status(campaign_id=\"{campaign_id[:8]}...\")\n"
        "To create a new campaign: create_campaign(\"your target description\")"
    )
    return result
