"""Command-line interface for Yosoi.

Handles argument parsing and delegates to pipeline.
"""

import argparse
import json
import os
import sys

import logfire
from dotenv import load_dotenv

from yosoi import gemini, groq
from yosoi.pipeline import SelectorDiscoveryPipeline
from yosoi.utils.files import init_yosoi, is_initialized
from yosoi.utils.logging import setup_local_logging


def setup_llm_config():
    """Set up LLM configuration from environment variables.

    Checks for GROQ_KEY first, then GEMINI_KEY.

    Returns:
        LLMConfig instance configured with available API key.

    Raises:
        SystemExit: If no API keys are found in environment.

    """
    groq_api_key = os.getenv('GROQ_KEY')
    gemini_api_key = os.getenv('GEMINI_KEY')

    if groq_api_key:
        print('Using GROQ as AI provider')
        return groq('llama-3.3-70b-versatile', groq_api_key)

    if gemini_api_key:
        print('Using Gemini as AI provider')
        return gemini('gemini-2.0-flash-exp', gemini_api_key)

    print('Error: No API keys found')
    print('Please set GROQ_KEY or GEMINI_KEY in your .env file')
    sys.exit(1)


def setup_logfire():
    """Set up Logfire observability if token is available.

    Configures Logfire and instruments Pydantic if LOGFIRE_TOKEN is set.

    Returns:
        None

    """
    logfire_token = os.getenv('LOGFIRE_TOKEN')
    if logfire_token:
        logfire.configure(token=logfire_token)
        logfire.instrument_pydantic()
        print('Logfire setup complete')
    else:
        print('LOGFIRE_TOKEN not set - skipping logfire setup')


def load_urls_from_file(filepath: str) -> list[str]:
    """Load URLs from a file (JSON or plain text).

    Args:
        filepath: Path to file containing URLs

    Returns:
        List of URL strings.

    Raises:
        SystemExit: If file is not found.

    """
    if not os.path.exists(filepath):
        print(f'Error: File not found: {filepath}')
        sys.exit(1)

    if filepath.endswith('.json'):
        with open(filepath) as f:
            data = json.load(f)

        # Extract URLs based on structure
        if isinstance(data, list):
            return [item.get('url', item) for item in data if item]
        return [data[key]['url'] for key in data if 'url' in data.get(key, {})]
    # Plain text file
    with open(filepath) as f:
        return [line.strip() for line in f if line.strip() and not line.startswith('#')]


def parse_arguments():
    """Parse command-line arguments.

    Returns:
        argparse.Namespace object with parsed arguments.

    """
    parser = argparse.ArgumentParser(
        description='Discover selectors from web pages using AI',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s -u https://example.com
  %(prog)s -f urls.txt -l 10
  %(prog)s --url https://example.com --force
  %(prog)s -s
  %(prog)s -u https://example.com -d -F
        """,
    )

    parser.add_argument('-u', '--url', type=str, help='Single URL to process')
    parser.add_argument('-f', '--file', type=str, help='File containing URLs (one per line, or JSON)')
    parser.add_argument('-l', '--limit', type=int, help='Limit number of URLs to process from file')
    parser.add_argument('-F', '--force', action='store_true', help='Force re-discovery even if selectors exist')
    parser.add_argument('-s', '--summary', action='store_true', help='Show summary of saved selectors')
    parser.add_argument(
        '-d', '--debug', action='store_true', help='Enable debug mode (saves extracted HTML to debug_html/)'
    )
    parser.add_argument('-S', '--skip-validation', action='store_true', help='Skip validation for faster processing')
    parser.add_argument(
        '-o',
        '--output',
        choices=['json', 'markdown', 'md'],
        default='json',
        help='Output format for extracted content (default: json)',
    )
    parser.add_argument(
        '-t',
        '--fetcher',
        choices=['simple', 'playwright', 'smart'],
        default='simple',
        help='HTML fetcher to use (default: simple)',
    )
    parser.add_argument(
        '-L',
        '--log-level',
        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'ALL'],
        default=os.getenv('YOSOI_LOG_LEVEL', 'DEBUG'),
        help='Logging level for the local log file (default: DEBUG or YOSOI_LOG_LEVEL env)',
    )

    return parser.parse_args()


def print_fetcher_info(fetcher_type: str):
    """Print information about the selected fetcher.

    Args:
        fetcher_type: Type of fetcher ('simple', 'playwright', or 'smart')

    Returns:
        None

    """
    if fetcher_type == 'playwright':
        print('ℹ Using Playwright fetcher (slower but more reliable)')
    elif fetcher_type == 'smart':
        print('ℹ Using Smart fetcher (tries simple first, falls back to Playwright)')
    else:
        print('ℹ Using Simple fetcher (fast, works for most sites)')


def main():
    """Run the CLI entry point."""
    # Load environment variables
    load_dotenv()

    # Parse arguments
    args = parse_arguments()

    if not is_initialized():
        init_yosoi()

    # Set up LLM configuration
    llm_config = setup_llm_config()

    # Initialize logging
    log_file = setup_local_logging(level=args.log_level)

    # Normalize output format
    output_format = 'markdown' if args.output in ['markdown', 'md'] else 'json'

    # Initialize pipeline with output format
    pipeline = SelectorDiscoveryPipeline(llm_config, debug_mode=args.debug, output_format=output_format)

    # Set up Logfire
    setup_logfire()

    from rich import print as rprint

    # Show log file link
    rprint(f'ℹ Log file: [link=file://{log_file}]file://{log_file}[/link]')

    # Handle summary request (quick exit)
    if args.summary:
        pipeline.show_summary()
        return

    # Gather URLs
    urls = []

    if args.url:
        urls.append(args.url)

    if args.file:
        file_urls = load_urls_from_file(args.file)
        urls.extend(file_urls)

    if not urls:
        print('Error: No URLs provided')
        print('Use --url <url> or --file <file>')
        sys.exit(1)

    # Apply limit if specified
    if args.limit:
        urls = urls[: args.limit]
        print(f'ℹ Limiting to first {args.limit} URLs')

    # Show debug info
    if args.debug:
        print('ℹ Debug mode enabled - extracted HTML will be saved to debug_html/')

    # Show output format info
    print(f'ℹ Output format: {output_format}')

    # Show fetcher info
    print_fetcher_info(args.fetcher)

    # Process URLs (output_format already set in pipeline)
    pipeline.process_urls(
        urls,
        force=args.force,
        skip_validation=args.skip_validation,
        fetcher_type=args.fetcher,
    )


if __name__ == '__main__':
    main()
