#!/usr/bin/env python3
"""
Preview duplicate code detection on file(s) or directory.

This is read-only - it won't modify any files.

Usage:
    python3 preview.py <file_or_directory>
    python3 preview.py my_file.py
    python3 preview.py src/
    python3 preview.py .
"""

import sys
import os
import ast
import argparse
from towel.unification.refactor_engine import (
    UnificationRefactorEngine,
    filter_overlapping_proposals,
)


def main():
    parser = argparse.ArgumentParser(
        description="Preview unification-based refactoring opportunities."
    )
    parser.add_argument("target", help="File or directory to analyze")
    pref_group = parser.add_mutually_exclusive_group()
    pref_group.add_argument(
        "--prefer-absolute-imports",
        dest="prefer_absolute_imports",
        action="store_true",
        help="Prefer absolute imports for cross-file extractions when possible (even same-dir in packages)",
    )
    pref_group.add_argument(
        "--no-prefer-absolute-imports",
        dest="prefer_absolute_imports",
        action="store_false",
        help="Prefer local/same-dir imports when possible",
    )
    parser.set_defaults(prefer_absolute_imports=None)

    pep_group = parser.add_mutually_exclusive_group()
    pep_group.add_argument(
        "--pep420",
        dest="pep420",
        action="store_true",
        help="Treat directories as namespace packages (PEP 420) when deriving module paths",
    )
    pep_group.add_argument(
        "--no-pep420",
        dest="pep420",
        action="store_false",
        help="Require __init__.py for packages when deriving module paths",
    )
    parser.set_defaults(pep420=None)

    args = parser.parse_args()

    target = args.target

    # Check if target exists
    if not os.path.exists(target):
        print(f"Error: '{target}' does not exist")
        sys.exit(1)

    # Determine if it's a file or directory
    is_file = os.path.isfile(target)
    is_dir = os.path.isdir(target)

    if not is_file and not is_dir:
        print(f"Error: '{target}' is neither a file nor a directory")
        sys.exit(1)

    # Create engine
    engine = UnificationRefactorEngine(
        max_parameters=5,
        min_lines=3,
        parameterize_constants=True,
        prefer_absolute_imports=args.prefer_absolute_imports,
        pep420_namespace_packages=args.pep420,
    )

    # Analyze based on type
    if is_file:
        if not target.endswith(".py"):
            print(f"Note: '{target}' is not a Python file (.py)")
            print()

        print(f"Analyzing file: {target}")
        all_proposals = engine.analyze_file(target)
    else:
        print(f"Analyzing directory: {target}")
        all_proposals = engine.analyze_directory(
            target, recursive=True, verbose=True, progress="tqdm"
        )

    print(f"\nFound {len(all_proposals)} refactoring opportunities")

    if not all_proposals:
        print("No duplicates found!")
        return

    # Filter overlapping proposals
    proposals = filter_overlapping_proposals(all_proposals)

    if len(proposals) < len(all_proposals):
        print(f"Filtered to {len(proposals)} non-overlapping proposals")
        print(f"(Removed {len(all_proposals) - len(proposals)} overlapping proposals)")

    print("\n" + "=" * 70)
    print("REFACTORING OPPORTUNITIES")
    print("=" * 70)

    for i, prop in enumerate(proposals[:10], 1):  # Show first 10
        print(f"\n{i}. {prop.description}")
        print(f"   Parameters: {prop.parameters_count}")

        # Show which files are affected
        files_affected = set()
        for item in prop.replacements:
            if len(item) == 3:
                files_affected.add(item[2])
            else:
                files_affected.add(prop.file_path)

        if len(files_affected) > 1:
            print(f"   Type: Cross-file ({len(files_affected)} files)")
            for f in sorted(files_affected):
                print(f"      - {f}")
        else:
            print(f"   Type: Same file ({prop.file_path})")

        # Show extracted function preview
        print("\n   Extracted function preview:")
        try:
            func_code = ast.unparse(prop.extracted_function)
            lines = func_code.split("\n")
            for line in lines[:8]:
                print(f"      {line}")
            if len(lines) > 8:
                print(f"      ... ({len(lines) - 8} more lines)")
        except ValueError as e:
            # Can happen with complex f-string transformations
            print(f"      (Preview unavailable: {e})")
            print(f"      Function name: {prop.extracted_function.name}")

    if len(proposals) > 10:
        print(f"\n... and {len(proposals) - 10} more proposals")

    print("\n" + "=" * 70)
    print("\nTo apply these refactorings, run:")
    if is_file:
        print(f"  python3 scripts/dry {target} <output> [--yes]")
    else:
        print(f"  python3 scripts/dry {target} <output_dir> [--yes]")
    print()


if __name__ == "__main__":
    main()
