#!/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

# 既存のライブラリ（環境に合わせてパスを通してください）
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 が見つかりません。パスを確認してください。", file=sys.stderr)
    sys.exit(1)

#=========================================================
# INI Reading Logic (make_textbook5.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"

    if infile is None:
        for path in [os.getcwd(), script_dir]:
            candidate = os.path.join(path, default_ini)
            if os.path.isfile(candidate): return candidate
        return None
    
    if not os.path.isfile(infile):
        candidate = os.path.join(script_dir, infile)
        if os.path.isfile(candidate): return candidate
        return None
    return infile

def read_ini(inifile=None):
    path = search_file(inifile)
    if path is None:
        raise FileNotFoundError("INIファイルが見つかりませんでした")

    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

            # 複数行値の終了判定（stripで判定）
            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

            # key=val の解析
            if '=' in line:
                key, val = map(str.strip, line.split('=', 1))
                val = val.strip()

                # 複数行値の開始判定（空文字でも対応）
                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):
            var_name = match.group(1)
            return variables.get(var_name, match.group(0))
        result[key] = re.sub(r"\$(\w+)\b", expand_var, val)

    return result

#=========================================================
# Language Dictionary
#=========================================================
language_dict = {
    ".py": "python", ".pl": "perl", ".pm": "perl", ".c" : "C",
    ".cpp": "C++", ".pas": "pascal", ".f"  : "fortran", ".js" : "Javascript",
    ".java": "Java", ".go": "Go", ".sh": "bash script", ".html": "HTML"
}

def get_program_type(path):
    base = os.path.basename(path)
    name, ext = os.path.splitext(base)
    if ext == ".pm" or base.startswith("tk"): return 'lib'
    return 'main'

def initialize():
    ini_path = os.path.splitext(sys.argv[0])[0] + ".ini"

    parser = argparse.ArgumentParser(description="プログラムコードをAIでドキュメント化するツール")
    parser.add_argument("pattern", help="対象ファイルのワイルドカード（例: '*.py'）")
    parser.add_argument("output", nargs="?", help="出力名（単一ファイル時のみ）")
    parser.add_argument("--inifile", default=ini_path, help="プロンプト設定ファイル")
    parser.add_argument("--api", choices=["openai", "openai5", "google", "gemini"], default='google')
    parser.add_argument("-t", "--program_type", choices=["", "main", "lib"], default="")
    parser.add_argument("-u", "--update", type=int, default=0)
    parser.add_argument("-w", "--overwrite", type=int, default=0)
    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(args):
    # AI設定の読み込み
    read_ai_config("ai.env")
    
    # プロンプトINIの読み込み
    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: sys.exit(1)

    outputs = [args.output] if args.output else [os.path.splitext(f)[0] + "_usage.md" for f in files]

    for inp, out in zip(files, outputs):
        if os.path.exists(out) and not args.overwrite and (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:
            code = Path(inp).read_text(encoding="shift-jis")

        ext = os.path.splitext(inp)[1]
        lang = language_dict.get(ext, "text")
        p_type = args.program_type or get_program_type(inp)

        # プロンプト構築
        tpl_key = f"PROMPT_{p_type.upper()}"
        template = ini_data.get(tpl_key, ini_data.get("PROMPT_MAIN"))
        role = ini_data.get("SYSTEM_ROLE", "Assistant")
        
        prompt = template.replace("{{script_name}}", inp).replace("{{code}}", code).replace("{{language}}", lang)

        # AI呼び出し
        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:
            Path(out).write_text(doc, encoding="utf-8")
            print(f"Done: {out}")
        time.sleep(1)

    if args.pause:
        input("\nPress ENTER to terminate>>\n")

if __name__ == "__main__":
    print()
    print(f"=== {sys.argv[0]} ===")
    parser = initialize()
    args = read_args(parser)

    try:
        main(args)
    except Exception:
        print("\n" + "!"*60)
        print(" 予期せぬ致命的なエラーが発生しました。")
        traceback.print_exc()
        print("!"*60)
        sys.exit(1)
            