"""
ショートカット管理システム
ヘッダーのショートカットとリングランチャーを統合管理
"""

import sys
import os
import shutil
import configparser
import logging
import time
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel, 
                             QPushButton, QFileDialog, QGridLayout, 
                             QMessageBox, QComboBox, QScrollArea, QWidget, QInputDialog)
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPixmap, QIcon
from app_utils import get_translation, resource_path, get_config_file_path
from utils.emoji_dialog import EmojiSelectionDialog

class ShortcutManager:
    """ショートカット設定の統合管理クラス"""
    
    def __init__(self, config_file=None):
        # 統一したconfig_pathを使用
        self.config_file = config_file or get_config_file_path()
        self.config = configparser.ConfigParser()
        self.load_config()
        
        # デフォルト設定
        self.max_shortcuts = 10
        
        # UI更新制御用
        self._update_in_progress = False
        
        # ビルド環境と開発環境でパスを切り替え
        if getattr(sys, 'frozen', False):
            # PyInstallerでビルドされた場合
            self.base_dir = os.path.dirname(sys.executable)
            self.icon_dir = os.path.join(self.base_dir, 'shortcut_icons')
            self.texts_dir = os.path.join(self.base_dir, 'texts')
        else:
            # 開発環境
            self.icon_dir = resource_path('shortcut_icons')
            self.texts_dir = resource_path('texts')
        
        # ディレクトリが存在しない場合は作成
        os.makedirs(self.icon_dir, exist_ok=True)
        os.makedirs(self.texts_dir, exist_ok=True)
    
    def load_config(self):
        """設定ファイルを読み込み"""
        try:
            if os.path.exists(self.config_file):
                self.config.read(self.config_file, encoding='utf-8')
            else:
                logging.warning(f"設定ファイルが存在しません: {self.config_file}")
            
            # セクション確認・作成
            for section in ['ShortcutMappings', 'ShortcutIcons']:
                if not self.config.has_section(section):
                    self.config.add_section(section)
                
            # 初期状態でのデフォルト絵文字設定は無効化
            # （ユーザーが明示的に設定した場合のみ絵文字を使用）
                
        except UnicodeDecodeError as e:
            logging.error(f"設定ファイル文字エンコーディングエラー: {e}")
            logging.error(f"設定ファイルの文字エンコーディングを確認してください: {self.config_file}")
        except PermissionError as e:
            logging.error(f"設定ファイル読み込み権限エラー: {e}")
            logging.error(f"設定ファイルの読み取り権限を確認してください: {self.config_file}")
        except Exception as e:
            logging.error(f"設定ファイル読み込みエラー: {e}")
            import traceback
            logging.error(f"詳細エラー情報: {traceback.format_exc()}")
    
    def save_config(self):
        """設定をファイルに保存"""
        try:
            # 設定ファイルの存在確認
            config_dir = os.path.dirname(self.config_file)
            if not os.path.exists(config_dir):
                os.makedirs(config_dir, exist_ok=True)
            
            # 必要なセクションの存在確認
            if not self.config.has_section('ShortcutMappings'):
                self.config.add_section('ShortcutMappings')
            if not self.config.has_section('ShortcutIcons'):
                self.config.add_section('ShortcutIcons')
            
            # 安全な書き込み（一時ファイルを使用）
            temp_file = self.config_file + '.tmp'
            try:
                with open(temp_file, 'w', encoding='utf-8') as f:
                    self.config.write(f)
                    f.flush()  # 即座にディスクに書き込み
                    os.fsync(f.fileno())  # OSレベルでの強制書き込み
                
                # 元のファイルに置き換え（アトミック操作）
                if os.name == 'nt':  # Windows
                    if os.path.exists(self.config_file):
                        os.remove(self.config_file)
                    os.rename(temp_file, self.config_file)
                else:  # Unix系
                    os.rename(temp_file, self.config_file)
                
                return True
                
            except Exception as write_error:
                # 一時ファイルのクリーンアップ
                if os.path.exists(temp_file):
                    try:
                        os.remove(temp_file)
                    except:
                        pass
                raise write_error
            
        except PermissionError as e:
            logging.error(f"設定ファイル保存エラー（権限不足）: {self.config_file} - {e}")
            return False
        except Exception as e:
            logging.error(f"設定ファイル保存エラー: {self.config_file} - {e}")
            import traceback
            logging.error(f"詳細エラー情報: {traceback.format_exc()}")
            return False
    
    def convert_to_relative_path(self, file_path):
        """絶対パスを相対パスに変換"""
        if not file_path or not os.path.isabs(file_path):
            return file_path
        
        try:
            if file_path.startswith(self.texts_dir):
                return os.path.relpath(file_path, self.texts_dir)
        except:
            pass
        
        # ファイル名のみを返す
        return os.path.basename(file_path)
    
    def get_actual_file_path(self, text_file):
        """テキストファイルの実際のパスを取得"""
        if not text_file:
            return None
        
        try:
            # _MEIパス（PyInstaller一時フォルダ）を除外
            if '_MEI' in text_file:
                # ファイル名のみを抽出して再検索
                text_file = os.path.basename(text_file)
                logging.warning(f"_MEIパスを検出しました。ファイル名のみで検索: {text_file}")
            
            # 複数のパス解決方法を試す
            paths_to_try = [
                os.path.join(self.texts_dir, text_file),  # 相対パス
                text_file if not '_MEI' in text_file else None,  # 絶対パス（_MEI以外）
                os.path.join(self.texts_dir, os.path.basename(text_file))  # ファイル名のみ
            ]
            
            # _MEI以外のパスのみを試行
            for path in paths_to_try:
                if path and '_MEI' not in path:
                    try:
                        if os.path.exists(path):
                            return path
                    except (OSError, IOError) as e:
                        logging.warning(f"ファイルアクセスエラー: {path} - {e}")
                        continue
            
            logging.warning(f"ファイルが見つかりません: {text_file}")
            return None
            
        except Exception as e:
            logging.error(f"ファイルパス解決エラー: {text_file} - {e}")
            return None
    
    def get_shortcut_text(self, index):
        """指定されたインデックスのショートカットテキストを取得"""
        key = f"shortcut_{index}"
        if self.config.has_option('ShortcutMappings', key):
            text_file = self.config.get('ShortcutMappings', key)
            # 絶対パスから相対パスへの自動変換（後方互換性）
            if text_file and os.path.isabs(text_file):
                relative_path = self.convert_to_relative_path(text_file)
                if relative_path:
                    self.set_shortcut_text(index, relative_path)
                    return relative_path
            return text_file
        else:
            pass
        return None
    
    def set_shortcut_text(self, index, text_file):
        """ショートカットにテキストファイルを設定"""
        try:
            if not isinstance(index, int) or index < 1 or index > self.max_shortcuts:
                raise ValueError(f"無効なインデックス: {index}")
            
            key = f"shortcut_{index}"
            if text_file:
                # ファイル存在確認
                if not os.path.exists(text_file):
                    actual_path = self.get_actual_file_path(text_file)
                    if not actual_path:
                        logging.error(f"指定されたテキストファイルが見つかりません: {text_file}")
                        return False
                    text_file = actual_path
                
                # 常に相対パスで保存
                relative_path = self.convert_to_relative_path(text_file)
                final_path = relative_path or text_file
                self.config.set('ShortcutMappings', key, final_path)
                # logging.info(f"テキストファイルを設定: {index} -> {final_path}")
            else:
                if self.config.has_option('ShortcutMappings', key):
                    self.config.remove_option('ShortcutMappings', key)
                    # logging.info(f"テキストファイルをクリア: {index}")
            
            save_result = self.save_config()
            if not save_result:
                logging.error(f"テキストファイル設定の保存に失敗: {index}")
                return False
            
            return True
        except ValueError as e:
            logging.error(f"テキストファイル設定バリデーションエラー: {e}")
            return False
        except Exception as e:
            logging.error(f"テキストファイル設定エラー: {e}")
            import traceback
            logging.error(f"詳細エラー情報: {traceback.format_exc()}")
            return False
    
    def get_shortcut_icon(self, index):
        """指定されたインデックスのアイコンパスを取得"""
        icon_filename = f"{index}.png"
        icon_path = os.path.join(self.icon_dir, icon_filename)
        
        # 互換性のために古い形式もチェック
        if not os.path.exists(icon_path):
            icon_filename = f"{index}.jpg"
            icon_path = os.path.join(self.icon_dir, icon_filename)
        
        if os.path.exists(icon_path):
            return icon_path
        return None
    
    def set_shortcut_icon(self, index, source_image_path):
        """ショートカットにアイコンを設定（強化版）"""
        if not source_image_path:
            logging.warning(f"アイコンパスが指定されていません: index={index}")
            return False
            
        if not os.path.exists(source_image_path):
            logging.warning(f"アイコンファイルが存在しません: {source_image_path}")
            return False
        
        try:
            # ディレクトリの確実な作成と権限確認
            if not self._ensure_icon_directory():
                return False
            
            # 絵文字を確実にクリア
            self.clear_shortcut_emoji(index)
            # 強制的に設定を再読み込み（キャッシュクリア）
            self.load_config()
            
            # 拡張子を取得
            _, ext = os.path.splitext(source_image_path)
            if not ext:
                ext = '.png'
            
            # 保存先のファイル名
            dest_filename = f"{index}{ext}"
            dest_path = os.path.join(self.icon_dir, dest_filename)
            
            # パスを正規化して比較
            source_normalized = os.path.normpath(os.path.abspath(source_image_path))
            dest_normalized = os.path.normpath(os.path.abspath(dest_path))
            
            # 同じファイルの場合はコピーしない
            if source_normalized == dest_normalized:
                # logging.info(f"アイコンは既に正しい場所にあります: {dest_path}")
                
                # 画像設定のタイムスタンプを記録（既存ファイルの場合も）
                timestamp = str(int(time.time()))
                if not self.config.has_section('ShortcutIcons'):
                    self.config.add_section('ShortcutIcons')
                self.config.set('ShortcutIcons', f'image_{index}_timestamp', timestamp)
                self.save_config()
                
                # UI更新シグナルを安全に発火
                self._emit_update_signal("画像設定/既存")
                
                return True
            
            # 既存の全アイコンファイルを削除
            self._clear_all_icon_files(index)
            
            # 新しいアイコンをコピー
            shutil.copy2(source_image_path, dest_path)
            
            # 権限を設定（読み取り専用にして保護）
            try:
                os.chmod(dest_path, 0o644)
            except:
                pass  # 権限設定に失敗しても継続
            
            # 画像設定のタイムスタンプを記録
            timestamp = str(int(time.time()))
            if not self.config.has_section('ShortcutIcons'):
                self.config.add_section('ShortcutIcons')
            self.config.set('ShortcutIcons', f'image_{index}_timestamp', timestamp)
            self.save_config()
            
            # logging.info(f"画像アイコンを設定: {index} -> {dest_path}")
            
            # UI更新シグナルを安全に発火
            self._emit_update_signal("画像設定")
            
            return True
            
        except PermissionError as e:
            logging.error(f"画像アイコン設定エラー（権限不足）: {e}")
            return False
        except Exception as e:
            logging.error(f"画像アイコン設定エラー: {e}", exc_info=True)
            return False
    
    def validate_shortcuts(self):
        """すべてのショートカットを検証し、存在しないファイルを修正"""
        invalid_shortcuts = []
        
        for i in range(1, self.max_shortcuts + 1):
            text_file = self.get_shortcut_text(i)
            if text_file and not self._is_text_file_valid(text_file):
                invalid_shortcuts.append((i, text_file))
        
        return invalid_shortcuts
    
    def get_all_shortcuts(self):
        """すべてのショートカット情報を取得"""
        shortcuts = {}
        
        for i in range(1, self.max_shortcuts + 1):
            text_file = self.get_shortcut_text(i)
            icon_path = self.get_shortcut_icon(i)
            
            shortcuts[i] = {
                'text_file': text_file,
                'icon_path': icon_path,
                'is_valid': self._is_text_file_valid(text_file)
            }
        
        return shortcuts
    
    def _is_text_file_valid(self, text_file):
        """テキストファイルが有効か確認"""
        if not text_file:
            return True  # 空の場合は有効とする
        
        # get_actual_file_pathを使用して実際のパスが見つかるかチェック
        return self.get_actual_file_path(text_file) is not None
    
    def set_shortcut_emoji(self, index, emoji):
        """ショートカットに絵文字を設定（強化版）"""
        try:
            if not isinstance(index, int) or index < 1 or index > self.max_shortcuts:
                raise ValueError(f"無効なインデックス: {index}")
            
            if not emoji or not isinstance(emoji, str):
                raise ValueError(f"無効な絵文字: {emoji}")
            
            # 既存の全画像ファイルを確実に削除
            if not self._clear_all_icon_files(index):
                logging.warning(f"画像ファイルの削除で問題が発生しましたが継続します: {index}")
            
            # 絵文字をShortcutIconsセクションに保存
            if not self.config.has_section('ShortcutIcons'):
                self.config.add_section('ShortcutIcons')
            
            # 絵文字とタイムスタンプを確実に保存
            timestamp = str(int(time.time()))
            self.config.set('ShortcutIcons', f'emoji_{index}', emoji)
            self.config.set('ShortcutIcons', f'emoji_{index}_timestamp', timestamp)
            
            # 強制保存と確認
            save_result = self.save_config()
            if not save_result:
                logging.error(f"絵文字設定の保存に失敗: {index}")
                return False
            
            # 設定が正しく保存されたか確認
            self.load_config()
            saved_emoji = self.config.get('ShortcutIcons', f'emoji_{index}', fallback=None)
            saved_timestamp = self.config.get('ShortcutIcons', f'emoji_{index}_timestamp', fallback=None)
            
            if saved_emoji == emoji and saved_timestamp == timestamp:
                # logging.info(f"絵文字アイコンを確実に設定: {index} -> {emoji} (ts: {timestamp})")
                return True
            else:
                logging.error(f"絵文字設定の確認に失敗: {index}, 保存={saved_emoji}, 期待={emoji}")
                return False
            
        except ValueError as e:
            logging.error(f"絵文字設定バリデーションエラー: {e}")
            return False
        except Exception as e:
            logging.error(f"絵文字アイコン設定エラー: {e}")
            import traceback
            logging.error(f"詳細エラー情報: {traceback.format_exc()}")
            return False
    
    def get_shortcut_emoji(self, index):
        """指定されたインデックスの絵文字を取得"""
        key = f"emoji_{index}"
        if self.config.has_option('ShortcutIcons', key):
            emoji = self.config.get('ShortcutIcons', key)
            # logging.debug(f"絵文字取得: {index} -> {emoji}")
            return emoji
        else:
            # logging.debug(f"絵文字未設定: {index}")
            pass
        return None
    
    def get_preferred_icon_type(self, index):
        """後から設定された方のアイコンタイプを取得（優先順位判定）"""
        emoji_timestamp_key = f"emoji_{index}_timestamp"
        image_timestamp_key = f"image_{index}_timestamp"
        
        emoji_timestamp = 0
        image_timestamp = 0
        
        # 絵文字のタイムスタンプを取得
        if self.config.has_option('ShortcutIcons', emoji_timestamp_key):
            try:
                emoji_timestamp = int(self.config.get('ShortcutIcons', emoji_timestamp_key))
            except:
                emoji_timestamp = 0
        
        # 画像のタイムスタンプを取得
        if self.config.has_option('ShortcutIcons', image_timestamp_key):
            try:
                image_timestamp = int(self.config.get('ShortcutIcons', image_timestamp_key))
            except:
                image_timestamp = 0
        
        # 絵文字が存在するかチェック
        has_emoji = self.get_shortcut_emoji(index) is not None
        # 画像が存在するかチェック
        has_image = self.get_shortcut_icon(index) is not None
        
        # logging.debug(f"優先順位判定 {index}: emoji_ts={emoji_timestamp}, image_ts={image_timestamp}, has_emoji={has_emoji}, has_image={has_image}")
        
        # 両方とも存在しない場合
        if not has_emoji and not has_image:
            return None
        
        # 片方だけ存在する場合
        if has_emoji and not has_image:
            return "emoji"
        if has_image and not has_emoji:
            return "image"
        
        # 両方存在する場合は、タイムスタンプで判定
        if emoji_timestamp > image_timestamp:
            # logging.debug(f"絵文字が後から設定されました: {index}")
            return "emoji"
        else:
            # logging.debug(f"画像が後から設定されました: {index}")
            return "image"
    
    def set_default_emojis(self):
        """デフォルトの絵文字を設定（初期状態のみ）"""
        default_emojis = {
            1: "📝",  # メモ
            2: "✨",   # キラキラ
            3: "📚",  # 本
            4: "📅",  # カレンダー
            5: "🎆",  # 花火
            6: "🌈",  # 虹
            7: "🌱",  # 芽
            8: "🌿",  # ハーブ
            9: "🌻",  # ひまわり
            10: "🌸" # 桜
        }
        
        # 初期状態の場合のみ設定（既存の設定がある場合は上書きしない）
        for index, emoji in default_emojis.items():
            # アイコンの存在確認でエラーが出ないように安全チェック
            try:
                has_emoji = self.get_shortcut_emoji(index) is not None
                has_icon = hasattr(self, 'icon_dir') and self.get_shortcut_icon(index) is not None
                if not has_emoji and not has_icon:
                    self.config.set('ShortcutIcons', f'emoji_{index}', emoji)
            except:
                # エラーが発生した場合はデフォルト絵文字を設定
                self.config.set('ShortcutIcons', f'emoji_{index}', emoji)
        
        self.save_config()
    
    def clear_shortcut_emoji(self, index):
        """指定されたインデックスの絵文字をクリア"""
        try:
            key = f"emoji_{index}"
            # 念のためセクションの存在確認
            if not self.config.has_section('ShortcutIcons'):
                self.config.add_section('ShortcutIcons')
                
            if self.config.has_option('ShortcutIcons', key):
                self.config.remove_option('ShortcutIcons', key)
                # logging.info(f"✂️ 絵文字をクリア: {index} (キー: {key})")
            else:
                # logging.info(f"🔍 絵文字は既にクリア済み: {index} (キー: {key})")
                pass
            
            # 絵文字タイムスタンプも削除
            timestamp_key = f"emoji_{index}_timestamp"
            if self.config.has_option('ShortcutIcons', timestamp_key):
                self.config.remove_option('ShortcutIcons', timestamp_key)
                # logging.info(f"✂️ 絵文字タイムスタンプをクリア: {timestamp_key}")
                
            # 即座に保存
            self.save_config()
            
            # 確認のため再読み込み
            self.load_config()
            
            # 確認ログ
            if self.config.has_option('ShortcutIcons', key):
                logging.warning(f"🚨 絵文字クリア失敗: {index} まだ存在しています")
                return False
            else:
                # logging.info(f"✅ 絵文字クリア確認: {index} 正常にクリアされました")
                return True
                
        except Exception as e:
            logging.error(f"絵文字クリアエラー: {e}")
            return False
    
    def clear_shortcut_completely(self, index):
        """指定されたインデックスのショートカットを完全にクリア（画像・絵文字・テキストファイル全て）"""
        try:
            # logging.info(f"🧹 ショートカット {index} を完全クリア開始")
            
            # 1. 画像ファイルとタイムスタンプをクリア
            if not self._clear_all_icon_files(index):
                logging.warning(f"画像ファイルクリアで問題発生: {index}")
            
            # 2. 絵文字とタイムスタンプをクリア
            if not self.clear_shortcut_emoji(index):
                logging.warning(f"絵文字クリアで問題発生: {index}")
            
            # 3. テキストファイル設定をクリア
            text_clear_result = self.set_shortcut_text(index, None)
            if not text_clear_result:
                logging.warning(f"テキストファイルクリアで問題発生: {index}")
            
            # 4. 設定を保存
            self.save_config()
            
            # 5. UI更新シグナルを安全に発火
            self._emit_update_signal("完全クリア")
            
            # logging.info(f"✅ ショートカット {index} の完全クリアが完了しました")
            return True
            
        except Exception as e:
            logging.error(f"ショートカット完全クリアエラー: {e}")
            return False
    
    def _ensure_icon_directory(self):
        """アイコンディレクトリの確実な作成と権限確認"""
        try:
            os.makedirs(self.icon_dir, exist_ok=True)
            
            # 権限テスト用のテンポラリファイル作成
            test_file = os.path.join(self.icon_dir, '.test_write')
            with open(test_file, 'w') as f:
                f.write('test')
            os.remove(test_file)
            
            # logging.info(f"アイコンディレクトリ確認完了: {self.icon_dir}")
            return True
        except Exception as e:
            logging.error(f"アイコンディレクトリ作成エラー: {e}")
            return False
    
    def _clear_all_icon_files(self, index):
        """指定されたインデックスの全画像ファイルを削除"""
        try:
            for old_ext in ['.png', '.jpg', '.jpeg', '.bmp', '.gif']:
                old_path = os.path.join(self.icon_dir, f"{index}{old_ext}")
                if os.path.exists(old_path):
                    os.remove(old_path)
                    # logging.info(f"画像ファイルを削除: {old_path}")
            
            # 画像タイムスタンプも削除
            timestamp_key = f"image_{index}_timestamp"
            if self.config.has_option('ShortcutIcons', timestamp_key):
                self.config.remove_option('ShortcutIcons', timestamp_key)
                # logging.info(f"✂️ 画像タイムスタンプをクリア: {timestamp_key}")
                self.save_config()
            
            return True
        except Exception as e:
            logging.error(f"画像ファイル削除エラー: {e}")
            return False
    
    def _emit_update_signal(self, operation_name):
        """UI更新シグナルを安全に発火（重複防止機能付き）"""
        try:
            # 更新中フラグチェック
            if self._update_in_progress:
                # logging.debug(f"UI更新が進行中のため、シグナル発火をスキップ: {operation_name}")
                return
            
            # シグナルが利用可能かチェック
            if not hasattr(self, 'shortcuts_updated'):
                # logging.debug(f"shortcuts_updatedシグナルが利用できません: {operation_name}")
                return
            
            # 更新フラグを設定
            self._update_in_progress = True
            
            try:
                # logging.info(f"🔄 shortcuts_updated シグナルを発火します（{operation_name}）")
                self.shortcuts_updated.emit()
                # logging.info(f"✅ shortcuts_updated シグナル発火完了（{operation_name}）")
            finally:
                # 更新フラグをリセット
                self._update_in_progress = False
                
        except Exception as e:
            logging.error(f"UI更新シグナル発火エラー（{operation_name}）: {e}")
            self._update_in_progress = False



class ShortcutSettingsDialog(QDialog):
    """ショートカット設定ダイアログ"""
    
    shortcuts_updated = pyqtSignal()  # 設定が更新されたときのシグナル
    
    def __init__(self, parent, shortcut_manager):
        super().__init__(parent)
        self.shortcut_manager = shortcut_manager
        self.main_window = parent  # メインウィンドウへの参照を保持
        self.setWindowTitle("リングランチャー設定")
        self.setModal(True)
        # このダイアログが閉じられてもアプリケーションを終了させない
        self.setAttribute(Qt.WA_QuitOnClose, False)
        # 最前面に表示
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        self.resize(900, 600)
        
        self.setup_ui()
        self.load_current_settings()
    
    def setup_ui(self):
        """UI設定"""
        layout = QVBoxLayout()
        
        # 説明ラベル
        info_label = QLabel("各ショートカットにテキストファイルとアイコンを設定してください:")
        layout.addWidget(info_label)
        
        # スクロールエリア
        scroll_area = QScrollArea()
        scroll_widget = QWidget()
        scroll_layout = QGridLayout(scroll_widget)
        
        # ヘッダー
        scroll_layout.addWidget(QLabel("番号"), 0, 0)
        scroll_layout.addWidget(QLabel("ショートカットキー"), 0, 1)
        scroll_layout.addWidget(QLabel("アイコン"), 0, 2)
        scroll_layout.addWidget(QLabel("テキストファイル"), 0, 3)
        scroll_layout.addWidget(QLabel("画像アイコン"), 0, 4)
        scroll_layout.addWidget(QLabel("絵文字アイコン"), 0, 5)
        scroll_layout.addWidget(QLabel("テキスト設定"), 0, 6)
        
        self.shortcut_widgets = {}
        
        for i in range(1, self.shortcut_manager.max_shortcuts + 1):
            row = i
            
            # 番号
            num_label = QLabel(str(i))
            num_label.setAlignment(Qt.AlignCenter)
            scroll_layout.addWidget(num_label, row, 0)
            
            # ショートカットキー表示
            shortcut_key_label = QLabel(f"Ctrl+{i}")
            shortcut_key_label.setAlignment(Qt.AlignCenter)
            shortcut_key_label.setStyleSheet("font-weight: bold; color: #0066cc;")
            scroll_layout.addWidget(shortcut_key_label, row, 1)
            
            # アイコン表示
            icon_label = QLabel()
            icon_label.setFixedSize(48, 48)
            icon_label.setScaledContents(True)
            icon_label.setAlignment(Qt.AlignCenter)
            scroll_layout.addWidget(icon_label, row, 2)
            
            # テキストファイル表示
            text_label = QLabel("未設定")
            text_label.setMinimumWidth(200)  # 最小幅を200pxに設定
            text_label.setWordWrap(True)     # 長いファイル名の折り返し許可
            scroll_layout.addWidget(text_label, row, 3)
            
            # 画像アイコン選択ボタン
            icon_button = QPushButton("画像選択")
            icon_button.clicked.connect(lambda checked, idx=i: self.select_icon(idx))
            scroll_layout.addWidget(icon_button, row, 4)
            
            # 絵文字アイコン選択ボタン
            emoji_button = QPushButton("絵文字選択")
            emoji_button.clicked.connect(lambda checked, idx=i: self.select_emoji(idx))
            scroll_layout.addWidget(emoji_button, row, 5)
            
            # テキスト選択ボタン
            text_button = QPushButton("テキスト選択")
            text_button.clicked.connect(lambda checked, idx=i: self.select_text(idx))
            scroll_layout.addWidget(text_button, row, 6)
            
            # 完全クリアボタン
            clear_button = QPushButton("完全クリア")
            clear_button.clicked.connect(lambda checked, idx=i: self.clear_shortcut(idx))
            clear_button.setToolTip("テキスト・絵文字・画像の全設定をクリア")
            scroll_layout.addWidget(clear_button, row, 7)
            
            self.shortcut_widgets[i] = {
                'shortcut_key_label': shortcut_key_label,
                'icon_label': icon_label,
                'text_label': text_label
            }
        
        scroll_area.setWidget(scroll_widget)
        layout.addWidget(scroll_area)
        
        # ボタン
        button_layout = QHBoxLayout()
        ok_button = QPushButton("OK")
        ok_button.clicked.connect(self.accept)
        cancel_button = QPushButton("キャンセル")
        cancel_button.clicked.connect(self.reject)
        
        button_layout.addWidget(ok_button)
        button_layout.addWidget(cancel_button)
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def load_current_settings(self):
        """現在の設定を読み込んで表示"""
        try:
            shortcuts = self.shortcut_manager.get_all_shortcuts()
            
            for i, info in shortcuts.items():
                if i not in self.shortcut_widgets:
                    continue  # ウィジェットが存在しない場合はスキップ
                    
                widgets = self.shortcut_widgets[i]
                
                # ウィジェットの有効性確認
                if not widgets or not widgets.get('icon_label'):
                    continue
                
                # アイコン表示（preferred_typeによる優先順位対応）
                emoji = self.shortcut_manager.get_shortcut_emoji(i)
                preferred_type = self.shortcut_manager.get_preferred_icon_type(i)
                
                if preferred_type == "emoji" and emoji:
                    # 絵文字が優先される場合
                    widgets['icon_label'].clear()
                    widgets['icon_label'].setText(emoji)
                    widgets['icon_label'].setStyleSheet("font-size: 24px;")
                elif preferred_type == "image" and info['icon_path'] and os.path.exists(info['icon_path']):
                    # 画像が優先される場合
                    try:
                        pixmap = QPixmap(info['icon_path'])
                        if not pixmap.isNull():
                            scaled_pixmap = pixmap.scaled(32, 32, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                            widgets['icon_label'].setPixmap(scaled_pixmap)
                            widgets['icon_label'].setStyleSheet("")
                        else:
                            widgets['icon_label'].clear()
                            widgets['icon_label'].setText("エラー")
                            widgets['icon_label'].setStyleSheet("color: red;")
                    except Exception as e:
                        logging.warning(f"画像読み込みエラー: {info['icon_path']}, {e}")
                        widgets['icon_label'].clear()
                        widgets['icon_label'].setText("エラー")
                        widgets['icon_label'].setStyleSheet("color: red;")
                else:
                    # 何もない場合
                    widgets['icon_label'].clear()
                    widgets['icon_label'].setText("なし")
                    widgets['icon_label'].setStyleSheet("")
                
                # テキストファイル表示
                if info['text_file']:
                    if info['is_valid']:
                        widgets['text_label'].setText(os.path.basename(info['text_file']))
                        widgets['text_label'].setStyleSheet("")
                    else:
                        widgets['text_label'].setText(f"❌ {os.path.basename(info['text_file'])}")
                        widgets['text_label'].setStyleSheet("color: red;")
                else:
                    widgets['text_label'].setText("未設定")
                    widgets['text_label'].setStyleSheet("")
        except Exception as e:
            logging.error(f"設定読み込みエラー: {e}")
    
    def select_icon(self, index):
        """アイコン選択"""
        # 初期フォルダを設定
        if getattr(sys, 'frozen', False):
            # ビルド環境
            images_dir = os.path.join(os.path.dirname(sys.executable), 'images')
        else:
            # 開発環境
            images_dir = resource_path('images')
        
        # imagesフォルダが存在しない場合はbase_dirを使用
        if not os.path.exists(images_dir):
            images_dir = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) else os.path.dirname(__file__)
        
        # Create a custom QFileDialog with WindowStaysOnTopHint
        dialog = QFileDialog(self)
        dialog.setWindowFlags(dialog.windowFlags() | Qt.WindowStaysOnTopHint)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilter("画像ファイル (*.png *.jpg *.jpeg *.bmp *.gif);;すべてのファイル (*)")
        dialog.setWindowTitle(f"ショートカット {index} のアイコンを選択")
        dialog.setDirectory(images_dir)
        
        if dialog.exec_() == QFileDialog.Accepted:
            file_paths = dialog.selectedFiles()
            filename = file_paths[0] if file_paths else None
        else:
            filename = None
        
        if filename:
            try:
                if self.shortcut_manager.set_shortcut_icon(index, filename):
                    # logging.info(f"アイコンを設定しました: ショートカット {index}")
                    # 設定を更新
                    try:
                        self.load_current_settings()
                    except Exception as e:
                        logging.warning(f"設定画面更新でエラー（無視）: {e}")
                    
                    # メインウィンドウに更新を通知
                    # logging.info("🔄 shortcuts_updated シグナルを発火します（画像設定）")
                    self.shortcuts_updated.emit()
                    # logging.info("✅ shortcuts_updated シグナル発火完了（画像設定）")
                    
                    # 直接メインウィンドウを更新（確実性のため）
                    if hasattr(self, 'main_window') and hasattr(self.main_window, 'refresh_shortcut_buttons_only'):
                        # logging.info("🔧 メインウィンドウを直接更新（画像設定）")
                        self.main_window.refresh_shortcut_buttons_only()
                    else:
                        logging.warning(f"🚨 メインウィンドウの参照がありません: main_window={hasattr(self, 'main_window')}")
                else:
                    logging.warning(f"アイコンの設定に失敗しました: ショートカット {index}")
            except Exception as e:
                logging.error(f"アイコン設定処理エラー: {e}")
    
    def select_text(self, index):
        """テキストファイル選択"""
        texts_dir = self.shortcut_manager.texts_dir
        # Create a custom QFileDialog with WindowStaysOnTopHint
        dialog = QFileDialog(self)
        dialog.setWindowFlags(dialog.windowFlags() | Qt.WindowStaysOnTopHint)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilter("テキストファイル (*.txt);;すべてのファイル (*)")
        dialog.setWindowTitle(f"ショートカット {index} のテキストファイルを選択")
        dialog.setDirectory(texts_dir)
        
        if dialog.exec_() == QFileDialog.Accepted:
            file_paths = dialog.selectedFiles()
            filename = file_paths[0] if file_paths else None
        else:
            filename = None
        
        if filename:
            # 相対パスに変換
            if filename.startswith(texts_dir):
                relative_path = os.path.relpath(filename, texts_dir)
            else:
                relative_path = filename
            
            # logging.info(f"テキストファイルを選択: {filename} -> {relative_path}")
            self.shortcut_manager.set_shortcut_text(index, relative_path)
            try:
                self.load_current_settings()
            except Exception as e:
                logging.warning(f"設定画面更新でエラー（無視）: {e}")
            
            # メインウィンドウに更新を通知
            # logging.info("🔄 shortcuts_updated シグナルを発火します（テキスト設定）")
            self.shortcuts_updated.emit()
            # logging.info("✅ shortcuts_updated シグナル発火完了（テキスト設定）")
            
            # 直接メインウィンドウを更新（確実性のため）
            if hasattr(self, 'main_window') and hasattr(self.main_window, 'refresh_shortcut_buttons_only'):
                # logging.info("🔧 メインウィンドウを直接更新（テキスト設定）")
                self.main_window.refresh_shortcut_buttons_only()
    
    def select_emoji(self, index):
        """絵文字選択（カスタムダイアログ）"""
        # カスタムダイアログを作成
        dialog = EmojiSelectionDialog(self, shortcut_index=index, for_memo_insert=False)
        
        if dialog.exec_() == QDialog.Accepted:
            selected_emoji = dialog.get_selected_emoji()
            ok = selected_emoji is not None
            text = selected_emoji
        else:
            text = None
            ok = False
        
        if ok and text:
            if self.shortcut_manager.set_shortcut_emoji(index, text):
                # logging.info(f"絵文字を設定しました: ショートカット {index} = {text}")
                try:
                    self.load_current_settings()
                except Exception as e:
                    logging.warning(f"設定画面更新でエラー（無視）: {e}")
                
                # メインウィンドウに更新を通知
                # logging.info("🔄 shortcuts_updated シグナルを発火します（絵文字設定）")
                self.shortcuts_updated.emit()
                # logging.info("✅ shortcuts_updated シグナル発火完了（絵文字設定）")
                
                # 直接メインウィンドウを更新（確実性のため）
                if hasattr(self, 'main_window') and hasattr(self.main_window, 'refresh_shortcut_buttons_only'):
                    # logging.info("🔧 メインウィンドウを直接更新（絵文字設定）")
                    self.main_window.refresh_shortcut_buttons_only()
            else:
                logging.warning(f"絵文字の設定に失敗しました: ショートカット {index}")

    def clear_shortcut(self, index):
        """ショートカットを完全にクリア（画像・絵文字・テキストファイル全て）"""
        try:
            # 確認ダイアログを表示
            reply = QMessageBox.question(
                self, 
                "ショートカット完全クリア確認",
                f"ショートカット {index} の設定を完全にクリアしますか？\n\n"
                f"以下の内容が削除されます：\n"
                f"• テキストファイル設定\n"
                f"• 絵文字アイコン\n"
                f"• 画像アイコン\n"
                f"• 全ての関連設定\n\n"
                f"この操作は元に戻せません。",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No
            )
            
            if reply == QMessageBox.Yes:
                # logging.info(f"🧹 設定ダイアログからショートカット {index} を完全クリア")
                
                # 完全クリア実行
                result = self.shortcut_manager.clear_shortcut_completely(index)
                
                if result:
                    # logging.info(f"✅ ショートカット {index} の完全クリアに成功")
                    # 現在の設定を再読み込み（UI更新）
                    self.load_current_settings()
                    
                    # メインウィンドウに更新を通知
                    # logging.info("🔄 shortcuts_updated シグナルを発火します（完全クリア）")
                    self.shortcuts_updated.emit()
                    # logging.info("✅ shortcuts_updated シグナル発火完了（完全クリア）")
                    
                    # 成功メッセージ
                    QMessageBox.information(
                        self,
                        "クリア完了",
                        f"ショートカット {index} の設定を完全にクリアしました。"
                    )
                else:
                    logging.error(f"❌ ショートカット {index} の完全クリアに失敗")
                    QMessageBox.warning(
                        self,
                        "クリア失敗",
                        f"ショートカット {index} のクリアに失敗しました。"
                    )
            else:
                # logging.info(f"🚫 ショートカット {index} のクリアがキャンセルされました")
                pass
                
        except Exception as e:
            logging.error(f"設定ダイアログからの完全クリアエラー: {e}")
            QMessageBox.critical(
                self,
                "エラー",
                f"クリア処理中にエラーが発生しました：\n{str(e)}"
            )
            import traceback
            traceback.print_exc()
    
    def accept(self):
        """OKボタン押下時"""
        try:
            # 最終的な保存を確実に行う
            self.shortcut_manager.save_config()
            # logging.info("設定ダイアログ終了時に設定を保存しました")
            
            self.shortcuts_updated.emit()
            super().accept()
        except Exception as e:
            logging.error(f"設定保存エラー: {e}")
            import traceback
            traceback.print_exc()
    
    def reject(self):
        """キャンセルボタン押下時"""
        try:
            # logging.info("🔧 ShortcutSettingsDialog: reject()が呼ばれました")
            super().reject()
            # logging.info("🔧 ShortcutSettingsDialog: super().reject()完了")
        except Exception as e:
            logging.error(f"🔧 ShortcutSettingsDialog reject()エラー: {e}")
            import traceback
            traceback.print_exc()
    
    def closeEvent(self, event):
        """ダイアログが閉じられる時"""
        try:
            # logging.info("🔧 ShortcutSettingsDialog: closeEvent()が呼ばれました")
            super().closeEvent(event)
            # logging.info("🔧 ShortcutSettingsDialog: super().closeEvent()完了")
        except Exception as e:
            logging.error(f"🔧 ShortcutSettingsDialog closeEvent()エラー: {e}")
            import traceback
            traceback.print_exc()


if __name__ == "__main__":
    """テスト用のメイン関数"""
    import sys
    from PyQt5.QtWidgets import QApplication
    
    app = QApplication(sys.argv)
    
    # テスト用の設定ファイル
    config_file = os.path.join(os.path.dirname(__file__), 'config.ini')
    
    # マネージャーを作成
    manager = ShortcutManager(config_file)
    
    # ダイアログを表示
    dialog = ShortcutSettingsDialog(None, manager)
    dialog.exec_()
    
    # 結果を表示
    pass  # デバッグ情報を削除
    
    sys.exit(0)