# -*- coding: utf-8 -*-

# ■■■ プログラム概要 ■■■
# このプログラムは、Excelファイル「customer.xlsx」から顧客データを読み取り、
# 指定された画面上の座標に自動で転記・登録するGUI自動化スクリプトです。
#
# 【信頼性向上版】
# データ入力後に、正しく入力されたかを自動で確認し、失敗した場合は
# 3回まで再試行（リトライ）する機能を搭載しています。

# ■■■ 事前準備 ■■■
# 1. 必要なライブラリをインストールしてください。
#    ターミナルやコマンドプロモプトで以下のコマンドを実行します。
#    pip install openpyxl pyautogui pyperclip

# 2. このスクリプトと同じフォルダに「customer.xlsx」を配置してください。

# 3. 実行前に、Excelファイル「customer.xlsx」は必ず閉じておいてください。

# ■■■ 緊急停止の方法 ■■■
# 処理を途中で緊急停止したい場合は、マウスカーソルを画面の【左上隅】に
# 素早く移動させてください。pyautoguiのフェールセーフ機能により、
# プログラムが強制的に停止します。

import openpyxl
import pyautogui
import pyperclip
import time
import sys

# --- グローバル設定 ---
MAX_RETRIES = 3  # ★★★ 入力失敗時の最大リトライ回数

# --- 関数定義 ---
def paste_text(text):
    """
    クリップボード経由でテキストをペースト入力する関数。
    """
    text_to_paste = "" if text is None else str(text)
    pyperclip.copy(text_to_paste)
    
    if sys.platform == 'darwin':
        pyautogui.hotkey('command', 'v')
    else:
        pyautogui.hotkey('ctrl', 'v')
    
    time.sleep(0.5)

# ★★★ 入力検証のための関数を新規追加 ★★★
def verify_input(expected_text, field_name):
    """
    入力フィールドのテキストをクリップボードにコピーし、期待値と一致するか検証する関数。
    前提：検証したい入力フィールドがアクティブになっていること。
    """
    # ExcelのセルがNoneの場合も考慮して、文字列に変換しておく
    expected_text_str = "" if expected_text is None else str(expected_text)

    # クリップボードを一旦クリア
    pyperclip.copy('')
    time.sleep(0.2)
    
    # (Ctrl+A)で全選択し、(Ctrl+C)でコピー
    if sys.platform == 'darwin':
        pyautogui.hotkey('command', 'a')
        time.sleep(0.3)
        pyautogui.hotkey('command', 'c')
    else:
        pyautogui.hotkey('ctrl', 'a')
        time.sleep(0.3)
        pyautogui.hotkey('ctrl', 'c')
        
    time.sleep(0.3) # クリップボードにデータが格納されるのを待つ

    # クリップボードから読み取った値
    pasted_text = pyperclip.paste()
    
    # 前後の空白を削除して比較
    if pasted_text.strip() == expected_text_str.strip():
        print(f"  [OK] {field_name} の入力内容を確認しました。")
        return True
    else:
        print(f"  [NG] {field_name} の入力確認に失敗しました。")
        print(f"       - 期待値: '{expected_text_str}'")
        print(f"       - 実際の値: '{pasted_text}'")
        return False

# ★★★ 入力と検証をセットで行う関数を新規追加 ★★★
def input_and_verify(x, y, text_to_input, field_name):
    """
    指定座標をクリックし、テキストを入力、そしてその結果を検証する一連の処理を行う。
    失敗した場合は最大回数までリトライする。
    """
    for attempt in range(MAX_RETRIES):
        print(f"-> {field_name} を入力します... ({attempt + 1}/{MAX_RETRIES}回目)")
        pyautogui.click(x, y)
        time.sleep(1.0) # クリック後、入力欄がアクティブになるのをしっかり待つ
        paste_text(text_to_input)
        
        # 検証処理
        if verify_input(text_to_input, field_name):
            return True # 成功したらループを抜ける
        else:
            print("     入力に失敗したため、リトライします。")
            time.sleep(1) # リトライ前に少し待つ
            
    # 最大リトライ回数を超えた場合
    print(f"\n[エラー] {field_name}の入力に{MAX_RETRIES}回失敗しました。プログラムを停止します。")
    return False


# --- メイン処理 ---
if __name__ == "__main__":
    
    # --- 開始前のアナウンス ---
    print("■■■ GUI自動化プログラム（信頼性向上版）を開始します ■■■")
    print("5秒後に処理を開始します。")
    print("【重要】それまでに、データ転記先のアプリケーションウィンドウをクリックしてアクティブな状態にしてください。")
    for i in range(5, 0, -1):
        print(f"開始まで... {i}")
        time.sleep(1)
    print("\n処理を開始します。")

    # --- Excelファイルの読み込み ---
    try:
        workbook = openpyxl.load_workbook("customer.xlsx")
        sheet = workbook["customer"]
    except FileNotFoundError:
        print("\n[エラー] Excelファイル 'customer.xlsx' が見つかりませんでした。")
        sys.exit()
    except KeyError:
        print("\n[エラー] Excelファイル内に 'customer' という名前のシートが見つかりませんでした。")
        sys.exit()
    except Exception as e:
        print(f"\n[予期せぬエラー] Excelファイルの読み込み中にエラーが発生しました: {e}")
        sys.exit()

    # --- データ転記のメインループ ---
    for i, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
        
        customer_name, furigana, phone_number, email_address, address = row[0:5]

        if not customer_name:
            print(f"({i}行目): 顧客名が空のためスキップします。")
            continue

        print("-" * 40)
        print(f"({i}行目): 「{customer_name}」様のデータを転記します。")

        try:
            # 1. 新規登録ボタン
            pyautogui.click(x=578, y=758)
            time.sleep(3.0)

            # ★★★ 以下、新しい関数 input_and_verify を使用するように変更 ★★★
            if not input_and_verify(x=867, y=443, text_to_input=customer_name, field_name="顧客名"): sys.exit()
            if not input_and_verify(x=879, y=485, text_to_input=furigana, field_name="フリガナ"): sys.exit()
            if not input_and_verify(x=869, y=622, text_to_input=phone_number, field_name="電話番号"): sys.exit()
            if not input_and_verify(x=855, y=660, text_to_input=email_address, field_name="メールアドレス"): sys.exit()
            if not input_and_verify(x=870, y=531, text_to_input=address, field_name="住所"): sys.exit()

            # 7. 登録実行ボタン
            print("-> 登録ボタンをクリックします。")
            pyautogui.click(x=872, y=700)
            time.sleep(3.5)

            # 8. 確認ダイアログを閉じる
            print("-> 確認ダイアログを閉じます。")
            pyautogui.click(x=1030, y=613)
            time.sleep(2.5)
            
            print(f"({i}行目): 転記完了。")

        except pyautogui.FailSafeException:
            print("\n[緊急停止] フェールセーフ機能が作動しました。プログラムを中断します。")
            sys.exit()
        except Exception as e:
            print(f"\n[エラー] 自動操作の実行中に予期せぬエラーが発生しました: {e}")
            sys.exit()

    print("-" * 40)
    print("\n■■■ すべてのデータの処理が完了しました。 ■■■")