#!/usr/bin/env python3
"""
会话管理模块
管理角色创建会话、临时文件和用户确认流程
"""

import json
import uuid
import time
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Any
from datetime import datetime
import logging
from dataclasses import dataclass, asdict, field
from enum import Enum

logger = logging.getLogger(__name__)


class SessionStatus(Enum):
    """会话状态"""
    CREATED = "created"          # 已创建
    TEMP_SAVED = "temp_saved"    # 临时文件已保存
    VALIDATED = "validated"      # 已校验
    CONFLICTS_DETECTED = "conflicts_detected"  # 检测到冲突
    USER_REVIEWED = "user_reviewed"  # 用户已审核
    CONFIRMED = "confirmed"      # 用户已确认
    MOVED = "moved"              # 已移动到最终目录
    CANCELLED = "cancelled"      # 已取消
    ERROR = "error"              # 错误状态


@dataclass
class SessionConfig:
    """会话配置"""
    workspace: str
    character_name: str
    template_type: str = "standard"
    auto_cleanup: bool = True
    max_temp_age_hours: int = 24
    enable_validation: bool = True
    enable_conflict_check: bool = True
    require_confirmation: bool = True


@dataclass
class SessionData:
    """会话数据"""
    session_id: str
    config: SessionConfig
    status: SessionStatus = SessionStatus.CREATED
    created_at: float = field(default_factory=time.time)
    updated_at: float = field(default_factory=time.time)
    temp_file_path: Optional[str] = None
    final_file_path: Optional[str] = None
    conflicts: List[Dict] = field(default_factory=list)
    validation_results: List[Dict] = field(default_factory=list)
    user_notes: str = ""
    metadata: Dict[str, Any] = field(default_factory=dict)


class ProfileSession:
    """角色创建会话管理器"""

    def __init__(self, config: SessionConfig):
        """初始化会话

        Args:
            config: 会话配置
        """
        self.config = config
        self.session_id = str(uuid.uuid4())[:8]
        self.session_data = SessionData(
            session_id=self.session_id,
            config=config
        )
        self.workspace_path = Path(config.workspace).resolve()
        self.session_file = self.workspace_path / ".sessions" / f"session_{self.session_id}.json"

        # 确保会话目录存在
        self.session_file.parent.mkdir(parents=True, exist_ok=True)

        logger.info(f"创建会话: {self.session_id} - {config.character_name}")

    def save_temp_profile(self, content: str) -> Optional[Path]:
        """保存临时档案

        Args:
            content: 档案内容

        Returns:
            临时文件路径
        """
        try:
            from lore_bible_manager import LoreBibleManager
            manager = LoreBibleManager(self.config.workspace)

            # 确保目录存在
            manager.create_directory_structure()

            # 保存临时文件
            temp_path = manager.save_temp_profile(
                content=content,
                character_name=self.config.character_name,
                session_id=self.session_id
            )

            if temp_path:
                self.session_data.temp_file_path = str(temp_path)
                self.session_data.status = SessionStatus.TEMP_SAVED
                self._update_timestamp()
                self._save_session_data()

                logger.info(f"临时档案已保存: {temp_path}")
                return temp_path

        except Exception as e:
            logger.error(f"保存临时档案失败: {e}")
            self.session_data.status = SessionStatus.ERROR
            self.session_data.metadata["error"] = str(e)
            self._save_session_data()

        return None

    def validate_and_check_conflicts(self, character_data: Dict) -> Tuple[bool, List[Dict]]:
        """验证角色并检查冲突

        Args:
            character_data: 角色数据

        Returns:
            (是否有效, 冲突列表)
        """
        if not self.config.enable_validation and not self.config.enable_conflict_check:
            return True, []

        try:
            from lore_bible_manager import LoreBibleManager
            from conflict_detector import ConflictDetector, ConflictSeverity

            manager = LoreBibleManager(self.config.workspace)
            detector = ConflictDetector()

            # 获取现有角色
            existing_characters = manager.scan_existing_characters()

            # 设置角色索引
            detector.set_character_index({
                "characters": existing_characters,
                "total_count": len(existing_characters)
            })

            # 检测冲突
            conflicts = []
            if self.config.enable_conflict_check:
                conflicts = detector.detect_conflicts(character_data, existing_characters)

            # 验证角色
            is_valid = True
            if self.config.enable_validation:
                valid, validation_conflicts = detector.validate_character(character_data)
                if not valid:
                    is_valid = False
                conflicts.extend(validation_conflicts)

            # 更新会话数据
            self.session_data.conflicts = [asdict(conflict) if hasattr(conflict, '__dataclass_fields__') else conflict
                                          for conflict in conflicts]
            self.session_data.validation_results = [{"valid": is_valid}]

            if conflicts:
                self.session_data.status = SessionStatus.CONFLICTS_DETECTED
            else:
                self.session_data.status = SessionStatus.VALIDATED

            self._update_timestamp()
            self._save_session_data()

            logger.info(f"验证完成: 有效={is_valid}, 冲突数={len(conflicts)}")
            return is_valid, conflicts

        except Exception as e:
            logger.error(f"验证失败: {e}")
            self.session_data.status = SessionStatus.ERROR
            self.session_data.metadata["error"] = str(e)
            self._save_session_data()
            return False, []

    def present_to_user(self, conflicts: List[Dict]) -> bool:
        """向用户展示结果并获取反馈

        Args:
            conflicts: 冲突列表

        Returns:
            用户是否确认继续
        """
        print(f"\n{'='*60}")
        print(f"角色创建会话: {self.session_id}")
        print(f"角色名称: {self.config.character_name}")
        print(f"工作目录: {self.config.workspace}")
        print(f"{'='*60}\n")

        # 显示临时文件位置
        if self.session_data.temp_file_path:
            print(f"临时档案: {self.session_data.temp_file_path}")
            print("")

        # 显示冲突和警告
        if conflicts:
            print("⚠️  检测到以下问题:")

            # 按严重程度分组
            errors = [c for c in conflicts if c.get("severity") == "error"]
            warnings = [c for c in conflicts if c.get("severity") == "warning"]
            infos = [c for c in conflicts if c.get("severity") == "info"]

            if errors:
                print("\n❌ 错误:")
                for i, conflict in enumerate(errors, 1):
                    print(f"  {i}. {conflict.get('message', '未知错误')}")
                    if conflict.get('suggested_fixes'):
                        print(f"     建议: {conflict['suggested_fixes'][0]}")

            if warnings:
                print("\n⚠️  警告:")
                for i, conflict in enumerate(warnings, 1):
                    print(f"  {i}. {conflict.get('message', '未知警告')}")

            if infos:
                print("\nℹ️  提示:")
                for i, conflict in enumerate(infos, 1):
                    print(f"  {i}. {conflict.get('message', '未知提示')}")

            print("")

            # 询问用户
            if errors:
                print("存在错误，无法继续。请修改角色设定后重试。")
                return False
            else:
                response = input("是否继续创建角色? (y/n): ").strip().lower()
                if response == 'y':
                    notes = input("请输入备注（可选，直接回车跳过）: ").strip()
                    if notes:
                        self.session_data.user_notes = notes
                    return True
                else:
                    return False
        else:
            print("✓ 未检测到冲突")
            print("")

            if self.config.require_confirmation:
                response = input("是否创建角色? (y/n): ").strip().lower()
                if response == 'y':
                    notes = input("请输入备注（可选，直接回车跳过）: ").strip()
                    if notes:
                        self.session_data.user_notes = notes
                    return True
                else:
                    return False
            else:
                return True

    def confirm_and_move(self) -> Optional[Path]:
        """用户确认后移动到最终目录

        Returns:
            最终文件路径
        """
        try:
            if not self.session_data.temp_file_path:
                logger.error("临时文件路径不存在")
                return None

            temp_path = Path(self.session_data.temp_file_path)
            if not temp_path.exists():
                logger.error(f"临时文件不存在: {temp_path}")
                return None

            from lore_bible_manager import LoreBibleManager
            manager = LoreBibleManager(self.config.workspace)

            # 移动文件
            final_path = manager.move_to_characters(temp_path, self.config.character_name)

            if final_path:
                self.session_data.final_file_path = str(final_path)
                self.session_data.status = SessionStatus.MOVED
                self._update_timestamp()
                self._save_session_data()

                logger.info(f"档案已移动到: {final_path}")
                return final_path

        except Exception as e:
            logger.error(f"移动档案失败: {e}")
            self.session_data.status = SessionStatus.ERROR
            self.session_data.metadata["error"] = str(e)
            self._save_session_data()

        return None

    def cancel(self) -> bool:
        """取消会话并清理临时文件

        Returns:
            是否成功取消
        """
        try:
            # 删除临时文件
            if self.session_data.temp_file_path:
                temp_path = Path(self.session_data.temp_file_path)
                if temp_path.exists():
                    temp_path.unlink()
                    logger.info(f"已删除临时文件: {temp_path}")

            # 更新状态
            self.session_data.status = SessionStatus.CANCELLED
            self._update_timestamp()
            self._save_session_data()

            logger.info(f"会话已取消: {self.session_id}")
            return True

        except Exception as e:
            logger.error(f"取消会话失败: {e}")
            return False

    def cleanup(self) -> bool:
        """清理会话文件

        Returns:
            是否成功清理
        """
        try:
            if self.session_file.exists():
                self.session_file.unlink()
                logger.info(f"已删除会话文件: {self.session_file}")

            # 清理旧的临时文件
            if self.config.auto_cleanup:
                from lore_bible_manager import LoreBibleManager
                manager = LoreBibleManager(self.config.workspace)
                cleaned = manager.cleanup_old_temp_files(self.config.max_temp_age_hours)
                logger.info(f"清理了 {cleaned} 个临时文件")

            return True

        except Exception as e:
            logger.error(f"清理失败: {e}")
            return False

    def get_status_report(self) -> Dict:
        """获取状态报告

        Returns:
            状态报告字典
        """
        report = {
            "session_id": self.session_id,
            "character_name": self.config.character_name,
            "status": self.session_data.status.value,
            "created_at": datetime.fromtimestamp(self.session_data.created_at).isoformat(),
            "updated_at": datetime.fromtimestamp(self.session_data.updated_at).isoformat(),
            "temp_file": self.session_data.temp_file_path,
            "final_file": self.session_data.final_file_path,
            "conflict_count": len(self.session_data.conflicts),
            "user_notes": self.session_data.user_notes,
            "workspace": self.config.workspace
        }

        # 添加冲突摘要
        if self.session_data.conflicts:
            error_count = len([c for c in self.session_data.conflicts if c.get("severity") == "error"])
            warning_count = len([c for c in self.session_data.conflicts if c.get("severity") == "warning"])
            report["conflict_summary"] = {
                "errors": error_count,
                "warnings": warning_count
            }

        return report

    def _save_session_data(self):
        """保存会话数据到文件"""
        try:
            data = asdict(self.session_data)
            # 将枚举转换为字符串
            data["status"] = self.session_data.status.value

            with open(self.session_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2, default=str)

        except Exception as e:
            logger.error(f"保存会话数据失败: {e}")

    def _update_timestamp(self):
        """更新时间戳"""
        self.session_data.updated_at = time.time()

    @classmethod
    def load_session(cls, session_id: str, workspace: str) -> Optional["ProfileSession"]:
        """加载现有会话

        Args:
            session_id: 会话ID
            workspace: 工作目录

        Returns:
            会话实例，加载失败返回None
        """
        try:
            workspace_path = Path(workspace).resolve()
            session_file = workspace_path / ".sessions" / f"session_{session_id}.json"

            if not session_file.exists():
                logger.error(f"会话文件不存在: {session_file}")
                return None

            with open(session_file, 'r', encoding='utf-8') as f:
                data = json.load(f)

            # 重建配置
            config_data = data.get("config", {})
            config = SessionConfig(**config_data)

            # 创建会话实例
            session = cls(config)
            session.session_id = session_id
            session.session_file = session_file

            # 重建会话数据
            session.session_data = SessionData(
                session_id=session_id,
                config=config,
                status=SessionStatus(data.get("status", "created")),
                created_at=data.get("created_at", time.time()),
                updated_at=data.get("updated_at", time.time()),
                temp_file_path=data.get("temp_file_path"),
                final_file_path=data.get("final_file_path"),
                conflicts=data.get("conflicts", []),
                validation_results=data.get("validation_results", []),
                user_notes=data.get("user_notes", ""),
                metadata=data.get("metadata", {})
            )

            logger.info(f"已加载会话: {session_id}")
            return session

        except Exception as e:
            logger.error(f"加载会话失败: {e}")
            return None

    @classmethod
    def list_sessions(cls, workspace: str, active_only: bool = True) -> List[Dict]:
        """列出所有会话

        Args:
            workspace: 工作目录
            active_only: 是否只显示活动会话

        Returns:
            会话列表
        """
        sessions = []
        workspace_path = Path(workspace).resolve()
        sessions_dir = workspace_path / ".sessions"

        if not sessions_dir.exists():
            return sessions

        for session_file in sessions_dir.glob("session_*.json"):
            try:
                with open(session_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)

                session_id = session_file.stem.replace("session_", "")
                status = data.get("status", "created")

                # 如果只显示活动会话，跳过已完成/取消的
                if active_only and status in ["moved", "cancelled", "error"]:
                    continue

                sessions.append({
                    "session_id": session_id,
                    "character_name": data.get("config", {}).get("character_name", "未知"),
                    "status": status,
                    "created_at": data.get("created_at"),
                    "temp_file": data.get("temp_file_path"),
                    "final_file": data.get("final_file_path")
                })

            except Exception as e:
                logger.warning(f"读取会话文件失败 {session_file}: {e}")

        # 按创建时间排序
        sessions.sort(key=lambda x: x.get("created_at", 0), reverse=True)
        return sessions


def main():
    """命令行测试"""
    import sys

    if len(sys.argv) < 3:
        print("用法: python profile_session.py <工作目录> <角色姓名>")
        print("可选参数: --template <模板类型> --no-confirm")
        sys.exit(1)

    workspace = sys.argv[1]
    character_name = sys.argv[2]

    # 解析可选参数
    template_type = "standard"
    require_confirmation = True

    i = 3
    while i < len(sys.argv):
        if sys.argv[i] == "--template" and i + 1 < len(sys.argv):
            template_type = sys.argv[i + 1]
            i += 2
        elif sys.argv[i] == "--no-confirm":
            require_confirmation = False
            i += 1
        else:
            i += 1

    # 创建配置
    config = SessionConfig(
        workspace=workspace,
        character_name=character_name,
        template_type=template_type,
        require_confirmation=require_confirmation
    )

    # 创建会话
    session = ProfileSession(config)
    print(f"创建会话: {session.session_id}")

    # 模拟角色数据
    character_data = {
        "name": character_name,
        "age": "25",
        "gender": "男",
        "occupation": "剑士",
        "role": "主角"
    }

    # 模拟档案内容
    profile_content = f"""# {character_name} - 角色档案

## 基本信息
- **姓名**: {character_name}
- **年龄**: 25
- **性别**: 男
- **职业/身份**: 剑士
- **故事中的角色**: 主角
"""

    # 保存临时档案
    temp_path = session.save_temp_profile(profile_content)
    if temp_path:
        print(f"临时档案已保存: {temp_path}")

    # 验证和冲突检测
    is_valid, conflicts = session.validate_and_check_conflicts(character_data)
    print(f"验证结果: {'有效' if is_valid else '无效'}, 冲突数: {len(conflicts)}")

    # 展示给用户
    if session.present_to_user(conflicts):
        print("用户确认继续")

        # 确认并移动
        final_path = session.confirm_and_move()
        if final_path:
            print(f"档案已保存到: {final_path}")
        else:
            print("保存失败")
    else:
        print("用户取消")
        session.cancel()

    # 显示状态报告
    report = session.get_status_report()
    print(f"\n会话状态: {report['status']}")
    print(f"最终文件: {report['final_file'] or '无'}")


if __name__ == "__main__":
    main()