#!/usr/bin/env python3
"""CLI entry point for code-reviewer

Usage:
    reviewate owner/repo -p 123                    # review (default)
    reviewate summary owner/repo -p 123            # summary only
    reviewate full owner/repo -p 123               # review + summary
    reviewate review owner/repo -p 123 --dry-run   # explicit review

    # From URL (platform, repo, PR auto-detected):
    reviewate https://github.com/org/repo/pull/48
    reviewate https://gitlab.com/group/repo/-/merge_requests/1
    reviewate https://gitlab.example.com/group/sub/project/-/merge_requests/352
"""

from __future__ import annotations

import asyncio
import json
import os
import sys
import time
from collections.abc import Callable

# Fix imports when running as script (not as module)
if __name__ == "__main__" and __package__ is None:
    # Add parent directory to path so we can import code_reviewer
    _parent = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.insert(0, _parent)
    __package__ = "code_reviewer"

    # Load .env file for local development only (not when installed as a package).
    # Sets _REVIEWATE_DOTENV_OK so __init__.py knows not to neuter load_dotenv.
    os.environ["_REVIEWATE_DOTENV_OK"] = "1"
    from dotenv import load_dotenv

    load_dotenv()

from rich.console import Console

from code_reviewer import __version__
from code_reviewer.adaptors.factory import create_platform_handlers
from code_reviewer.cli import parse_args
from code_reviewer.config import Platform
from code_reviewer.config_file import _run_interactive_setup, load_config_file
from code_reviewer.errors import CLIError, ErrorType, PostingError, error_type_for_exception
from code_reviewer.logging_config import BaseLogger, setup_logging
from code_reviewer.output import ProgressTracker, emit_error, emit_result, print_result_summary
from code_reviewer.runner import _aggregate_results, _load_and_validate_config, _run_review_workflow
from code_reviewer.workflows import run_summary_workflow
from code_reviewer.workflows.context import LinkedRepoInfo
from code_reviewer.workflows.review import WorkflowResult
from code_reviewer.workflows.summary import SummaryResult

# Initialize module logger wrapper
logger = BaseLogger("main", "main")


def cli_entry() -> None:
    """Sync entry point for `pip install reviewate` console script."""
    try:
        sys.exit(asyncio.run(main()))
    except KeyboardInterrupt:
        sys.exit(1)
    except Exception as e:
        _console = Console(stderr=True, highlight=False)
        _console.print(f"[bold red]Error:[/] {e}")
        if "--debug" in sys.argv:
            _console.print_exception()
        sys.exit(1)


async def main() -> int:
    """Main entry point for the CLI."""
    args = parse_args()

    # Handle config subcommand (no review, just re-run setup)
    if args.command == "config":
        try:
            _run_interactive_setup()
        except KeyboardInterrupt:
            Console(stderr=True, highlight=False).print("\n[dim]Cancelled.[/]")
            return 1
        return 0

    start_time = time.time()

    # Setup logging: containers set LOG_LEVEL explicitly; TTY uses the progress
    # tracker as sole UI so we suppress all log output (CRITICAL).
    is_tty = sys.stderr.isatty()
    log_level = os.getenv("LOG_LEVEL", "CRITICAL" if is_tty else "INFO")
    setup_logging(log_level, debug=args.debug)

    # Set global flag for disabling thinking (checked by base agent)
    if args.disable_thinking:
        os.environ["DISABLE_THINKING"] = "1"
        logger.info("Extended thinking disabled (non-thinking model mode)")

    try:
        logger.info("=" * 60)
        logger.info("REVIEWATE_START")
        logger.info("=" * 60)
        logger.info(
            f"Starting Reviewate CLI - repo={args.repo} pr={args.pr} platform={args.platform}"
        )

        # Load config file (interactive setup on first run if needed)
        file_config = load_config_file()
        config, review_provider, utility_provider = _load_and_validate_config(args, file_config)

        logger.debug(f"Configuration loaded: platform={args.platform} repo={args.repo}")

        # Create platform adaptors
        repository, issue_handler = create_platform_handlers(args.platform, config)

        # Determine platform
        platform = Platform.GITHUB if args.platform == "github" else Platform.GITLAB

        # Parse linked repositories from env var (set by container backend)
        linked_repos_input: list[LinkedRepoInfo] | None = None
        linked_repos_env = os.getenv("LINKED_REPOS")
        if linked_repos_env:
            try:
                linked_repos_input = json.loads(linked_repos_env)
                logger.info(f"Loaded {len(linked_repos_input)} linked repos from env")
            except json.JSONDecodeError:
                logger.warning("Failed to parse LINKED_REPOS env var")

        # Parse team guidelines from env var (set by container backend)
        team_guidelines = os.getenv("TEAM_GUIDELINES")
        if team_guidelines:
            logger.info("Loaded team guidelines from env")

        results: list[tuple[str, WorkflowResult | SummaryResult]] = []

        # Progress tracker for TTY mode (spinner + step log)
        tracker: ProgressTracker | None = None
        _exit_error: str | None = None
        on_status: Callable[[str], None] | None = None
        on_step_done: Callable[[str], None] | None = None

        if is_tty:
            workflows_label = " + ".join(
                f for f, enabled in [("review", args.review), ("summary", args.summary)] if enabled
            )
            tracker = ProgressTracker(
                repo=args.repo,
                pr=args.pr,
                workflows=workflows_label,
                review_model=f"{review_provider}/{config.get_agent_model('review_agent')}",
                utility_model=f"{utility_provider}/{config.get_agent_model('style_agent')}",
                version=__version__,
            )
            tracker.start()
            on_status = tracker.step
            on_step_done = tracker.done

        try:
            # Run summary workflow first (faster, gives quick feedback)
            if args.summary:
                logger.info("Starting summary workflow")
                if on_status:
                    on_status("Running summary workflow...")

                summary_result = await run_summary_workflow(
                    config=config,
                    repository=repository,
                    issue_handler=issue_handler,
                    repo=args.repo,
                    merge_id=args.pr,
                    dry_run=args.dry_run,
                    on_status=on_status,
                    on_step_done=on_step_done,
                )
                results.append(("Summary", summary_result))

            # Run review workflow if requested
            if args.review:
                logger.info("Starting review workflow")
                review_result = await _run_review_workflow(
                    args=args,
                    config=config,
                    repository=repository,
                    issue_handler=issue_handler,
                    platform=platform,
                    linked_repos_input=linked_repos_input,
                    team_guidelines=team_guidelines,
                    on_status=on_status,
                    on_step_done=on_step_done,
                )
                results.append(("Review", review_result))
        except CLIError as e:
            _exit_error = str(e)
            return 1
        except Exception as e:
            _exit_error = str(e)
            raise
        finally:
            if tracker is not None:
                if _exit_error:
                    tracker.fail(_exit_error)
                else:
                    tracker.finish()

        result_data = _aggregate_results(results)
        print_result_summary(result_data)
        emit_result(result_data, include_reviews=args.dry_run)
        return 0

    except KeyboardInterrupt:
        total_duration = time.time() - start_time
        logger.warning(f"REVIEWATE_INTERRUPTED user_cancelled=true duration={total_duration:.2f}s")
        emit_error(ErrorType.INTERRUPTED, "User cancelled the operation")
        return 1
    except PostingError as e:
        total_duration = time.time() - start_time
        logger.error(
            f"REVIEWATE_ERROR error_type=PostingError message={str(e)} duration={total_duration:.2f}s"
        )
        emit_error(ErrorType.POST_FAILED, str(e))
        return 1
    except Exception as e:
        total_duration = time.time() - start_time
        logger.error(
            f"REVIEWATE_ERROR error_type={type(e).__name__} message={str(e)} duration={total_duration:.2f}s"
        )
        if args.debug:
            logger.exception("Full traceback:")
        emit_error(error_type_for_exception(e), str(e))
        return 1


if __name__ == "__main__":
    cli_entry()
