#!/usr/bin/env python3
import click
import os
import json
from datetime import datetime
from typing import Optional, List
from rich.console import Console
from rich.table import Table
from rich.panel import Panel

# 콘솔 설정
console = Console()

@click.group()
@click.version_option(version="0.1.0")
def main():
    """MemoryBlockEngine - LLM 독립적 기억 시스템 CLI"""
    pass

@main.command("init")
@click.option("--db-path", default=None, help="데이터베이스 경로 (기본: data/memory.db)")
@click.option("--use-embedding", default="simple", help="사용할 임베딩 모델 (simple, sentence-transformer, openai)")
@click.option("--openai-key", default=None, help="OpenAI API 키 (OpenAI 임베딩 모델 사용시 필요)")
def init_command(db_path, use_embedding, openai_key):
    """메모리 엔진 초기화"""
    try:
        # 데이터 디렉토리 확인
        data_dir = os.path.dirname(db_path or "data/memory.db")
        if data_dir and not os.path.exists(data_dir):
            os.makedirs(data_dir)
            console.print(f"[green]데이터 디렉토리 생성: {data_dir}[/green]")
        
        # 데이터베이스 초기화
        from memory_engine import DatabaseManager
        db_path = db_path or os.path.join("data", "memory.db")
        db_manager = DatabaseManager(db_path)
        console.print(f"[green]데이터베이스 초기화 완료: {db_path}[/green]")
        
        # 임베딩 모델 초기화
        if use_embedding == "simple":
            from memory_engine import SimpleEmbeddingModel, register_embedding_model
            model = SimpleEmbeddingModel()
            register_embedding_model("default", model, set_as_default=True)
            console.print("[green]간단한 임베딩 모델 초기화 완료[/green]")
        elif use_embedding == "sentence-transformer":
            from memory_engine import init_sentence_transformer
            init_sentence_transformer()
            console.print("[green]SentenceTransformer 임베딩 모델 초기화 완료[/green]")
        elif use_embedding == "openai":
            if not openai_key:
                console.print("[yellow]OpenAI API 키가 필요합니다. --openai-key 옵션을 사용하세요.[/yellow]")
                return
            from memory_engine import init_openai
            init_openai(api_key=openai_key)
            console.print("[green]OpenAI 임베딩 모델 초기화 완료[/green]")
        else:
            console.print(f"[red]지원하지 않는 임베딩 모델: {use_embedding}[/red]")
            return
        
        console.print("[bold green]메모리 엔진 초기화 완료![/bold green]")
    except Exception as e:
        console.print(f"[bold red]초기화 오류: {str(e)}[/bold red]")

@main.command("add-memory")
@click.argument("text")
@click.option("--db-path", default=None, help="데이터베이스 경로 (기본: data/memory.db)")
@click.option("--keywords", default=None, help="키워드 (쉼표로 구분)")
@click.option("--tags", default=None, help="태그 (쉼표로 구분)")
@click.option("--importance", default=None, type=float, help="중요도 (0~1)")
def add_memory_command(text, db_path, keywords, tags, importance):
    """새 기억 추가"""
    try:
        # 데이터베이스 연결
        from memory_engine import DatabaseManager
        db_path = db_path or os.path.join("data", "memory.db")
        db_manager = DatabaseManager(db_path)
        
        # 텍스트 처리
        from memory_engine.text_utils import process_user_input
        
        # 사용자가 제공한 키워드와 태그 처리
        user_keywords = keywords.split(",") if keywords else None
        user_tags = tags.split(",") if tags else None
        
        # 텍스트 처리
        result = process_user_input(text)
        
        # 사용자 제공 값 우선 적용
        if user_keywords:
            result["keywords"] = user_keywords
        if user_tags:
            result["tags"] = user_tags
        if importance is not None:
            result["importance"] = importance
        
        # 타임스탬프 및 해시 추가
        from hashlib import sha256
        timestamp = datetime.now().isoformat()
        result["timestamp"] = timestamp
        
        # 블록 인덱스 생성 (마지막 블록 + 1)
        last_block = db_manager.get_blocks(limit=1)
        block_index = 0
        if last_block:
            block_index = last_block[0].get("block_index", -1) + 1
        
        # 이전 해시 가져오기
        prev_hash = ""
        if block_index > 0:
            prev_block = db_manager.get_block(block_index - 1)
            if prev_block:
                prev_hash = prev_block.get("hash", "")
        
        # 해시 계산
        hash_data = {
            "block_index": block_index,
            "timestamp": timestamp,
            "context": text,
            "prev_hash": prev_hash
        }
        hash_str = json.dumps(hash_data, sort_keys=True)
        hash_value = sha256(hash_str.encode()).hexdigest()
        
        # 최종 블록 데이터
        block_data = {
            "block_index": block_index,
            "timestamp": timestamp,
            "context": text,
            "keywords": result.get("keywords", []),
            "tags": result.get("tags", []),
            "embedding": result.get("embedding", []),
            "importance": result.get("importance", 0.5),
            "hash": hash_value,
            "prev_hash": prev_hash
        }
        
        # 데이터베이스에 추가
        db_manager.add_block(block_data)
        
        # 출력
        console.print(f"[green]기억 블록 추가 완료: #{block_index}[/green]")
        console.print(Panel.fit(
            f"[bold]컨텍스트:[/bold] {text}\n"
            f"[bold]키워드:[/bold] {', '.join(block_data['keywords'])}\n"
            f"[bold]태그:[/bold] {', '.join(block_data['tags'])}\n"
            f"[bold]중요도:[/bold] {block_data['importance']:.2f}"
        ))
    except Exception as e:
        console.print(f"[bold red]기억 추가 오류: {str(e)}[/bold red]")

@main.command("search")
@click.argument("query")
@click.option("--db-path", default=None, help="데이터베이스 경로 (기본: data/memory.db)")
@click.option("--limit", default=5, help="결과 개수 제한")
@click.option("--mode", default="hybrid", help="검색 모드 (embedding, keyword, temporal, hybrid)")
def search_command(query, db_path, limit, mode):
    """기억 검색"""
    try:
        # 데이터베이스 연결
        from memory_engine import DatabaseManager
        db_path = db_path or os.path.join("data", "memory.db")
        db_manager = DatabaseManager(db_path)
        
        blocks = []
        
        # 검색 모드에 따라 다른 방법 사용
        if mode == "embedding":
            # 임베딩 검색
            from memory_engine import get_embedding
            embedding = get_embedding(query)
            blocks = db_manager.search_blocks_by_embedding(embedding, top_k=limit)
            console.print(f"[blue]임베딩 검색 결과:[/blue]")
        elif mode == "keyword":
            # 키워드 검색
            keywords = query.split()
            blocks = db_manager.search_blocks_by_keyword(keywords, limit=limit)
            console.print(f"[blue]키워드 검색 결과:[/blue]")
        elif mode == "temporal":
            # 시간적 검색
            from memory_engine import TemporalReasoner
            reasoner = TemporalReasoner(db_manager)
            result = reasoner.search_by_time_reference(query)
            blocks = result.get("blocks", [])
            
            # 시간 참조 정보 출력
            time_ref = result.get("time_ref")
            if time_ref:
                console.print(f"[blue]시간 표현 감지: {time_ref.get('term')}[/blue]")
                from_date = time_ref.get("from_date")
                to_date = time_ref.get("to_date")
                if from_date and to_date:
                    console.print(f"[blue]검색 범위: {from_date} ~ {to_date}[/blue]")
            console.print(f"[blue]시간적 검색 결과:[/blue]")
        elif mode == "hybrid":
            # 하이브리드 검색 (기본값)
            from memory_engine import TemporalReasoner, get_embedding
            reasoner = TemporalReasoner(db_manager)
            embedding = get_embedding(query)
            keywords = query.split()
            result = reasoner.hybrid_search(query, embedding, keywords, top_k=limit)
            blocks = result.get("blocks", [])
            console.print(f"[blue]하이브리드 검색 결과:[/blue]")
        else:
            console.print(f"[red]지원하지 않는 검색 모드: {mode}[/red]")
            return
        
        # 결과 출력
        if not blocks:
            console.print("[yellow]검색 결과가 없습니다.[/yellow]")
            return
        
        table = Table(title=f"'{query}' 검색 결과")
        table.add_column("블록 #", justify="right", style="cyan")
        table.add_column("날짜", style="blue")
        table.add_column("컨텍스트", style="green")
        table.add_column("키워드", style="yellow")
        table.add_column("관련도", justify="right", style="magenta")
        
        for block in blocks:
            # 날짜 형식 변환
            try:
                timestamp = datetime.fromisoformat(block.get("timestamp", ""))
                date_str = timestamp.strftime("%Y-%m-%d %H:%M")
            except:
                date_str = block.get("timestamp", "")[:16]
            
            # 컨텍스트 요약 (너무 길면 자름)
            context = block.get("context", "")
            if len(context) > 50:
                context = context[:47] + "..."
            
            # 키워드 출력
            keywords = ", ".join(block.get("keywords", [])[:3])
            
            # 관련도 점수
            score = ""
            if "similarity" in block:
                score = f"{block['similarity']:.2f}"
            elif "relevance_score" in block:
                score = f"{block['relevance_score']:.2f}"
            
            table.add_row(
                str(block.get("block_index", "")),
                date_str,
                context,
                keywords,
                score
            )
        
        console.print(table)
        
        # 블록 상세 보기 안내
        console.print("\n[bold]블록 상세 정보를 보려면:[/bold]")
        console.print(f"memory-engine get-block <블록 번호>")
        
    except Exception as e:
        console.print(f"[bold red]검색 오류: {str(e)}[/bold red]")

@main.command("get-block")
@click.argument("block_index", type=int)
@click.option("--db-path", default=None, help="데이터베이스 경로 (기본: data/memory.db)")
def get_block_command(block_index, db_path):
    """특정 블록 상세 정보 조회"""
    try:
        # 데이터베이스 연결
        from memory_engine import DatabaseManager
        db_path = db_path or os.path.join("data", "memory.db")
        db_manager = DatabaseManager(db_path)
        
        # 블록 조회
        block = db_manager.get_block(block_index)
        
        if not block:
            console.print(f"[yellow]블록 #{block_index}를 찾을 수 없습니다.[/yellow]")
            return
        
        # 시간 형식 변환
        try:
            timestamp = datetime.fromisoformat(block.get("timestamp", ""))
            date_str = timestamp.strftime("%Y-%m-%d %H:%M:%S")
        except:
            date_str = block.get("timestamp", "")
        
        # 블록 정보 출력
        console.print(Panel.fit(
            f"[bold cyan]블록 #{block_index}[/bold cyan] [blue]({date_str})[/blue]\n\n"
            f"[bold]컨텍스트:[/bold]\n{block.get('context', '')}\n\n"
            f"[bold]키워드:[/bold] {', '.join(block.get('keywords', []))}\n"
            f"[bold]태그:[/bold] {', '.join(block.get('tags', []))}\n"
            f"[bold]중요도:[/bold] {block.get('importance', 0):.2f}\n\n"
            f"[bold]해시:[/bold] {block.get('hash', '')[:16]}...\n"
            f"[bold]이전 해시:[/bold] {block.get('prev_hash', '')[:16]}..."
        ))
        
        # 수정 이력 확인
        try:
            from memory_engine import MemoryEvolutionManager
            evolution_manager = MemoryEvolutionManager(db_manager)
            revisions = evolution_manager.get_revision_chain(block_index)
            
            if len(revisions) > 1:
                console.print(f"\n[blue]이 블록은 {len(revisions)} 개의 수정 이력이 있습니다.[/blue]")
                for i, rev in enumerate(revisions):
                    if rev.get("block_index") == block_index:
                        continue
                    console.print(f"  - 수정 #{i+1}: 블록 #{rev.get('block_index')} ({rev.get('timestamp', '')[:16]})")
        except ImportError:
            pass
            
    except Exception as e:
        console.print(f"[bold red]블록 조회 오류: {str(e)}[/bold red]")

@main.command("update-memory")
@click.argument("block_index", type=int)
@click.argument("new_text")
@click.option("--db-path", default=None, help="데이터베이스 경로 (기본: data/memory.db)")
@click.option("--reason", default="내용 업데이트", help="변경 이유")
def update_memory_command(block_index, new_text, db_path, reason):
    """기존 기억 업데이트"""
    try:
        # 데이터베이스 연결
        from memory_engine import DatabaseManager, MemoryEvolutionManager
        db_path = db_path or os.path.join("data", "memory.db")
        db_manager = DatabaseManager(db_path)
        
        # 진화 관리자 초기화
        evolution_manager = MemoryEvolutionManager(db_manager)
        
        # 수정본 생성
        revision = evolution_manager.create_memory_revision(
            original_block_index=block_index,
            new_context=new_text,
            reason=reason
        )
        
        if revision:
            console.print(f"[green]기억 블록 업데이트 완료: #{revision['block_index']}[/green]")
            console.print(Panel.fit(
                f"[bold]원본 블록:[/bold] #{block_index}\n"
                f"[bold]수정 이유:[/bold] {reason}\n"
                f"[bold]새 내용:[/bold] {new_text}\n"
            ))
        else:
            console.print(f"[red]기억 업데이트 실패[/red]")
            
    except Exception as e:
        console.print(f"[bold red]업데이트 오류: {str(e)}[/bold red]")

@main.command("recent-memories")
@click.option("--limit", default=10, help="표시할 기억 개수")
@click.option("--db-path", default=None, help="데이터베이스 경로 (기본: data/memory.db)")
def recent_memories_command(limit, db_path):
    """최근 기억 목록 조회"""
    try:
        # 데이터베이스 연결
        from memory_engine import DatabaseManager
        db_path = db_path or os.path.join("data", "memory.db")
        db_manager = DatabaseManager(db_path)
        
        # 최근 블록 조회
        blocks = db_manager.get_blocks(limit=limit)
        
        if not blocks:
            console.print("[yellow]저장된 기억이 없습니다.[/yellow]")
            return
        
        # 테이블 생성
        table = Table(title=f"최근 {limit}개 기억")
        table.add_column("블록 #", justify="right", style="cyan")
        table.add_column("날짜", style="blue")
        table.add_column("컨텍스트", style="green")
        table.add_column("중요도", style="magenta")
        
        for block in blocks:
            # 날짜 형식 변환
            try:
                timestamp = datetime.fromisoformat(block.get("timestamp", ""))
                date_str = timestamp.strftime("%Y-%m-%d %H:%M")
            except:
                date_str = block.get("timestamp", "")[:16]
            
            # 컨텍스트 요약
            context = block.get("context", "")
            if len(context) > 50:
                context = context[:47] + "..."
            
            table.add_row(
                str(block.get("block_index", "")),
                date_str,
                context,
                f"{block.get('importance', 0):.2f}"
            )
        
        console.print(table)
        
    except Exception as e:
        console.print(f"[bold red]기억 조회 오류: {str(e)}[/bold red]")

if __name__ == "__main__":
    main() 