#!/usr/bin/env python3
"""
정보 관리 시스템 - 검색 엔진
제이회장님의 AI 비서를 위한 토큰 효율적 검색 시스템
"""

import json
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Tuple


class MemorySearchEngine:
    """메모리 검색 엔진 - index.json 활용"""

    def __init__(self, memory_path: str = None):
        """초기화"""
        if memory_path is None:
            # 기본 경로: /home/jay/workspace/memory/
            memory_path = Path(__file__).parent
        self.memory_path = Path(memory_path)
        self.index_path = self.memory_path / "index.json"
        self.index = None
        self.load_index()

    def load_index(self) -> bool:
        """index.json 로드"""
        try:
            if self.index_path.exists():
                with open(self.index_path, "r", encoding="utf-8") as f:
                    self.index = json.load(f)
                return True
            else:
                print(f"⚠️ index.json이 없습니다: {self.index_path}")
                self.index = {"documents": {}, "keywords": {}, "participants": {}}
                return False
        except Exception as e:
            print(f"❌ index.json 로드 실패: {e}")
            self.index = {"documents": {}, "keywords": {}, "participants": {}}
            return False

    def save_index(self) -> bool:
        """index.json 저장"""
        try:
            # lastUpdated 업데이트
            self.index["lastUpdated"] = datetime.now().isoformat() + "Z"

            with open(self.index_path, "w", encoding="utf-8") as f:
                json.dump(self.index, f, ensure_ascii=False, indent=2)
            return True
        except Exception as e:
            print(f"❌ index.json 저장 실패: {e}")
            return False

    def search_by_keyword(self, keyword: str) -> List[Dict]:
        """
        키워드로 검색

        Args:
            keyword: 검색할 키워드

        Returns:
            검색 결과 리스트 (doc_id, title, summary, path)
        """
        results = []

        if not self.index:
            return results

        # keywords 섹션에서 검색
        keywords = self.index.get("keywords", {})

        # 정확한 매칭
        if keyword in keywords:
            doc_ids = keywords[keyword]
            for doc_id in doc_ids:
                doc = self.index["documents"].get(doc_id)
                if doc:
                    results.append(
                        {
                            "id": doc_id,
                            "title": doc.get("title", "제목 없음"),
                            "summary": doc.get("summary", ""),
                            "path": doc.get("path", ""),
                            "date": doc.get("date", ""),
                            "type": doc.get("type", ""),
                        }
                    )

        # 부분 매칭 (키워드가 포함된 경우)
        for key, doc_ids in keywords.items():
            if keyword.lower() in key.lower() and key != keyword:
                for doc_id in doc_ids:
                    if doc_id not in [r["id"] for r in results]:
                        doc = self.index["documents"].get(doc_id)
                        if doc:
                            results.append(
                                {
                                    "id": doc_id,
                                    "title": doc.get("title", "제목 없음"),
                                    "summary": doc.get("summary", ""),
                                    "path": doc.get("path", ""),
                                    "date": doc.get("date", ""),
                                    "type": doc.get("type", ""),
                                }
                            )

        return results

    def search_by_participant(self, name: str) -> List[Dict]:
        """
        참여자로 검색

        Args:
            name: 참여자 이름

        Returns:
            검색 결과 리스트
        """
        results = []

        if not self.index:
            return results

        # participants 섹션에서 검색
        participants = self.index.get("participants", {})

        # 정확한 매칭
        if name in participants:
            doc_ids = participants[name]
            for doc_id in doc_ids:
                doc = self.index["documents"].get(doc_id)
                if doc:
                    results.append(
                        {
                            "id": doc_id,
                            "title": doc.get("title", "제목 없음"),
                            "summary": doc.get("summary", ""),
                            "path": doc.get("path", ""),
                            "date": doc.get("date", ""),
                            "type": doc.get("type", ""),
                        }
                    )

        # 부분 매칭
        for key, doc_ids in participants.items():
            if name.lower() in key.lower() and key != name:
                for doc_id in doc_ids:
                    if doc_id not in [r["id"] for r in results]:
                        doc = self.index["documents"].get(doc_id)
                        if doc:
                            results.append(
                                {
                                    "id": doc_id,
                                    "title": doc.get("title", "제목 없음"),
                                    "summary": doc.get("summary", ""),
                                    "path": doc.get("path", ""),
                                    "date": doc.get("date", ""),
                                    "type": doc.get("type", ""),
                                }
                            )

        return results

    def search_by_date(self, start_date: str, end_date: str = None) -> List[Dict]:
        """
        날짜 범위로 검색

        Args:
            start_date: 시작 날짜 (YYYY-MM-DD)
            end_date: 종료 날짜 (YYYY-MM-DD), 없으면 start_date만 검색

        Returns:
            검색 결과 리스트
        """
        results = []

        if not self.index:
            return results

        # 종료 날짜가 없으면 시작 날짜와 동일하게 설정
        if end_date is None:
            end_date = start_date

        # 모든 문서 검색
        for doc_id, doc in self.index["documents"].items():
            doc_date = doc.get("date", "")

            # 날짜 형식 확인 (YYYY-MM-DD)
            if doc_date:
                if start_date <= doc_date <= end_date:
                    results.append(
                        {
                            "id": doc_id,
                            "title": doc.get("title", "제목 없음"),
                            "summary": doc.get("summary", ""),
                            "path": doc.get("path", ""),
                            "date": doc_date,
                            "type": doc.get("type", ""),
                        }
                    )

        # 날짜순 정렬 (최신순)
        results.sort(key=lambda x: x["date"], reverse=True)

        return results

    def get_summary(self, doc_id: str) -> Optional[str]:
        """
        문서의 요약만 반환 (토큰 절약)

        Args:
            doc_id: 문서 ID

        Returns:
            요약 텍스트 (없으면 None)
        """
        if not self.index:
            return None

        doc = self.index["documents"].get(doc_id)
        if doc:
            return doc.get("summary", "")
        return None

    def get_document_info(self, doc_id: str) -> Optional[Dict]:
        """
        문서의 전체 정보 반환

        Args:
            doc_id: 문서 ID

        Returns:
            문서 정보 딕셔너리
        """
        if not self.index:
            return None

        return self.index["documents"].get(doc_id)

    def read_full_document(self, doc_id: str) -> Optional[str]:
        """
        문서 전체 읽기 (필요시에만 사용)

        Args:
            doc_id: 문서 ID

        Returns:
            문서 전체 텍스트
        """
        if not self.index:
            return None

        doc = self.index["documents"].get(doc_id)
        if not doc:
            return None

        path = doc.get("path", "")
        if not path:
            return None

        # 전체 경로 계산
        full_path = self.memory_path / path

        try:
            with open(full_path, "r", encoding="utf-8") as f:
                return f.read()
        except Exception as e:
            print(f"❌ 문서 읽기 실패: {e}")
            return None

    def list_all_documents(self, doc_type: str = None) -> List[Dict]:
        """
        모든 문서 목록 반환

        Args:
            doc_type: 문서 타입 필터 (daily, meeting, project, template 등)

        Returns:
            문서 목록
        """
        results = []

        if not self.index:
            return results

        for doc_id, doc in self.index["documents"].items():
            if doc_type is None or doc.get("type") == doc_type:
                results.append(
                    {
                        "id": doc_id,
                        "title": doc.get("title", "제목 없음"),
                        "summary": doc.get("summary", ""),
                        "path": doc.get("path", ""),
                        "date": doc.get("date", ""),
                        "type": doc.get("type", ""),
                    }
                )

        # 날짜순 정렬 (최신순)
        results.sort(key=lambda x: x.get("date", ""), reverse=True)

        return results

    def update_index_from_document(self, doc_path: str) -> bool:
        """
        문서에서 메타데이터 추출하여 index.json 업데이트

        Args:
            doc_path: 문서 경로 (memory/ 기준 상대 경로)

        Returns:
            성공 여부
        """
        try:
            # 전체 경로 계산
            full_path = self.memory_path / doc_path

            if not full_path.exists():
                print(f"⚠️ 문서가 없습니다: {full_path}")
                return False

            # 문서 읽기
            with open(full_path, "r", encoding="utf-8") as f:
                content = f.read()

            # YAML frontmatter 추출
            if not content.startswith("---"):
                print(f"⚠️ frontmatter가 없습니다: {doc_path}")
                return False

            # frontmatter 파싱
            parts = content.split("---", 2)
            if len(parts) < 3:
                print(f"⚠️ frontmatter 형식 오류: {doc_path}")
                return False

            import yaml

            try:
                metadata = yaml.safe_load(parts[1])
                # date 객체를 문자열로 변환
                if "date" in metadata and hasattr(metadata["date"], "isoformat"):
                    metadata["date"] = metadata["date"].isoformat()
            except Exception as e:
                print(f"⚠️ YAML 파싱 오류: {e}")
                return False

            # 필수 필드 확인
            doc_id = metadata.get("id")
            if not doc_id:
                print(f"⚠️ id가 없습니다: {doc_path}")
                return False

            # 요약 추출
            summary = ""
            if "## 📋 1분 요약" in content:
                summary_start = content.find("## 📋 1분 요약")
                summary_end = content.find("##", summary_start + 20)
                if summary_end == -1:
                    summary_end = content.find("---", summary_start)
                if summary_end > summary_start:
                    summary = content[summary_start:summary_end].strip()
                    # 헤더 제거
                    summary = summary.replace("## 📋 1분 요약", "").strip()

            # index.json에 추가
            doc_entry = {
                "path": doc_path,
                "type": metadata.get("type", ""),
                "date": metadata.get("date", ""),
                "title": metadata.get("title", doc_path),
                "keywords": metadata.get("keywords", []),
                "participants": metadata.get("participants", []),
                "summary": summary,
                "related": metadata.get("related", []),
            }

            # documents 섹션 업데이트
            if "documents" not in self.index:
                self.index["documents"] = {}
            self.index["documents"][doc_id] = doc_entry

            # keywords 섹션 업데이트
            if "keywords" not in self.index:
                self.index["keywords"] = {}
            for keyword in metadata.get("keywords", []):
                if keyword not in self.index["keywords"]:
                    self.index["keywords"][keyword] = []
                if doc_id not in self.index["keywords"][keyword]:
                    self.index["keywords"][keyword].append(doc_id)

            # participants 섹션 업데이트
            if "participants" not in self.index:
                self.index["participants"] = {}
            for participant in metadata.get("participants", []):
                if participant not in self.index["participants"]:
                    self.index["participants"][participant] = []
                if doc_id not in self.index["participants"][participant]:
                    self.index["participants"][participant].append(doc_id)

            # stats 업데이트
            if "stats" not in self.index:
                self.index["stats"] = {"totalDocuments": 0, "byType": {}}
            self.index["stats"]["totalDocuments"] = len(self.index["documents"])
            by_type = {}
            for doc in self.index["documents"].values():
                doc_type = doc.get("type", "unknown")
                by_type[doc_type] = by_type.get(doc_type, 0) + 1
            self.index["stats"]["byType"] = by_type

            # 저장
            return self.save_index()

        except Exception as e:
            print(f"❌ 인덱스 업데이트 실패: {e}")
            return False


# 사용 예시 (테스트용)
if __name__ == "__main__":
    engine = MemorySearchEngine()

    print("=" * 60)
    print("🔍 검색 시스템 테스트")
    print("=" * 60)

    # 1. 키워드 검색
    print("\n1️⃣ 키워드 검색: 'Boris Workflow'")
    results = engine.search_by_keyword("Boris Workflow")
    for r in results:
        print(f"  - {r['title']} ({r['date']})")
        print(f"    요약: {r['summary'][:100]}...")

    # 2. 참여자 검색
    print("\n2️⃣ 참여자 검색: '메인 관리자'")
    results = engine.search_by_participant("메인 관리자")
    for r in results:
        print(f"  - {r['title']} ({r['date']})")

    # 3. 날짜 검색
    print("\n3️⃣ 날짜 검색: 2025-02-26")
    results = engine.search_by_date("2025-02-26")
    for r in results:
        print(f"  - {r['title']} ({r['date']})")

    # 4. 모든 문서 목록
    print("\n4️⃣ 모든 문서 목록")
    results = engine.list_all_documents()
    for r in results:
        print(f"  - [{r['type']}] {r['title']} ({r['date']})")

    print("\n" + "=" * 60)
    print("✅ 검색 시스템 준비 완료")
    print("=" * 60)
