import tkinter as tk
from tkinter import ttk, messagebox
import csv
import json
import os
from datetime import date


class App34:
    """気分トラッカー"""

    MOODS = [
        ("😄", "最高", "#27ae60"),
        ("😊", "良い", "#2ecc71"),
        ("😐", "普通", "#f39c12"),
        ("😔", "悪い", "#e67e22"),
        ("😢", "最悪", "#e74c3c"),
    ]
    SAVE_FILE = "mood_log.csv"
    LEGACY_FILE = "mood_log.json"   # 旧バージョンの保存ファイル（あれば CSV へ移行）
    FIELDS = ["date", "mood", "emoji", "memo"]

    def __init__(self, root):
        self.root = root
        self.root.title("気分トラッカー")
        self.root.geometry("641x600")
        self.root.minsize(641, 600)
        self.root.configure(bg="#f8f9fc")
        self.records = self._load()
        self._build_ui()
        self._refresh_history()

    def _load(self):
        if os.path.exists(self.SAVE_FILE):
            with open(self.SAVE_FILE, encoding="utf-8", newline="") as f:
                return [dict(row) for row in csv.DictReader(f)]
        if os.path.exists(self.LEGACY_FILE):
            with open(self.LEGACY_FILE, encoding="utf-8") as f:
                self.records = json.load(f)
            self._save()   # JSON の内容をそのまま CSV に書き出して移行完了
            return self.records
        return []

    def _save(self):
        with open(self.SAVE_FILE, "w", encoding="utf-8", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=self.FIELDS, extrasaction="ignore")
            writer.writeheader()
            writer.writerows(self.records)

    def _mood_score(self, label):
        # 気分ラベルを 5（最高）〜1（最悪）の数値に変換する（未知のラベルは None）
        labels = [m[1] for m in self.MOODS]
        return len(labels) - labels.index(label) if label in labels else None

    def _build_ui(self):
        title_frame = tk.Frame(self.root, bg="#3776ab", pady=12)
        title_frame.pack(fill=tk.X)
        tk.Label(title_frame, text="気分トラッカー",
                 font=("Noto Sans JP", 16, "bold"),
                 bg="#3776ab", fg="white").pack()

        main_frame = tk.Frame(self.root, bg="#f8f9fc", padx=20, pady=12)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 今日の気分
        today_frame = ttk.LabelFrame(main_frame, text=f"今日の気分（{date.today()}）", padding=10)
        today_frame.pack(fill=tk.X, pady=(0, 10))

        bg_color = self.root.cget("bg")
        mood_row = tk.Frame(today_frame, bg=bg_color)
        mood_row.pack()
        self.mood_var = tk.IntVar(value=-1)
        for i, (emoji, label, color) in enumerate(self.MOODS):
            col = tk.Frame(mood_row, bg=bg_color)
            col.pack(side=tk.LEFT, padx=8)
            tk.Label(col, text=emoji, font=("Segoe UI Emoji", 26),
                     bg=bg_color).pack()
            tk.Radiobutton(col, text=label, variable=self.mood_var, value=i,
                           bg=bg_color,
                           activebackground=bg_color,
                           font=("Noto Sans JP", 9)).pack()

        tk.Label(today_frame, text="メモ（任意）:", bg=bg_color).pack(anchor="w", pady=(8, 2))
        self.memo_entry = ttk.Entry(today_frame, font=("Noto Sans JP", 11), width=40)
        self.memo_entry.pack(fill=tk.X)

        ttk.Button(main_frame, text="記録する", command=self.record).pack(pady=8)

        # 気分の推移グラフ
        graph_frame = ttk.LabelFrame(main_frame, text="気分の推移（直近30件）", padding=4)
        graph_frame.pack(fill=tk.X, pady=(0, 10))
        self.canvas = tk.Canvas(graph_frame, height=130, bg="white",
                                highlightthickness=1, highlightbackground="#ccc")
        self.canvas.pack(fill=tk.X)
        self.canvas.bind("<Configure>", lambda e: self._draw_graph())

        # 履歴
        hist_frame = ttk.LabelFrame(main_frame, text="記録履歴", padding=8)
        hist_frame.pack(fill=tk.BOTH, expand=True)

        self.hist_text = tk.Text(hist_frame, font=("Noto Sans JP", 10),
                                 bg="white", relief=tk.FLAT, state=tk.DISABLED, height=8)
        self.hist_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        sb = ttk.Scrollbar(hist_frame, command=self.hist_text.yview)
        self.hist_text.configure(yscrollcommand=sb.set)
        sb.pack(side=tk.RIGHT, fill=tk.Y)

    def record(self):
        mood_idx = self.mood_var.get()
        if mood_idx == -1:
            messagebox.showwarning("警告", "気分を選択してください")
            return
        emoji, label, _ = self.MOODS[mood_idx]
        memo = self.memo_entry.get().strip()
        rec = {"date": str(date.today()), "mood": label, "emoji": emoji, "memo": memo}
        self.records.append(rec)
        self._save()
        self.memo_entry.delete(0, tk.END)
        self.mood_var.set(-1)
        self._refresh_history()
        messagebox.showinfo("記録完了", f"今日の気分「{emoji} {label}」を記録しました")

    def _refresh_history(self):
        self.hist_text.config(state=tk.NORMAL)
        self.hist_text.delete("1.0", tk.END)
        for r in reversed(self.records[-30:]):
            line = f"{r['date']}  {r['emoji']} {r['mood']}"
            if r.get("memo"):
                line += f"  — {r['memo']}"
            self.hist_text.insert(tk.END, line + "\n")
        self.hist_text.config(state=tk.DISABLED)
        self._draw_graph()

    def _draw_graph(self):
        c = self.canvas
        c.delete("all")
        w, h = c.winfo_width(), c.winfo_height()
        left, right, top, bottom = 40, 16, 12, 22
        points = [(r["date"], self._mood_score(r["mood"]), r["mood"])
                  for r in self.records[-30:]]
        points = [p for p in points if p[1] is not None]
        if not points:
            c.create_text(w / 2, h / 2, text="記録がありません", fill="#999")
            return
        plot_w, plot_h = w - left - right, h - top - bottom
        levels = len(self.MOODS)
        # 縦軸: 5段階の気分を絵文字で表示
        for i, (emoji, _, _) in enumerate(self.MOODS):
            y = top + plot_h * i / (levels - 1)
            c.create_text(20, y, text=emoji, font=("Segoe UI Emoji", 9))
            c.create_line(left, y, w - right, y, fill="#eee")
        n = len(points)
        coords = []
        for i, (_, score, _) in enumerate(points):
            x = left + (plot_w * i / (n - 1) if n > 1 else plot_w / 2)
            y = top + plot_h * (levels - score) / (levels - 1)
            coords.append((x, y))
        for (x1, y1), (x2, y2) in zip(coords, coords[1:]):
            c.create_line(x1, y1, x2, y2, fill="#3776ab", width=2)
        for (x, y), (_, score, _) in zip(coords, points):
            color = self.MOODS[levels - score][2]
            c.create_oval(x - 4, y - 4, x + 4, y + 4, fill=color, outline="white")
        c.create_text(left, h - bottom + 4, text=points[0][0], anchor="n", font=("Arial", 8))
        c.create_text(w - right, h - bottom + 4, text=points[-1][0], anchor="ne", font=("Arial", 8))


if __name__ == "__main__":
    root = tk.Tk()
    app = App34(root)
    root.mainloop()
