#!/usr/bin/env python3
"""Add a comment and optional attachment to a Jira issue via REST API.

Uses Typer for elegant CLI, loads credentials from ~/.jira.env,
supports interactive multiline input and attachment notes.
"""

import getpass
import shutil
from datetime import datetime
from pathlib import Path
from typing import Optional

import requests
import typer
from requests.auth import HTTPBasicAuth

from .jira_helper import load_jira_env
from .logging_helper import setup_logging
from .prompt_helper import read_multiline_input

app = typer.Typer(
    add_completion=False,
    help="Add a comment (with optional attachment) to a Jira issue.",
    epilog="Credentials are loaded from ~/.jira.env (JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN)",
)


def confirm_comment(text: str) -> bool:
    """Show comment and confirm with user.

    Args:
        text: The comment text to display.

    Returns:
        True if user confirms, False to abort.
    """
    typer.echo("\nYour comment:")
    typer.echo("-" * 60)
    typer.echo(text.strip() or "(empty)")
    typer.echo("-" * 60)
    return typer.confirm("Proceed with this comment?", default=True)


def get_attachment_note() -> str:
    """Prompt for pre-canned or custom attachment note.

    Returns:
        str: The selected or entered note text.
    """
    canned_options = [
        "This README.md outlines steps for testing and evaluation.",
        "This is the STDOUT.",
        "This is the STDERR.",
        "This is the log file.",
    ]

    use_canned = typer.confirm("Use pre-canned accompanying note?", default=True)
    if use_canned:
        typer.echo("Available notes:")
        for i, opt in enumerate(canned_options, 1):
            typer.echo(f"  {i}. {opt}")
        while True:
            choice = typer.prompt("Select (number or type part of text)", type=str)
            if choice.isdigit() and 1 <= int(choice) <= len(canned_options):
                return canned_options[int(choice) - 1]
            for opt in canned_options:
                if choice.lower() in opt.lower():
                    return opt
            typer.echo("Invalid selection. Try again.", err=True)
    else:
        return typer.prompt("Enter your one-line note", type=str).strip()


@app.command()
def main(
    jira_id: str = typer.Argument(..., help="Jira issue key, e.g. JPS-1220"),
    comment_file: Optional[Path] = typer.Option(
        None, "--comment-file", help="File containing comment text"
    ),
    attach_file: Optional[Path] = typer.Option(
        None, "--attach-file", help="File to attach to the comment"
    ),
    logfile: Optional[Path] = typer.Option(
        None,
        "--logfile",
        help="Custom log file path (default: /tmp/<user>/add_comment.py/<timestamp>/add_comment.py.log)",
    ),
) -> None:
    """Add a comment and optional attachment to a Jira issue.

    Args:
        jira_id: The Jira issue key (e.g. JPS-1220).
        comment_file: Optional file path to load comment from.
        attach_file: Optional file path to attach.
        logfile: Optional custom log file path.

    Raises:
        Exit: On error or user cancellation.
    """
    timestamp = datetime.now().strftime("%Y-%m-%d-%H%M%S")
    default_log_dir = Path("/tmp") / getpass.getuser() / "add_comment.py" / timestamp
    log_file = logfile or (default_log_dir / "add_comment.py.log")
    log_file = log_file.expanduser().resolve()

    logger = setup_logging(log_file)
    logger.info("=== add_comment.py started ===")
    logger.info("Jira ID: %s", jira_id)
    logger.info("Comment file: %s", comment_file)
    logger.info("Attach file: %s", attach_file)

    base_url, email, token = load_jira_env()
    auth = HTTPBasicAuth(email, token)
    session = requests.Session()
    session.auth = auth
    session.headers.update({"Accept": "application/json"})

    jira_url = f"{base_url}/browse/{jira_id}"
    logger.info("Jira URL: %s", jira_url)

    # === Get comment text ===
    comment_text: str = ""
    if comment_file:
        comment_file = comment_file.expanduser().resolve()
        if not comment_file.is_file():
            logger.error("Comment file not found: %s", comment_file)
            typer.echo(f"Error: Comment file not found: {comment_file}", err=True)
            raise typer.Exit(1)
        comment_text = comment_file.read_text(encoding="utf-8")
        logger.info("Loaded comment from %s", comment_file)
    else:
        comment_text = read_multiline_input("Enter your comment (end with two blank lines):")
        if not confirm_comment(comment_text):
            logger.info("User aborted after comment entry")
            typer.echo("Cancelled.")
            raise typer.Exit(0)

    # === Handle attachment ===
    attachment_path: Optional[Path] = None
    attachment_note: Optional[str] = None
    readme_timestamp_name: Optional[str] = None

    if attach_file:
        attach_file = attach_file.expanduser().resolve()
        if not attach_file.exists():
            logger.error("Attachment not found: %s", attach_file)
            typer.echo(f"Error: Attachment file does not exist: {attach_file}", err=True)
            raise typer.Exit(1)
        if not attach_file.is_file():
            logger.error("Attachment path is not a file: %s", attach_file)
            typer.echo(f"Error: Not a regular file: {attach_file}", err=True)
            raise typer.Exit(1)
        if attach_file.stat().st_size == 0:
            logger.error("Attachment is empty: %s", attach_file)
            typer.echo(f"Error: Attachment file is empty: {attach_file}", err=True)
            raise typer.Exit(1)

        # If it's a README.md, create timestamped copy
        if attach_file.name == "README.md":
            timestamp_formatted = datetime.now().strftime("%Y-%m-%d-%H%M")
            readme_timestamp_name = f"README-{timestamp_formatted}.md"
            timestamped_path = attach_file.parent / readme_timestamp_name
            shutil.copy2(attach_file, timestamped_path)
            attachment_path = timestamped_path
            logger.info("Created timestamped copy: %s", timestamped_path)
        else:
            attachment_path = attach_file

        logger.info(
            "Validated attachment: %s (%d bytes)", attachment_path, attachment_path.stat().st_size
        )

        if typer.confirm("Add accompanying note for attachment?", default=True):
            attachment_note = get_attachment_note()

    # === Final confirmation table ===
    typer.echo("\n" + "=" * 70)
    typer.echo("FINAL REVIEW - ABOUT TO POST")
    typer.echo("=" * 70)
    typer.echo(f"Jira Ticket       : {jira_id}")
    typer.echo(f"Jira URL          : {jira_url}")
    typer.echo(
        f"Comment           : {'(empty)' if not comment_text.strip() else comment_text.splitlines()[0]}{' ...' if len(comment_text.splitlines()) > 1 else ''}"  # noqa: E501
    )
    typer.echo(f"Attachment        : {attachment_path or 'None'}")
    typer.echo(f"Attachment Note   : {attachment_note or 'None'}")
    typer.echo("=" * 70)

    if not typer.confirm("Proceed and post to Jira?", default=True):
        logger.info("User cancelled at final confirmation")
        typer.echo("Cancelled.")
        raise typer.Exit(0)

    # === Build comment body ===
    full_comment = ""
    
    # If README was timestamped, add the "Attached README-..." line first
    if readme_timestamp_name:
        full_comment = f"Attached {readme_timestamp_name}.\n\n"
    
    # Add user comment
    full_comment += comment_text
    
    # Add attachment note if provided
    if attachment_note:
        full_comment += f"\n\n{attachment_note}"

    payload = {
        "body": {
            "type": "doc",
            "version": 1,
            "content": [{"type": "paragraph", "content": [{"type": "text", "text": full_comment}]}],
        }
    }

    # === Post comment ===
    comment_url = f"{base_url}/rest/api/3/issue/{jira_id}/comment"
    logger.info("POST comment → %s", comment_url)
    resp = session.post(comment_url, json=payload)
    if not resp.ok:
        logger.error("Comment failed: %d %s", resp.status_code, resp.text)
        typer.echo(f"Failed to add comment: {resp.status_code}", err=True)
        typer.echo(resp.text, err=True)
        raise typer.Exit(1)

    comment_id = resp.json().get("id")
    logger.info("Comment created: %s", comment_id)

    # === Upload attachment ===
    if attachment_path:
        files = {"file": (attachment_path.name, open(attachment_path, "rb"))}
        attach_url = f"{base_url}/rest/api/3/issue/{jira_id}/attachments"
        headers = {"X-Atlassian-Token": "nocheck"}
        logger.info("Uploading attachment → %s", attach_url)
        resp = session.post(attach_url, headers=headers, files=files)
        if resp.ok:
            logger.info("Attachment uploaded successfully")
        else:
            logger.error("Attachment upload failed: %d %s", resp.status_code, resp.text)
            typer.echo(f"Warning: Attachment upload failed: {resp.status_code}", err=True)

    # === Success ===
    typer.echo(f"\nSuccess! Comment added to {jira_id}")
    typer.echo(f"Jira URL: {jira_url}")
    typer.echo(f"Wrote the log file to '{log_file}'")


if __name__ == "__main__":
    app()
