#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import argparse
import glob
import time
import re
import traceback
from pathlib import Path

# AI連携用ライブラリのインポート
try:
    from tkai_lib import read_ai_config
    from tkai_lib import query_openai4, query_openai5, query_google
    from tkai_lib import extract_openai5_text
except ImportError:
    print("Error: tkai_lib.py が見つかりません。ライブラリのパスを確認してください。", file=sys.stderr)
    sys.exit(1)

# =========================================================
# INI検索・読み込みロジック (explain_program5.py の設計を継承)
# =========================================================
def search_file(infile=None):
    script_path = os.path.abspath(sys.argv[0])
    script_dir = os.path.dirname(script_path)
    script_name = os.path.splitext(os.path.basename(script_path))[0]
    default_ini = f"{script_name}.ini"

    search_target = infile if infile else default_ini

    candidate1 = os.path.join(os.getcwd(), search_target)
    if os.path.isfile(candidate1):
        return candidate1
    
    candidate2 = os.path.join(script_dir, search_target)
    if os.path.isfile(candidate2):
        return candidate2
        
    return None

def read_ini(inifile=None):
    path = search_file(inifile)
    if path is None:
        raise FileNotFoundError(f"INIファイルが見つかりませんでした: {inifile}")

    result = {}
    variables = {}
    current_key = None
    multiline_val = []
    multiline_delim = None

    with open(path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.rstrip()
            if not line or line.startswith('#') or line.startswith(';'):
                continue

            if multiline_delim:
                if line.strip() == multiline_delim:
                    val = '\n'.join(multiline_val)
                    result[current_key] = val
                    variables[current_key] = val
                    current_key = None
                    multiline_val = []
                    multiline_delim = None
                else:
                    multiline_val.append(line)
                continue

            if '=' in line:
                key, val = map(str.strip, line.split('=', 1))
                if (val == '"""' or val == "'''" or
                   (val.startswith('"""') and not val.endswith('"""')) or
                   (val.startswith("'''") and not val.endswith("'''"))):
                    multiline_delim = val[:3]
                    content = val[3:]
                    multiline_val = [content] if content else []
                    current_key = key
                    continue
                
                if (val.startswith('"""') and val.endswith('"""')) or \
                   (val.startswith("'''") and val.endswith("'''")):
                    val = val[3:-3]

                result[key] = val
                variables[key] = val

    for key, val in result.items():
        def expand_var(match):
            return variables.get(match.group(1), match.group(0))
        result[key] = re.sub(r"\$(\w+)\b", expand_var, val)

    return result

# =========================================================
# メイン処理
# =========================================================
def initialize():
    default_ini_name = os.path.splitext(os.path.basename(sys.argv[0]))[0] + ".ini"

    parser = argparse.ArgumentParser(description="PythonコードにSphinx形式のDocstringを自動追加するツール")
    # explain_program5.py に合わせた引数構成
    parser.add_argument("pattern", help="対象ファイルのワイルドカード（例: '*.py'）")
    parser.add_argument("output", nargs="?", help="出力名（単一ファイル時のみ）")
    parser.add_argument("--inifile", default=default_ini_name, help="プロンプト設定ファイルパス")
    parser.add_argument("--api", choices=["openai", "openai5", "google", "gemini"], default='google')
    parser.add_argument("-u", "--update", type=int, default=0, help="1の場合、ソースが新しい場合のみ更新")
    parser.add_argument("-w", "--overwrite", type=int, default=0, help="1の場合、既存ファイルを上書き")
    parser.add_argument("-p", "--pause", type=int, default=1)
    return parser

def read_args(parser):
    args = parser.parse_args()
    print("Args:")
    print(f"  {args.pattern=}")
    print(f"  {args.output=}")
    print(f"  {args.inifile=}")
    print(f"  {args.api=}")
    print(f"  {args.update=}")
    print(f"  {args.overwrite=}")
    print(f"  {args.pause=}")
    return args

def main():
    print()
    print(f"=== {sys.argv[0]} ===")

    parser = initialize()
    args = read_args(parser)

    read_ai_config("ai.env")
    
    try:
        ini_data = read_ini(args.inifile)
        print(f"Loaded INI: {search_file(args.inifile)}")
    except Exception as e:
        print(f"Error loading INI: {e}")
        sys.exit(1)

    # ワイルドカード展開
    files = glob.glob(args.pattern)
    if not files:
        print(f"No files matched pattern: {args.pattern}")
        sys.exit(1)

    # 出力ファイル名のリスト作成
    if args.output and len(files) == 1:
        outputs = [args.output]
    else:
        outputs = [os.path.splitext(f)[0] + "_docstring.py" for f in files]

    for inp, out in zip(files, outputs):
        # 更新・上書きチェックロジック
        if os.path.exists(out) and not args.overwrite:
            # updateモードかつ、出力ファイルの方が新しい場合はスキップ
            if not args.update or os.path.getmtime(out) >= os.path.getmtime(inp):
                print(f"Skip: {out}")
                continue

        print(f"Processing: {inp} -> {out}")
        
        try:
            code = Path(inp).read_text(encoding="utf-8")
        except:
            try:
                code = Path(inp).read_text(encoding="shift-jis")
            except Exception as e:
                print(f"Error reading {inp}: {e}")
                continue

        base_name = os.path.splitext(os.path.basename(inp))[0]
        template = ini_data.get("PROMPT_MAIN", "")
        role = ini_data.get("SYSTEM_ROLE", "Assistant")
        
        prompt = template.replace("{{script_name}}", inp)\
                         .replace("{{code}}", code)\
                         .replace("{{base_name}}", base_name)

        try:
            if args.api == "openai5":
                res = query_openai5(prompt, os.getenv("openai_model5"), instructions=role)
                doc = extract_openai5_text(res)
            elif args.api == "openai":
                res = query_openai4(prompt, os.getenv("openai_model"), role=role)
                doc = res.choices[0].message.content
            else:
                res = query_google(prompt, os.getenv("gemini_model"), role=role)
                doc = res.text if res else None

            if doc:
                # Markdownブロックの除去
                doc = doc.strip()
                if doc.startswith("```"):
                    doc = re.sub(r'^```[a-zA-Z]*\n', '', doc)
                    doc = re.sub(r'\n```$', '', doc)

                Path(out).write_text(doc, encoding="utf-8")
                print(f"Done: {out}")
            else:
                print(f"Error: No response from AI for {inp}")

        except Exception:
            print(f"\n!!! Error during AI processing for {inp} !!!")
            traceback.print_exc()
        
        time.sleep(1) # API連続呼び出しの負荷軽減

    if args.pause:
        input("\nPress ENTER to terminate>>\n")
    
if __name__ == "__main__":
    main()