import sys
import re
from typing import List, Dict, Tuple
from pathlib import Path

from pilot.job.impl.base_job import BaseJob


class SplitMethodBaseJob(BaseJob):
    """
    VB(.vb)ソースを行単位で解析し、メソッド（Sub/Function）ごとに別ファイルに分割保存するジョブ。
    """

    # メソッド開始行の判定用正規表現 (修飾子を考慮)
    METHOD_START_PATTERN = re.compile(
        r"^\s*(?:(?:Public|Private|Protected|Friend|Partial|Shared|Shadows|Async|Overrides|Overridable|NotOverridable|MustOverride|Overloads)\s+)*(Sub|Function)\s+([a-zA-Z0-9_]+)\b",
        re.IGNORECASE
    )

    # メソッド終了行の判定用正規表現
    METHOD_END_PATTERN = re.compile(
        r"^\s*End\s+(Sub|Function)\b",
        re.IGNORECASE
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 分割結果ファイルのパスリストを保持
        self.generated_files: List[Path] = []
        self.section_order_list: List[str] = []

    def run(self):
        """
        ジョブ実行メイン処理
        """
        try:
            src_path = Path(self.file_path)

            # 1. 読み込み
            if not src_path.is_file():
                print(f"Error: Source file not found -> {src_path}", file=sys.stderr)
                return

            encoding = 'utf-8'  # 必要に応じてBOM付きUTF-8などに変更
            try:
                lines = src_path.read_text(encoding=encoding).splitlines(keepends=True)
            except UnicodeDecodeError:
                # shift_jisなどの場合
                lines = src_path.read_text(encoding='shift_jis').splitlines(keepends=True)

            # 2. 分割ロジック実行
            blocks, section_order_list = self._split_methods(lines)

            if blocks:
                # 3. 出力先ディレクトリ (元のファイル名と同じディレクトリ)
                out_dir = src_path.parent

                # 4. 書き出し
                self.generated_files = self._write_blocks(blocks, out_dir, src_path)

                self.section_order_list = section_order_list
            else:
                print("Warning: No blocks detected.", file=sys.stderr)

        except Exception as e:
            # エラーハンドリング
            if hasattr(self, 'logger'):
                self.logger.error(f"{__name__} 異常終了. {e}")
            else:
                print(f"{__name__} 異常終了. {e}", file=sys.stderr)
            return

        # 親クラスのrunを実行
        super().run()

    def _split_methods(self, lines: List[str]) -> Tuple[Dict[str, List[str]], List[str]]:
        """
        メソッド単位でコードを分割する
        """
        blocks: Dict[str, List[str]] = {}
        section_order_list: List[str] = []

        current_method = None
        current_lines = []
        inside_method = False
        method_type = None  # 'Sub' または 'Function'

        for line in lines:
            if not inside_method:
                # メソッド外の場合は開始行を探す
                match = self.METHOD_START_PATTERN.search(line)
                if match:
                    method_type = match.group(1).title()  # 'Sub' または 'Function'
                    current_method = match.group(2)
                    inside_method = True
                    current_lines = [line]
            else:
                # メソッド内の場合は行を追加しつつ、終了行を探す
                current_lines.append(line)
                end_match = self.METHOD_END_PATTERN.search(line)
                if end_match and end_match.group(1).title() == method_type:
                    # メソッド終了
                    if current_method not in section_order_list:
                        section_order_list.append(current_method)
                    blocks[current_method] = current_lines.copy()

                    inside_method = False
                    current_method = None
                    current_lines = []

        return blocks, section_order_list

    def _write_blocks(self, blocks: Dict[str, List[str]], out_dir: Path, src_path: Path) -> List[Path]:
        """
        各ブロックを個別のファイルとして書き出す。
        同名メソッドのオーバーロード等があった場合、連番を付与する。
        """
        out_dir.mkdir(parents=True, exist_ok=True)
        from collections import defaultdict
        counter = defaultdict(int)
        created_files = []

        for title, lines in blocks.items():
            if not lines:
                continue

            counter[title] += 1
            idx_suffix = f"_{counter[title]}" if counter[title] > 1 else ""
            filename = out_dir / f"{src_path.name}.{title}{idx_suffix}"

            with filename.open("w", encoding="utf-8", newline="\n") as fp:
                fp.writelines(lines)

            created_files.append(filename)

        return created_files
