import os
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext


class FileTreeApp:

    def __init__(self, root):
        self.root = root
        self.root.title("ファイルツリー作成ツール (filistry風)")
        self.root.geometry("700x550")

        # 画面のレイアウト作成
        self.create_widgets()

    def create_widgets(self):
        # ----------------------------------------------------
        # 1. 上部：フォルダ選択エリア
        # ----------------------------------------------------
        top_frame = tk.Frame(self.root, pady=10)
        top_frame.pack(fill=tk.X)

        tk.Button(
            top_frame,
            text="フォルダを選択",
            command=self.select_folder,
            width=15,
            font=("Arial", 10, "bold"),
        ).pack(side=tk.LEFT, padx=10)

        self.lbl_path = tk.Label(
            top_frame, text="対象のフォルダが選択されていません", fg="gray", anchor="w"
        )
        self.lbl_path.pack(side=tk.LEFT, fill=tk.X, expand=True)

        # ----------------------------------------------------
        # 2. 中央：結果表示エリア
        # ----------------------------------------------------
        main_frame = tk.Frame(self.root, padx=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        tk.Label(
            main_frame, text="【生成されたファイルツリー】", font=("Arial", 9, "bold")
        ).pack(anchor="w", pady=(0, 5))

        # スクロール付きのテキストエリア
        self.txt_result = scrolledtext.ScrolledText(
            main_frame, font=("MS Gothic", 10), wrap=tk.NONE
        )  # 等幅フォントでズレを防止
        self.txt_result.pack(fill=tk.BOTH, expand=True)

        # ----------------------------------------------------
        # 3. 下部：保存エリア
        # ----------------------------------------------------
        bottom_frame = tk.Frame(self.root, pady=15)
        bottom_frame.pack(fill=tk.X, side=tk.BOTTOM)

        self.btn_save = tk.Button(
            bottom_frame,
            text="テキストファイルとして保存",
            command=self.save_tree,
            font=("Arial", 11, "bold"),
            bg="#4CAF50",
            fg="white",
            padx=20,
            pady=5,
        )
        self.btn_save.pack()

    def select_folder(self):
        """フォルダ選択ダイアログを開き、ツリーを生成する"""
        folder_path = filedialog.askdirectory(title="解析するフォルダを選択")
        if not folder_path:
            return

        # パス表示を更新
        self.lbl_path.config(text=folder_path, fg="black")

        # 画面を一度クリア
        self.txt_result.delete("1.0", tk.END)

        # ツリー構造のテキストを生成
        tree_text = f"📁 {os.path.basename(folder_path)}\n"
        tree_text += self.generate_tree(folder_path, "")

        # 画面に出力
        self.txt_result.insert(tk.END, tree_text)

    def generate_tree(self, dir_path, prefix=""):
        """再帰アルゴリズムを使ってフォルダ内のツリーをテキスト化する"""
        try:
            # フォルダ内のアイテム（ファイル、フォルダ）の一覧を取得
            items = os.listdir(dir_path)
        except Exception as e:
            return f"{prefix}└── [アクセス拒否: {e}]\n"

        # 表示をきれいにするために並び替え
        items.sort()

        output = ""
        num_items = len(items)

        for i, item in enumerate(items):
            # その階層の最後のアイテムかどうかを判定
            is_last = i == num_items - 1
            connector = "└── " if is_last else "├── "

            full_path = os.path.join(dir_path, item)

            if os.path.isdir(full_path):
                # フォルダの場合
                output += f"{prefix}{connector}📁 {item}\n"
                # 次の階層のインデントを決定
                next_prefix = prefix + ("    " if is_last else "│   ")
                output += self.generate_tree(full_path, next_prefix)
            else:
                # ファイルの場合
                output += f"{prefix}{connector}📄 {item}\n"

        return output

    def save_tree(self):
        """画面に表示されているテキストを保存する"""
        tree_text = self.txt_result.get("1.0", tk.END).strip()
        if not tree_text:
            messagebox.showwarning(
                "警告", "保存するツリーが生成されていません。"
            )
            return

        save_path = filedialog.asksaveasfilename(
            title="名前を付けてツリーを保存",
            defaultextension=".txt",
            filetypes=[("Text files", "*.txt"), ("All files", "*.*")],
        )

        if not save_path:
            return

        try:
            with open(save_path, "w", encoding="utf-8") as f:
                f.write(tree_text)
            messagebox.showinfo("成功", "ツリーを保存しました！")
        except Exception as e:
            messagebox.showerror(
                "エラー", f"ファイルの保存中にエラーが発生しました:\n{e}"
            )


if __name__ == "__main__":
    root = tk.Tk()
    app = FileTreeApp(root)
    root.mainloop()
