import os
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from tkinterdnd2 import TkinterDnD, DND_FILES
import deepl
from opencc import OpenCC  # 簡体字・繁体字変換用ライブラリ

# 言語の選択肢（表示名: DeepL/OpenCC識別用コード）
LANGUAGES = {
    "英語 (English)": "EN-US",
    "日本語 (Japanese)": "JA",
    "韓国語 (Korean)": "KO",
    "中国語 簡体字 (Chinese-Simplified)": "ZH",
    "中国語 繁体字 (Chinese-Traditional)": "ZH-HANT",
    "ドイツ語 (German)": "DE",
    "フランス語 (French)": "FR"
}

# ⚠️ ここにご自身のDeepL APIキーを貼り付けてください
API_KEY = "my_deepl_api_key"

class AdvancedTranslatorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("実用DeepL翻訳ツール (D&D ＆ 貼り付け対応)")
        self.root.geometry("1000x600")

        # DeepLクライアントの初期化
        try:
            self.translator = deepl.Translator(API_KEY)
        except Exception as e:
            messagebox.showerror("初期化エラー", "DeepL APIキーが無効、または未設定です。コード内のAPI_KEYを確認してください。")
            self.translator = None

        # --- 1. 上部コントロールエリア（ボタン類を配置） ---
        top_frame = ttk.Frame(root, padding=10)
        top_frame.pack(fill="x")

        # 言語選択
        ttk.Label(top_frame, text="翻訳先の言語: ").pack(side="left")
        self.lang_var = tk.StringVar(value="日本語 (Japanese)")
        self.lang_combo = ttk.Combobox(
            top_frame, textvariable=self.lang_var, values=list(LANGUAGES.keys()), state="readonly", width=18
        )
        self.lang_combo.pack(side="left", padx=5)

        # 各種操作ボタン（左から順に配置）
        self.btn_translate = ttk.Button(top_frame, text="画面のテキストを翻訳する", command=self.translate_input_text)
        self.btn_translate.pack(side="left", padx=5)

        self.btn_export = ttk.Button(top_frame, text="原文と訳文をテキスト出力", command=self.export_text_to_file)
        self.btn_export.pack(side="left", padx=5)

        self.btn_clear = ttk.Button(top_frame, text="クリア", command=self.clear_text)
        self.btn_clear.pack(side="left", padx=5)

        # --- 2. メイン編集エリア（左右分割・右側2.5倍幅） ---
        main_frame = ttk.Frame(root, padding=10)
        main_frame.pack(fill="both", expand=True)

        main_frame.columnconfigure(0, weight=2) # 左（原文）の比率
        main_frame.columnconfigure(1, weight=5) # 右（訳文）の比率（2.5倍）
        main_frame.rowconfigure(0, weight=1)

        # 左側：原文入力
        left_frame = ttk.LabelFrame(main_frame, text=" 原文 (テキスト入力 / 貼り付け / txtファイルをD&D) ", padding=5)
        left_frame.grid(row=0, column=0, sticky="nsew", padx=5)

        self.src_text = tk.Text(left_frame, wrap="word", undo=True, font=("Meiryo", 10))
        self.src_text.pack(fill="both", expand=True)

        # 右側：訳文出力
        right_frame = ttk.LabelFrame(main_frame, text=" 翻訳結果 ", padding=5)
        right_frame.grid(row=0, column=1, sticky="nsew", padx=5)

        self.dest_text = tk.Text(right_frame, wrap="word", font=("Meiryo", 10))
        self.dest_text.pack(fill="both", expand=True)

        # --- 3. 右クリックメニューの設定 ---
        self.context_menu = tk.Menu(root, tearoff=0)
        self.context_menu.add_command(label="コピー", command=self.menu_copy)
        self.context_menu.add_command(label="貼り付け", command=self.menu_paste)
        self.context_menu.add_command(label="すべて選択", command=self.menu_select_all)

        # 左右両方のテキストエリアに右クリックをバインド
        self.src_text.bind("<Button-3>", self.show_context_menu)
        self.dest_text.bind("<Button-3>", self.show_context_menu)

        # --- 4. 下部ステータスエリア ---
        bottom_frame = ttk.Frame(root, padding=5)
        bottom_frame.pack(fill="x")

        self.status_label = ttk.Label(bottom_frame, text="準備完了（ファイルをここにD&D、または直接文章を貼り付けてください）")
        self.status_label.pack(side="left", padx=5)

        # --- 5. ドラッグ＆ドロップ機能の登録 ---
        self.root.drop_target_register(DND_FILES)
        self.root.dnd_bind('<<Drop>>', self.handle_file_drop)
        self.src_text.drop_target_register(DND_FILES)
        self.src_text.dnd_bind('<<Drop>>', self.handle_file_drop)

    # --- 右クリックメニューの処理 ---
    def show_context_menu(self, event):
        """右クリックメニューを表示する（クリックされたテキストエリアを記録）"""
        self.active_text_widget = event.widget  # クリックされた方を記録
        self.context_menu.post(event.x_root, event.y_root)

    def menu_copy(self):
        """選択されたテキストをコピー"""
        if hasattr(self, 'active_text_widget'):
            try:
                self.active_text_widget.event_generate("<<Copy>>")
            except tk.TclError:
                pass

    def menu_paste(self):
        """クリップボードから貼り付け"""
        if hasattr(self, 'active_text_widget'):
            try:
                self.active_text_widget.event_generate("<<Paste>>")
            except tk.TclError:
                pass

    def menu_select_all(self):
        """テキストをすべて選択"""
        if hasattr(self, 'active_text_widget'):
            self.active_text_widget.tag_add("sel", "1.0", "end")
            self.active_text_widget.mark_set("insert", "1.0")
            self.active_text_widget.see("insert")

    # --- 翻訳・変換のコアロジック ---
    def process_translation(self, text_content, dest_lang):
        """
        指定された言語コードに応じて、DeepL翻訳またはOpenCC変換を行う内部関数。
        変数の不整合エラーを回避するため、完全にカプセル化しています。
        """
        # 原文が漢字（中国語）であるかを判定するための簡易チェック
        is_original_chinese = any(0x4e00 <= ord(c) <= 0x9fff for c in text_content)

        # ケース1: 翻訳先が「繁体字」で、原文が中国語（簡体字など）の場合 -> OpenCCで直接変換
        if dest_lang == "ZH-HANT" and is_original_chinese:
            cc = OpenCC('s2twp')  # 簡体字から台湾繁体字（固有名詞変換含む）
            return cc.convert(text_content)

        # ケース2: 翻訳先が「簡体字」で、原文が中国語（繁体字）の場合 -> OpenCCで直接変換
        elif dest_lang == "ZH" and is_original_chinese:
            cc = OpenCC('t2s')  # 繁体字から簡体字
            return cc.convert(text_content)

        # ケース3: それ以外の通常の言語（英語、日本語、独、仏など） -> DeepL APIを使用
        else:
            if not self.translator:
                raise Exception("APIキーが設定されていないため、DeepL翻訳を実行できません。")
            result = self.translator.translate_text(text_content, target_lang=dest_lang)
            return result.text

    # --- ファイル保存の処理 ---
    def export_text_to_file(self):
        """画面の原文と訳文をセットにしてファイル出力する"""
        src_content = self.src_text.get("1.0", tk.END).strip()
        dest_content = self.dest_text.get("1.0", tk.END).strip()

        if not src_content or not dest_content:
            messagebox.showwarning("警告", "出力する原文または翻訳結果がありません。先に翻訳を行ってください。")
            return

        selected_lang_name = self.lang_var.get()
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
            title="翻訳結果の保存",
            initialfile=f"translated_{LANGUAGES[selected_lang_name].lower().replace('-', '_')}.txt"
        )

        if not file_path:
            return  # キャンセルされた場合

        try:
            with open(file_path, 'a', encoding='utf-8') as f:
                f.write("=== 原文 (Original) ===\n")
                f.write(src_content)
                f.write("\n\n")
                f.write(f"=== 翻訳文 (Translated to {selected_lang_name}) ===\n")
                f.write(dest_content)

            self.status_label.config(text=f"ファイルに出力しました: {os.path.basename(file_path)}")
            messagebox.showinfo("成功", "原文と翻訳文の出力を完了しました！")
        except Exception as e:
            messagebox.showerror("エラー", f"ファイル保存中にエラーが発生しました:\n{e}")

    def handle_file_drop(self, event):
        """ファイルをドロップされた時の処理"""
        file_path = event.data.strip('{}')

        if not file_path.endswith('.txt'):
            messagebox.showerror("エラー", "D&D翻訳に対応しているファイルは .txt のみです。\nその他の文章はコピー＆ペーストしてください。")
            return

        selected_lang_name = self.lang_var.get()
        dest_lang = LANGUAGES[selected_lang_name]

        try:
            self.status_label.config(text="ファイルを読み込んで処理中...")
            self.root.update_idletasks()

            with open(file_path, 'r', encoding='utf-8') as f:
                text_content = f.read()

            if not text_content.strip():
                messagebox.showwarning("警告", "ファイルが空です。")
                return

            self.src_text.delete("1.0", tk.END)
            self.src_text.insert("1.0", text_content)

            # 改良したコアロジックで翻訳・変換を実行
            translated_text = self.process_translation(text_content, dest_lang)

            self.dest_text.delete("1.0", tk.END)
            self.dest_text.insert("1.0", translated_text)

            # ファイルに自動保存
            base, ext = os.path.splitext(file_path)
            output_path = f"{base}_{dest_lang.lower().replace('-', '_')}{ext}"
            with open(output_path, 'w', encoding='utf-8') as f:
                f.write("=== 原文 (Original) ===\n")
                f.write(text_content)
                f.write("\n\n")
                f.write(f"=== 翻訳文 (Translated to {selected_lang_name}) ===\n")
                f.write(translated_text)

            self.status_label.config(text=f"処理完了: {os.path.basename(output_path)} に保存しました")
            messagebox.showinfo("成功", f"処理・保存が完了しました！\n\n保存先:\n{output_path}")

        except Exception as e:
            messagebox.showerror("エラー", f"処理中にエラーが発生しました:\n{e}")
            self.status_label.config(text="エラーが発生しました")

    def translate_input_text(self):
        """「画面のテキストを翻訳する」ボタンが押された時の処理"""
        text_content = self.src_text.get("1.0", tk.END).strip()

        if not text_content:
            messagebox.showwarning("警告", "翻訳するテキストを入力または貼り付けてください。")
            return

        dest_lang = LANGUAGES[self.lang_var.get()]

        try:
            self.status_label.config(text="処理中...")
            self.root.update_idletasks()

            # 改良したコアロジックで翻訳・変換を実行
            translated_text = self.process_translation(text_content, dest_lang)

            self.dest_text.delete("1.0", tk.END)
            self.dest_text.insert("1.0", translated_text)

            self.status_label.config(text="処理が完了しました")

        except Exception as e:
            messagebox.showerror("エラー", f"処理中にエラーが発生しました:\n{e}")
            self.status_label.config(text="エラーが発生しました")

    def clear_text(self):
        """テキストエリアをクリア"""
        self.src_text.delete("1.0", tk.END)
        self.dest_text.delete("1.0", tk.END)
        self.status_label.config(text="クリアしました")

# --- アプリケーションの起動 ---
if __name__ == "__main__":
    root = TkinterDnD.Tk()
    app = AdvancedTranslatorApp(root)
    root.mainloop()
