import sys
import json
import os
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QTabWidget, QGridLayout,
    QTextEdit, QPushButton, QVBoxLayout, QHBoxLayout, QColorDialog,
    QFontDialog, QInputDialog, QMenu, QTabBar, QMessageBox, QLineEdit, QLabel
)
from PySide6.QtGui import QFont, QColor, QAction
from PySide6.QtCore import Qt, Signal

SAVE_FILE = "sticky_notes_data.json"

class StickyNote(QWidget):
    """単一の付箋を表すカスタムウィジェット"""
    data_changed = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout(self)
        layout.setContentsMargins(5, 5, 5, 5)
        layout.setSpacing(4)

        self.text_edit = QTextEdit()
        self.text_edit.setPlaceholderText("用件を入力してください（約5行）...")
        self.text_edit.textChanged.connect(self.data_changed.emit)

        default_font = QFont("Helvetica", 11)
        self.text_edit.setFont(default_font)

        self.base_color_hex = "#FFF9C4"  # 初期の薄黄色
        self.set_note_color(QColor(self.base_color_hex))

        btn_layout = QHBoxLayout()
        btn_layout.setSpacing(2)

        self.btn_font = QPushButton("文字設定")
        self.btn_color = QPushButton("色変更")
        self.btn_clear = QPushButton("消去")

        btn_style = "font-size: 10px; padding: 2px;"
        for btn in [self.btn_font, self.btn_color, self.btn_clear]:
            btn.setStyleSheet(btn_style)

        self.btn_font.clicked.connect(self.change_font)
        self.btn_color.clicked.connect(self.change_color)
        self.btn_clear.clicked.connect(self.clear_text)

        btn_layout.addWidget(self.btn_font)
        btn_layout.addWidget(self.btn_color)
        btn_layout.addWidget(self.btn_clear)

        layout.addWidget(self.text_edit)
        layout.addLayout(btn_layout)

    def set_note_color(self, color, highlight=False):
        """付箋の背景色を設定。検索ヒット時は枠線を赤く太くする"""
        self.current_color = color
        self.base_color_hex = color.name()

        # 検索ヒット時は枠線を赤(#FF5252)に変更
        border_style = "2px solid #FF5252" if highlight else "1px solid #E0E0E0"

        self.text_edit.setStyleSheet(f"""
            QTextEdit {{
                background-color: {self.base_color_hex};
                border: {border_style};
                border-radius: 4px;
            }}
        """)

    def change_color(self):
        color = QColorDialog.getColor(self.current_color, self, "付箋の背景色を選択")
        if color.isValid():
            self.set_note_color(color)
            self.data_changed.emit()

    def change_font(self):
        current_font = self.text_edit.font()
        ok, font = QFontDialog.getFont(current_font, self, "文字設定")
        if ok:
            self.text_edit.setFont(font)
            self.data_changed.emit()

    def clear_text(self):
        self.text_edit.clear()

    def get_text(self):
        """検索用のテキスト取得メソッド"""
        return self.text_edit.toPlainText()

    def get_note_data(self):
        return {
            "text": self.text_edit.toPlainText(),
            "color": self.base_color_hex,
            "font": self.text_edit.font().toString()
        }

    def set_note_data(self, data):
        self.text_edit.blockSignals(True)
        if "text" in data:
            self.text_edit.setPlainText(data["text"])
        if "color" in data:
            self.set_note_color(QColor(data["color"]))
        if "font" in data:
            font = QFont()
            font.fromString(data["font"])
            self.text_edit.setFont(font)
        self.text_edit.blockSignals(False)


class CustomTabBar(QTabBar):
    """右クリックメニュー（名前変更・削除）をサポートするカスタムタブバー"""
    tab_renamed = Signal()
    tab_delete_requested = Signal(int)

    def __init__(self, parent=None):
        super().__init__(parent)

    def mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            index = self.tabAt(event.position().toPoint())
            if index != -1:
                self.show_context_menu(index, event.globalPosition().toPoint())
        else:
            super().mousePressEvent(event)

    def show_context_menu(self, index, global_pos):
        menu = QMenu(self)
        rename_action = QAction("タブの名前を変更", self)
        delete_action = QAction("このタブを削除", self)

        menu.addAction(rename_action)
        menu.addAction(delete_action)

        action = menu.exec(global_pos)
        if action == rename_action:
            current_text = self.tabText(index)
            new_text, ok = QInputDialog.getText(
                self, "タブ名の変更", "新しいタブ名を入力してください:", text=current_text
            )
            if ok and new_text.strip():
                self.setTabText(index, new_text.strip())
                self.tab_renamed.emit()
        elif action == delete_action:
            self.tab_delete_requested.emit(index)


class StickyNoteNotebook(QMainWindow):
    """メインウィンドウ（増減機能＋検索機能の完全版）"""
    def __init__(self):
        super().__init__()
        self.setWindowTitle("多機能付箋ノート (PySide6)")
        self.resize(900, 800)

        self.is_loading = False

        # メインのベース構造（最上部に検索バーを置くためのレイアウト）
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout(main_widget)

        # === 🔍 検索バーエリアの作成 ===
        search_layout = QHBoxLayout()
        search_layout.setContentsMargins(10, 5, 10, 5)

        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("検索したいキーワードを入力（全タブから探します）...")
        self.search_input.returnPressed.connect(self.perform_search)  # Enterキーでも検索可能に

        search_button = QPushButton("検索")
        search_button.clicked.connect(self.perform_search)

        clear_search_button = QPushButton("検索クリア")
        clear_search_button.clicked.connect(self.clear_search_highlight)

        search_layout.addWidget(QLabel("付箋検索:"))
        search_layout.addWidget(self.search_input)
        search_layout.addWidget(search_button)
        search_layout.addWidget(clear_search_button)

        main_layout.addLayout(search_layout)

        # === タブエリアの作成 ===
        self.tab_widget = QTabWidget()
        self.custom_tab_bar = CustomTabBar()
        self.tab_widget.setTabBar(self.custom_tab_bar)

        self.custom_tab_bar.tab_renamed.connect(self.save_data)
        self.custom_tab_bar.tab_delete_requested.connect(self.delete_tab)

        # 【改善】隠れやすい「＋」ボタンをやめ、検索バーの列にハッキリとボタンを配置
        self.add_tab_button = QPushButton("＋ タブを追加")
        self.add_tab_button.setStyleSheet("font-weight: bold; background-color: #E0E0E0; padding: 4px 8px;")
        self.add_tab_button.clicked.connect(self.add_new_blank_tab)
        search_layout.addWidget(self.add_tab_button)  # 検索バーの並びに追加

        main_layout.addWidget(self.tab_widget)

        self.tabs_notes = {}

        self.load_data()

    def create_default_tabs(self):
        self.tab_widget.clear()
        self.tabs_notes.clear()
        for i in range(1, 6):
            self.add_new_tab_page(f"タブ {i}", None)

    def add_new_tab_page(self, tab_name, notes_data_list=None):
        tab_page = QWidget()
        grid_layout = QGridLayout(tab_page)
        grid_layout.setSpacing(10)

        notes_list = []
        idx = 0
        for row in range(3):
            for col in range(3):
                note = StickyNote()
                note.data_changed.connect(self.save_data)
                grid_layout.addWidget(note, row, col)
                notes_list.append(note)

                if notes_data_list and idx < len(notes_data_list):
                    note.set_note_data(notes_data_list[idx])
                idx += 1

        self.tab_widget.addTab(tab_page, tab_name)
        self.tabs_notes[tab_page] = notes_list
        return tab_page

    def add_new_blank_tab(self):
        new_page = self.add_new_tab_page("新規タブ", None)
        self.tab_widget.setCurrentWidget(new_page)
        self.save_data()

    def delete_tab(self, index):
        if self.tab_widget.count() <= 1:
            QMessageBox.warning(self, "削除不可", "これ以上タブを削除できません。")
            return

        tab_name = self.tab_widget.tabText(index)
        reply = QMessageBox.question(
            self, "タブの削除確認",
            f"「{tab_name}」の付箋データをすべて削除しますか？",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )

        if reply == QMessageBox.Yes:
            tab_page = self.tab_widget.widget(index)
            if tab_page in self.tabs_notes:
                del self.tabs_notes[tab_page]
            self.tab_widget.removeTab(index)
            self.save_data()

    # === 🔍 検索機能のロジック ===
    def perform_search(self):
        """全タブの付箋から文字を検索する"""
        query = self.search_input.text().strip()
        if not query:
            self.clear_search_highlight()
            return

        found_any = False
        first_match_tab_index = -1

        # 一度すべての強調表示をリセット
        self.clear_search_highlight(reset_input=False)

        # すべてのタブをループしてテキストを検索
        for i in range(self.tab_widget.count()):
            tab_page = self.tab_widget.widget(i)
            notes_list = self.tabs_notes.get(tab_page, [])

            for note in notes_list:
                if query in note.get_text():
                    # ヒットした付箋の枠線を強調（赤枠）
                    note.set_note_color(QColor(note.base_color_hex), highlight=True)
                    found_any = True
                    if first_match_tab_index == -1:
                        first_match_tab_index = i

        # 見つかった場合は、最初にヒットした付箋があるタブに切り替える
        if found_any:
            self.tab_widget.setCurrentIndex(first_match_tab_index)
        else:
            QMessageBox.information(self, "検索結果", f"「{query}」が見つかる付箋はありませんでした。")

    def clear_search_highlight(self, reset_input=True):
        """検索の赤枠ハイライトを元に戻す"""
        if reset_input:
            self.search_input.clear()

        for tab_page, notes_list in self.tabs_notes.items():
            for note in notes_list:
                # ハイライトをオフにして元の背景色を維持
                note.set_note_color(QColor(note.base_color_hex), highlight=False)

    def save_data(self):
        """現在のすべてのタブ名と付箋の状態をJSONに保存する"""
        if self.is_loading:
            return

        data = []
        for i in range(self.tab_widget.count()):
            tab_name = self.tab_widget.tabText(i)
            tab_page = self.tab_widget.widget(i)
            notes_list = self.tabs_notes.get(tab_page, [])
            notes_data = [note.get_note_data() for note in notes_list]

            data.append({
                "tab_name": tab_name,
                "notes": notes_data
            })

        try:
            with open(SAVE_FILE, "w", encoding="utf-8") as f:
                json.dump(data, f, ensure_ascii=False, indent=4)
        except Exception as e:
            print(f"保存エラー: {e}")

    def load_data(self):
        """JSONファイルからデータを読み込んで画面を再構築する"""
        if not os.path.exists(SAVE_FILE):
            self.create_default_tabs()
            return

        self.is_loading = True
        try:
            with open(SAVE_FILE, "r", encoding="utf-8") as f:
                data = json.load(f)

            self.tab_widget.clear()
            self.tabs_notes.clear()

            for tab_item in data:
                tab_name = tab_item.get("tab_name", "タブ")
                notes_data_list = tab_item.get("notes", [])
                self.add_new_tab_page(tab_name, notes_data_list)

        except Exception as e:
            print(f"読み込みエラー: {e}")
            self.create_default_tabs()
        finally:
            self.is_loading = False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    window = StickyNoteNotebook()
    window.show()
    sys.exit(app.exec())


