"""Store tripwire candidates as a metadata comment on a plan.

Usage:
    erk exec store-tripwire-candidates --plan-number <N> --candidates-file <path>

Reads a JSON file produced by the tripwire extraction agent and adds
a metadata comment to the plan with key `tripwire-candidates`.

Exit Codes:
    0: Success
    1: Error (file not found, invalid JSON, GitHub API failure)
"""

import json
from dataclasses import asdict, dataclass
from pathlib import Path

import click

from erk.cli.commands.exec.scripts.normalize_tripwire_candidates import (
    normalize_candidates_data,
)
from erk_shared.context.helpers import require_issues, require_repo_root
from erk_shared.gateway.github.metadata.tripwire_candidates import (
    InvalidTripwireCandidates,
    render_tripwire_candidates_comment,
    validate_candidates_data,
)


@dataclass(frozen=True)
class StoreSuccess:
    """Success response for tripwire candidates storage."""

    success: bool
    count: int


@dataclass(frozen=True)
class StoreError:
    """Error response for tripwire candidates storage."""

    success: bool
    error: str


@click.command(name="store-tripwire-candidates")
@click.option("--plan-number", required=True, type=int, help="Plan number")
@click.option("--candidates-file", required=True, help="Path to tripwire-candidates.json")
@click.pass_context
def store_tripwire_candidates(
    ctx: click.Context,
    *,
    plan_number: int,
    candidates_file: str,
) -> None:
    """Store tripwire candidates as a metadata comment on a plan."""
    repo_root = require_repo_root(ctx)
    issues = require_issues(ctx)

    # Read, normalize, and validate candidates file
    path = Path(candidates_file)
    if not path.is_file():
        error_response = StoreError(
            success=False, error=f"Candidates file not found: {candidates_file}"
        )
        click.echo(json.dumps(asdict(error_response)), err=True)
        raise SystemExit(1)

    raw = path.read_text(encoding="utf-8")
    try:
        data = json.loads(raw)
    except json.JSONDecodeError as exc:
        error_response = StoreError(success=False, error=f"Invalid JSON: {exc}")
        click.echo(json.dumps(asdict(error_response)), err=True)
        raise SystemExit(1) from None

    if not isinstance(data, dict):
        error_response = StoreError(
            success=False, error=f"Expected JSON object, got {type(data).__name__}"
        )
        click.echo(json.dumps(asdict(error_response)), err=True)
        raise SystemExit(1)

    normalized_data, _changed = normalize_candidates_data(data)
    result = validate_candidates_data(normalized_data)
    if isinstance(result, InvalidTripwireCandidates):
        error_response = StoreError(success=False, error=result.message)
        click.echo(json.dumps(asdict(error_response)), err=True)
        raise SystemExit(1)

    candidates = result.candidates
    if not candidates:
        # No candidates to store - still success
        success_response = StoreSuccess(success=True, count=0)
        click.echo(json.dumps(asdict(success_response)))
        return

    # Render metadata comment
    comment_body = render_tripwire_candidates_comment(candidates)

    # Post comment to issue
    issues.add_comment(repo_root, plan_number, comment_body)

    success_response = StoreSuccess(success=True, count=len(candidates))
    click.echo(json.dumps(asdict(success_response)))
