"""
Universal Code Migrator
Converts source code between any programming languages using Claude API.

Architecture:
  - Model:      src/gui_model.py     (ConversionConfig, ConversionState)
  - View:       src/gui_view.py      (MigratorView - widget creation/layout)
  - Controller: src/gui_controller.py (MigrationController - event handling/logic)
  - Engine:     src/migrator.py      (Migrator - Claude API translation + retry + resume)
  - Sanitizer:  src/sanitizer.py     (Markdown/NL stripping)
  - Resume:     src/resume_state.py  (Hash-based resume state)
  - Ecosystem:  src/ecosystem.py     (Project file mapping + priority ordering)
  - Languages:  src/languages.py     (113 language definitions + custom-language support)
"""
import os
import sys
import argparse

# Support running as script or frozen exe
if getattr(sys, 'frozen', False):
    BASE_DIR = os.path.dirname(sys.executable)
else:
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))

sys.path.insert(0, BASE_DIR)

from src.languages import LANGUAGE_NAMES, get_extensions

# 注: src.migrator は anthropic SDK に依存するため、実変換が必要なときだけ
# 遅延 import する。--list-languages や --demo のオフライン部分は SDK 不要。


def run_cli(args):
    """Execute migration in CLI mode."""
    print("=" * 60)
    print("Universal Code Migrator - CLI Mode")
    print("=" * 60)

    input_dir = args.input.strip()
    output_dir = args.output.strip()
    source_lang = args.source
    target_lang = args.target

    if not os.path.isdir(input_dir):
        print(f"[ERROR] Input directory does not exist: {input_dir}")
        sys.exit(1)

    if source_lang == target_lang:
        print("[ERROR] Source and target languages must be different.")
        sys.exit(1)

    # 一覧に無い言語も「カスタム言語」として受け付ける（LLM はどんな言語でも
    # 変換を試みられる）。ただし元言語のファイル走査には拡張子が必要なため、
    # 未知の元言語では --ext を要求する。
    if source_lang not in LANGUAGE_NAMES:
        print(f"[WARN] '{source_lang}' は組み込み一覧にありません。カスタム元言語として扱います。")
    if target_lang not in LANGUAGE_NAMES:
        print(f"[WARN] '{target_lang}' は組み込み一覧にありません。カスタム変換先として扱います。")

    # 元言語の拡張子: --ext 優先、無ければ組み込み定義
    if args.ext:
        src_exts = [e if e.startswith(".") else "." + e for e in args.ext.split(",") if e.strip()]
    else:
        src_exts = get_extensions(source_lang)
    if not src_exts:
        print(f"[ERROR] '{source_lang}' の拡張子が不明です。--ext で指定してください（例: --ext .abc,.xyz）。")
        sys.exit(1)

    # 変換先の拡張子: --out-ext 優先、無ければ組み込み定義、最後は .txt
    if args.out_ext:
        tgt_ext = args.out_ext if args.out_ext.startswith(".") else "." + args.out_ext
    else:
        tgt_exts = get_extensions(target_lang)
        tgt_ext = tgt_exts[0] if tgt_exts else ".txt"

    print(f"Source:     {source_lang} ({', '.join(src_exts)})")
    print(f"Target:     {target_lang} ({tgt_ext})")
    print(f"Input:      {input_dir}")
    print(f"Output:     {output_dir}")
    print(f"Model:      {args.model}")
    print(f"Resume:     {'ON' if not args.no_resume else 'OFF'}")
    print(f"Context:    {'ON' if not args.no_context else 'OFF'}")
    print(f"Ecosystem:  {'ON' if not args.no_ecosystem else 'OFF'}")

    # 実変換でのみ必要な SDK 依存を遅延 import する
    from src.migrator import Migrator

    migrator = Migrator(
        api_key=args.api_key or "",
        model=args.model,
    )

    def on_log(msg: str, tag: str = "info"):
        prefix = {"error": "[ERROR]", "warning": "[WARN]", "success": "[OK]"}.get(tag, "")
        if prefix:
            print(f"{prefix} {msg}")
        else:
            print(msg)

    results = migrator.migrate_folder(
        input_dir=input_dir,
        output_dir=output_dir,
        source_lang=source_lang,
        target_lang=target_lang,
        source_extensions=src_exts,
        target_extension=tgt_ext,
        extra_instructions=args.extra or "",
        on_progress=lambda f, i, n: print(f"[{i}/{n}] {f}"),
        on_log=on_log,
        encoding=args.encoding,
        enable_resume=not args.no_resume,
        enable_context=not args.no_context,
        enable_ecosystem=not args.no_ecosystem,
    )

    print(f"\n{'=' * 60}")
    print("Migration Complete")
    print(f"{'=' * 60}")
    print(f"  Success:  {results['success']} file(s)")
    if results['errors'] > 0:
        print(f"  Errors:   {results['errors']} file(s)")
    if results['skipped'] > 0:
        print(f"  Skipped:  {results['skipped']} file(s)")
    if results['resumed'] > 0:
        print(f"  Resumed:  {results['resumed']} file(s) (already converted)")

    if results['errors'] > 0:
        sys.exit(1)


def run_gui():
    """Launch GUI application."""
    import tkinter as tk
    from src.i18n import I18n
    from src.gui_view import MigratorView
    from src.gui_controller import MigrationController

    root = tk.Tk()

    icon_path = os.path.join(BASE_DIR, "icon.ico")
    if os.path.exists(icon_path):
        root.iconbitmap(icon_path)

    i18n = I18n("en")
    view = MigratorView(root, i18n)
    # root に束縛して GC を防ぐ（イベント配線を保持するため）
    root._controller = MigrationController(view, i18n)

    root.mainloop()


def list_languages():
    """Print all supported languages."""
    print("Supported languages:")
    print("-" * 40)
    for name in LANGUAGE_NAMES:
        exts = get_extensions(name)
        print(f"  {name:25s} {', '.join(exts)}")
    print(f"\nTotal: {len(LANGUAGE_NAMES)} languages")


def run_demo(args):
    """同梱サンプルで即動作デモ（叩けば即結果）。

    実変換は Anthropic API キーが必要だが、本デモはキーが無くても
    オフラインで「言語プラン・エコシステム対応・出力サニタイズ」の
    動きをすぐ確認できる。キーがある場合は実変換まで実行する。
    """
    from src.sanitizer import sanitize_code_output
    from src.ecosystem import get_ecosystem_mappings, sort_files_by_priority

    source_lang = args.source or "Python"
    target_lang = args.target or "Rust"
    sample = os.path.join(BASE_DIR, "samples", "hello.py")

    print("=" * 60)
    print("  Universal Code Migrator - DEMO MODE")
    print("=" * 60)
    print(f"  サンプル入力 : {sample}")
    print(f"  変換プラン   : {source_lang} ({', '.join(get_extensions(source_lang))})"
          f" -> {target_lang} ({', '.join(get_extensions(target_lang))})")

    # 1) エコシステム対応（プロジェクトファイルの対応付け）
    mappings = get_ecosystem_mappings(source_lang, target_lang)
    if mappings:
        print("\n[エコシステム対応] 設定ファイル等の対応付け例:")
        for src_name, tgt_name in list(mappings.items())[:6]:
            print(f"    {src_name}  ->  {tgt_name}")

    # 2) 優先順位付け（文脈に使う重要ファイルの並べ替え）
    files = ["src/main.py", "README.md", "requirements.txt", "src/util.py", "tests/test_x.py"]
    print("\n[優先順位付け] 文脈注入の順序:")
    for f in sort_files_by_priority(files):
        print(f"    {f}")

    # 3) 出力サニタイズ（LLM の余計な前置き/コードフェンスを除去）
    raw_llm_output = (
        "Here is the converted Rust code:\n"
        "```rust\n"
        "fn main() {\n"
        "    println!(\"Hello\");\n"
        "}\n"
        "```\n"
        "Key changes: replaced print with println!."
    )
    print("\n[出力サニタイズ] LLM 生出力 -> 純粋なコード:")
    print("  --- before ---")
    for line in raw_llm_output.splitlines():
        print(f"  | {line}")
    print("  --- after ---")
    for line in sanitize_code_output(raw_llm_output, target_lang).splitlines():
        print(f"  | {line}")

    # 4) API キーがあれば実変換まで実行
    api_key = args.api_key or os.environ.get("ANTHROPIC_API_KEY", "")
    if api_key:
        print("\n[実変換] API キーを検出。サンプルを実際に変換します...")
        out_dir = os.path.join(BASE_DIR, "demo_output")
        demo_args = argparse.Namespace(**vars(args))
        demo_args.input = os.path.join(BASE_DIR, "samples")
        demo_args.output = out_dir
        demo_args.source = source_lang
        demo_args.target = target_lang
        demo_args.api_key = api_key
        run_cli(demo_args)
    else:
        print("\nヒント: ANTHROPIC_API_KEY を設定すると、上記サンプルを実際に")
        print("       Rust へ変換できます（例: $env:ANTHROPIC_API_KEY=\"...\"）。")
        print("       python main.py -i ./samples -o ./out -s Python -t Rust")


def main():
    parser = argparse.ArgumentParser(
        description="Universal Code Migrator - Convert code between any programming languages"
    )
    parser.add_argument("-i", "--input", help="Input folder (CLI mode)")
    parser.add_argument("-o", "--output", help="Output folder (CLI mode)")
    parser.add_argument("-s", "--source", help="Source language name (e.g. 'Python', 'Java')")
    parser.add_argument("-t", "--target", help="Target language name (e.g. 'Rust', 'Go')")
    parser.add_argument("-k", "--api-key", default="", help="Anthropic API key (or set ANTHROPIC_API_KEY env)")
    parser.add_argument("-m", "--model", default="claude-sonnet-4-20250514", help="Model to use")
    parser.add_argument("-e", "--encoding", default="utf-8", help="Source file encoding (default: utf-8)")
    parser.add_argument("--ext", default="", help="カスタム元言語の拡張子（カンマ区切り、例: .abc,.xyz）。一覧外の言語を使うとき指定")
    parser.add_argument("--out-ext", default="", help="変換先ファイルの拡張子（例: .abc）。一覧外の変換先を使うとき指定")
    parser.add_argument("--extra", default="", help="Extra instructions for the migration")
    parser.add_argument("--no-resume", action="store_true", help="Disable resume (re-convert all files)")
    parser.add_argument("--no-context", action="store_true", help="Disable context injection from priority files")
    parser.add_argument("--no-ecosystem", action="store_true", help="Disable ecosystem file conversion")
    parser.add_argument("--list-languages", action="store_true", help="List all supported languages")
    parser.add_argument("--demo", action="store_true",
                        help="同梱サンプルで即動作デモ（APIキー不要のオフライン実演。キーがあれば実変換も実行）")

    args = parser.parse_args()

    if args.list_languages:
        list_languages()
        return

    if args.demo:
        run_demo(args)
        return

    if args.input and args.output and args.source and args.target:
        run_cli(args)
    elif any([args.input, args.output, args.source, args.target]):
        print("[ERROR] CLI mode requires all of: -i, -o, -s, -t")
        print("  Example: python main.py -i ./cobol_src -o ./java_out -s COBOL -t Java")
        sys.exit(1)
    else:
        run_gui()


if __name__ == "__main__":
    main()
