# ==============================================================================
# 統合版FAX自動処理プログラム
#
# このプログラムは以下の3つの処理を連続して実行します。
# 1. FAXフォルダ内のPDFの向きを自動補正し、「作業用」フォルダに出力します。(旧fax1.py)
# 2. 「作業用」フォルダ内のPDFからFAX送信元を特定し、ファイル名をリネームします。(旧fax2.py)
# 3. リネームされたPDFを「本日日付/送信元名」のフォルダに整理します。(旧fax3.py)
# ==============================================================================

# --- ライブラリのインポート ---
import os
import sys
import shutil
import subprocess
from datetime import datetime
from pathlib import Path

# 処理に必要なライブラリをインポートします
try:
    import pytesseract
    from pdf2image import convert_from_path
    import pikepdf
except ImportError as e:
    print(f"エラー: 必要なライブラリがインストールされていません: {e.name}")
    print(f"コマンドプロンプトで pip install {e.name} を実行してください。")
    input("\n何かキーを押すと終了します...")
    sys.exit(1)


# --- 全体設定 ---
# このセクションでプログラムの動作に必要な設定をすべて行います。
# ご自身の環境に合わせてパスなどを編集してください。
# ------------------------------------------------------------------------------

# (ステップ1: 向き補正用)
# 1. Tesseract-OCRの実行ファイルのパス
#    例: r'C:\Program Files\Tesseract-OCR\tesseract.exe'
TESSERACT_CMD_PATH = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

# 2. Popplerのbinフォルダのパス
#    例: r'C:\path\to\poppler\Library\bin'
POPPLER_PATH = r'C:\Program Files\poppler-25.07.0\Library\bin'

# (ステップ1, 2, 3で共通)
# 元のFAXデータが入っているフォルダ
FAX_SOURCE_DIR = Path("FAX")
# 中間ファイルを保存する作業用フォルダ
WORK_DIR = Path("作業用")

# (ステップ2: リネーム用)
# 1. FAX発信元が記載されたテキストファイルの名前
FAX_LIST_FILE = Path("FAX発信元リスト.txt")
# 2. 使用するGemini CLIのコマンド名 (.ps1 スクリプトのフルパス)
GEMINI_COMMAND = r"C:\Users\minak\AppData\Roaming\npm\gemini.ps1"

# ------------------------------------------------------------------------------


# ==============================================================================
# --- ステップ1: PDFの向き自動補正 (旧fax1.pyの機能) ---
# ==============================================================================
def step1_correct_pdf_orientation():
    """
    FAXフォルダ内のPDFファイルの向きを自動補正し、作業用フォルダに出力します。
    """
    print("--- [ステップ1/3] PDFの向き自動補正を開始します ---")

    # --- 依存関係のチェック ---
    is_ok = True
    if not os.path.exists(TESSERACT_CMD_PATH):
        print(f"エラー: Tesseract-OCRが見つかりません。パス: {TESSERACT_CMD_PATH}")
        is_ok = False
    if not POPPLER_PATH or not os.path.isdir(POPPLER_PATH):
        print(f"エラー: Popplerのbinフォルダのパスが正しくありません。パス: {POPPLER_PATH}")
        is_ok = False
    tessdata_dir = os.path.join(os.path.dirname(TESSERACT_CMD_PATH), 'tessdata')
    if not os.path.isdir(tessdata_dir) or not os.path.exists(os.path.join(tessdata_dir, 'osd.traineddata')):
        print(f"エラー: Tesseractの学習データ 'tessdata/osd.traineddata' が見つかりません。")
        is_ok = False
    if not is_ok:
        print("設定を確認してください。")
        return False # エラーがあればFalseを返して処理を中断

    pytesseract.pytesseract.tesseract_cmd = TESSERACT_CMD_PATH

    # --- フォルダの準備 ---
    WORK_DIR.mkdir(exist_ok=True)
    if not FAX_SOURCE_DIR.is_dir():
        print(f"エラー: 「{FAX_SOURCE_DIR}」フォルダが見つかりません。")
        return False

    # --- PDFファイルの処理 ---
    pdf_files = sorted(
        [f for f in FAX_SOURCE_DIR.glob("*.pdf")],
        key=lambda f: f.stat().st_ctime
    )
    if not pdf_files:
        print(f"「{FAX_SOURCE_DIR}」フォルダに処理対象のPDFファイルがありません。")
        return True # 処理対象なしはエラーではない

    print(f"処理対象のファイル: {len(pdf_files)}件")
    print("-" * 40)

    for pdf_path in pdf_files:
        output_path = WORK_DIR / pdf_path.name
        print(f"処理中: {pdf_path.name}")
        try:
            with pikepdf.open(pdf_path, allow_overwriting_input=True) as original_pdf:
                with pikepdf.Pdf.new() as new_pdf:
                    images = convert_from_path(pdf_path, poppler_path=POPPLER_PATH)
                    for i, page_image in enumerate(images):
                        print(f"  - {i + 1}ページ目の向きを判定中...")
                        try:
                            osd = pytesseract.image_to_osd(page_image, lang='osd', output_type=pytesseract.Output.DICT)
                            rotation = osd.get('rotate', 0)
                            page = original_pdf.pages[i]
                            if rotation != 0:
                                print(f"    -> {rotation}度回転します。")
                                page.rotate(rotation, relative=True)
                            else:
                                print(f"    -> 向きは正常です。")
                            new_pdf.pages.append(page)
                        except pytesseract.TesseractError as e:
                            print(f"  エラー: {i + 1}ページ目の向きを判定できませんでした。ページをそのままコピーします。")
                            new_pdf.pages.append(original_pdf.pages[i])
                    new_pdf.save(output_path)
                    print(f"保存しました: {output_path}")
        except Exception as e:
            print(f"エラー: {pdf_path.name} の処理中に予期せぬ問題が発生しました。 詳細: {e}")
        print("-" * 40)
    
    print("--- [ステップ1/3] PDFの向き自動補正が完了しました ---\n")
    return True

# ==============================================================================
# --- ステップ2: GeminiによるPDFリネーム (旧fax2.pyの機能) ---
# ==============================================================================
def get_fax_sender_from_gemini(pdf_path, fax_list_content):
    """Gemini CLIを呼び出してPDFからFAX送信元を取得します。"""
    prompt = f"""
あなたは高性能なAIアシスタントです。
添付されたPDFファイルはFAXの受信データです。内容を正確に読み取ってください。
そして、このFAXの送信元企業名を特定し、後述する「送信元候補リスト」の中から最も合致するものを一つだけ選び、その企業名のみを回答してください。
余計な説明や前置きは一切含めず、企業名だけを出力してください。
--- 送信元候補リスト ---
{fax_list_content}
--------------------
"""
    command = ["powershell", "-File", GEMINI_COMMAND, "--yolo", prompt, str(pdf_path)]
    try:
        print(f"  > Geminiに問い合わせ中: {pdf_path.name}")
        result = subprocess.run(command, capture_output=True, text=True, check=True, encoding='utf-8')
        sender_name = result.stdout.strip().splitlines()[0]
        return sender_name
    except FileNotFoundError:
        print(f"  > エラー: コマンド 'powershell' が見つかりません。", file=sys.stderr)
        return None
    except subprocess.CalledProcessError as e:
        print(f"  > エラー: Gemini CLIの実行中にエラーが発生しました。詳細: {e.stderr}", file=sys.stderr)
        return None
    except Exception as e:
        print(f"  > エラー: 予期せぬエラーが発生しました - {e}", file=sys.stderr)
        return None

def step2_rename_pdfs_with_sender():
    """
    作業用フォルダ内のPDFをGeminiで解析し、送信元をファイル名に追記します。
    """
    print("--- [ステップ2/3] Geminiによるファイル名のリネームを開始します ---")

    # --- 前提条件のチェック ---
    if not WORK_DIR.is_dir():
        print(f"エラー: '{WORK_DIR}' フォルダが見つかりません。ステップ1が正常に完了したか確認してください。")
        return False
    if not FAX_LIST_FILE.is_file():
        print(f"エラー: '{FAX_LIST_FILE}' が見つかりません。")
        return False

    # --- FAX発信元リストの読み込み ---
    try:
        with open(FAX_LIST_FILE, "r", encoding='utf-8') as f:
            fax_list_content = f.read()
            fax_senders = [line.strip() for line in fax_list_content.strip().splitlines()]
        print(f"参照ファイル '{FAX_LIST_FILE}' を読み込みました。")
    except Exception as e:
        print(f"エラー: '{FAX_LIST_FILE}' の読み込みに失敗しました: {e}")
        return False

    # --- PDFファイルの処理 ---
    pdf_files = sorted([p for p in WORK_DIR.glob("*.pdf")], key=lambda p: p.stat().st_ctime)
    if not pdf_files:
        print(f"'{WORK_DIR}' フォルダに処理対象のPDFファイルが見つかりませんでした。")
        return True

    print(f"{len(pdf_files)}個のPDFファイルを処理します。\n")
    success_count, fail_count = 0, 0
    for i, pdf_path in enumerate(pdf_files, 1):
        print(f"[{i}/{len(pdf_files)}] 処理中ファイル: {pdf_path.name}")
        sender_name = get_fax_sender_from_gemini(pdf_path, fax_list_content)
        if sender_name and sender_name in fax_senders:
            new_stem = f"{pdf_path.stem}_{sender_name}"
            new_path = pdf_path.with_stem(new_stem)
            try:
                pdf_path.rename(new_path)
                print(f"  > 成功: ファイル名を '{new_path.name}' に変更しました。\n")
                success_count += 1
            except Exception as e:
                print(f"  > エラー: ファイル名の変更に失敗しました - {e}\n", file=sys.stderr)
                fail_count += 1
        else:
            if not sender_name:
                print(f"  > 失敗: Geminiから送信元名を取得できませんでした。\n")
            else:
                print(f"  > 失敗: 取得した送信元 '{sender_name}' がリストに存在しません。\n")
            fail_count += 1

    print("--- 全てのファイルのリネーム処理が完了しました ---")
    print(f"成功: {success_count}件, 失敗: {fail_count}件")
    print("--- [ステップ2/3] ファイル名のリネームが完了しました ---\n")
    return True

# ==============================================================================
# --- ステップ3: 日付と送信元によるフォルダ整理 (旧fax3.pyの機能) ---
# ==============================================================================
def step3_organize_pdfs_into_folders():
    """
    作業用フォルダ内のPDFを、ファイル名に基づいて「本日日付/名称」のフォルダに整理します。
    """
    print("--- [ステップ3/3] フォルダ整理を開始します ---")

    # --- フォルダの準備 ---
    today_str = datetime.now().strftime('%Y年%m月%d日')
    date_folder_path = Path.cwd() / today_str
    date_folder_path.mkdir(exist_ok=True)
    print(f"作成/確認したフォルダ: {date_folder_path}")

    if not WORK_DIR.is_dir():
        print(f"エラー: '{WORK_DIR}' フォルダが見つかりません。")
        return False

    # --- ファイルの移動処理 ---
    pdf_files = list(WORK_DIR.glob("*.pdf"))
    if not pdf_files:
        print(f"'{WORK_DIR}' に整理対象のファイルがありません。")
        return True

    for source_path in pdf_files:
        try:
            parts = source_path.name.split('_', 1)
            if len(parts) > 1:
                name = parts[1].replace('.pdf', '')
                name_folder_path = date_folder_path / name
                name_folder_path.mkdir(exist_ok=True)
                destination_path = name_folder_path / source_path.name
                shutil.move(source_path, destination_path)
                print(f"移動しました: {source_path.name} -> {name_folder_path}")
            else:
                print(f"スキップしました（名前に'_'が含まれていません）: {source_path.name}")
        except Exception as e:
            print(f"エラー: {source_path.name} の処理中に問題が発生しました。 - {e}")

    print("\nすべてのファイルの整理が完了しました。")
    print("--- [ステップ3/3] フォルダ整理が完了しました ---\n")
    return True

# ==============================================================================
# --- メイン処理 ---
# ==============================================================================
def main():
    """
    すべてのステップを順番に実行するメイン関数
    """
    print("==============================================")
    print(" FAX自動処理プログラムを開始します")
    print("==============================================")

    # 各ステップを実行し、失敗した場合はそこで処理を中断する
    if not step1_correct_pdf_orientation():
        print("ステップ1でエラーが発生したため、処理を中断しました。")
    elif not step2_rename_pdfs_with_sender():
        print("ステップ2でエラーが発生したため、処理を中断しました。")
    elif not step3_organize_pdfs_into_folders():
        print("ステップ3でエラーが発生したため、処理を中断しました。")
    else:
        print("==============================================")
        print(" すべての処理が正常に完了しました。")
        print("==============================================")

    input("何かキーを押すとプログラムを終了します...")

if __name__ == '__main__':
    main()