"""AI Journal — AI 일지, 감정 분석, 하루 요약.

stdlib-only. SQLite 저장, mood.py 연동.
"""

from __future__ import annotations

import logging
from collections import Counter
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional

from salmalm.constants import KST, BASE_DIR
from salmalm.utils.db import connect as _connect_db

log = logging.getLogger(__name__)

JOURNAL_DB = BASE_DIR / "journal.db"

# Simple mood keywords for analysis
_MOOD_KEYWORDS = {
    "happy": ["기쁘", "좋아", "행복", "최고", "감사", "happy", "great", "awesome", "love", "신나", "ㅋㅋ", "ㅎㅎ"],
    "sad": ["슬프", "우울", "힘들", "외로", "sad", "depressed", "lonely", "ㅠㅠ", "ㅜㅜ"],
    "angry": ["화나", "짜증", "열받", "angry", "furious", "annoyed"],
    "anxious": ["걱정", "불안", "초조", "anxious", "worried", "stressed"],
    "tired": ["피곤", "졸려", "지친", "tired", "exhausted"],
    "excited": ["기대", "설레", "신나", "excited", "thrilled"],
    "neutral": [],
}


def _get_db(db_path: Optional[Path] = None):
    """Get db."""
    conn = _connect_db(db_path or JOURNAL_DB, wal=True)
    conn.execute("""CREATE TABLE IF NOT EXISTS journal_entries (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        date TEXT NOT NULL,
        content TEXT NOT NULL,
        mood TEXT DEFAULT 'neutral',
        mood_score REAL DEFAULT 0.5,
        auto_generated INTEGER DEFAULT 0,
        created_at TEXT NOT NULL
    )""")
    conn.commit()
    return conn


def _detect_mood(text: str) -> tuple:
    """Simple keyword-based mood detection. Returns (mood, score)."""
    text_lower = text.lower()
    scores = {}
    for mood, keywords in _MOOD_KEYWORDS.items():
        if not keywords:
            continue
        count = sum(1 for kw in keywords if kw in text_lower)
        if count:
            scores[mood] = count

    if not scores:
        return "neutral", 0.5

    best = max(scores, key=scores.get)
    # Score: positive moods > 0.5, negative < 0.5
    mood_valence = {
        "happy": 0.9,
        "excited": 0.85,
        "neutral": 0.5,
        "tired": 0.35,
        "anxious": 0.3,
        "sad": 0.2,
        "angry": 0.15,
    }
    return best, mood_valence.get(best, 0.5)


class JournalManager:
    """AI 일지 관리자."""

    def __init__(self, db_path: Optional[Path] = None) -> None:
        """Init  ."""
        self._db_path = db_path
        self._conn = None

    @property
    def conn(self):
        """Conn."""
        if self._conn is None:
            self._conn = _get_db(self._db_path)
        return self._conn

    def close(self) -> None:
        """Close."""
        if self._conn:
            self._conn.close()
            self._conn = None

    def write(self, text: str, date: Optional[str] = None) -> str:
        """일지 작성."""
        text = text.strip()
        if not text:
            return "❌ 일지 내용을 입력하세요."

        today = date or datetime.now(KST).strftime("%Y-%m-%d")
        now = datetime.now(KST).isoformat()
        mood, score = _detect_mood(text)

        self.conn.execute(
            "INSERT INTO journal_entries (date, content, mood, mood_score, auto_generated, created_at) "
            "VALUES (?, ?, ?, ?, 0, ?)",
            (today, text, mood, score, now),
        )
        self.conn.commit()

        mood_emoji = {
            "happy": "😊",
            "sad": "😢",
            "angry": "😡",
            "anxious": "😰",
            "tired": "😴",
            "excited": "🤩",
            "neutral": "😐",
        }
        emoji = mood_emoji.get(mood, "📝")
        return f"📝 일지 작성 완료! {emoji} 감정: {mood} ({score:.0%})"

    def review(self, date: str) -> str:
        """특정 날짜 일지 조회."""
        rows = self.conn.execute(
            "SELECT content, mood, mood_score, created_at, auto_generated "
            "FROM journal_entries WHERE date=? ORDER BY created_at",
            (date,),
        ).fetchall()

        if not rows:
            return f"📖 {date}의 일지가 없습니다."

        lines = [f"📖 **{date} 일지**\n"]
        for content, mood, score, created, auto in rows:
            tag = "🤖 자동" if auto else "✍️"
            mood_emoji = {
                "happy": "😊",
                "sad": "😢",
                "angry": "😡",
                "anxious": "😰",
                "tired": "😴",
                "excited": "🤩",
                "neutral": "😐",
            }.get(mood, "📝")
            lines.append(f"{tag} {mood_emoji} {content[:200]}")
        return "\n".join(lines)

    def today(self) -> str:
        """오늘 일지 조회."""
        today = datetime.now(KST).strftime("%Y-%m-%d")
        return self.review(today)

    def generate_today_summary(self, conversations: Optional[List[str]] = None) -> str:
        """오늘의 대화 기반 자동 일지 생성."""
        today = datetime.now(KST).strftime("%Y-%m-%d")
        now = datetime.now(KST).isoformat()

        # Get existing entries for today
        rows = self.conn.execute("SELECT content FROM journal_entries WHERE date=?", (today,)).fetchall()

        if not rows and not conversations:
            return "📝 오늘 기록된 일지가 없습니다."

        all_text = " ".join(r[0] for r in rows)
        if conversations:
            all_text += " " + " ".join(conversations)

        mood, score = _detect_mood(all_text)
        entry_count = len(rows)

        summary = f"오늘 {entry_count}개의 일지를 작성했습니다. 전반적 감정: {mood}."
        self.conn.execute(
            "INSERT INTO journal_entries (date, content, mood, mood_score, auto_generated, created_at) "
            "VALUES (?, ?, ?, ?, 1, ?)",
            (today, summary, mood, score, now),
        )
        self.conn.commit()

        return f"🤖 **오늘의 자동 일지**\n{summary}"

    def mood_trend(self, days: int = 14) -> str:
        """감정 트렌드 차트 (텍스트 기반)."""
        today = datetime.now(KST)
        lines = ["📊 **감정 트렌드** (최근 {0}일)\n".format(days)]

        mood_counts = Counter()
        daily_scores = []

        for i in range(days - 1, -1, -1):
            date = (today - timedelta(days=i)).strftime("%Y-%m-%d")
            rows = self.conn.execute("SELECT mood, mood_score FROM journal_entries WHERE date=?", (date,)).fetchall()

            if rows:
                avg_score = sum(r[1] for r in rows) / len(rows)
                moods = [r[0] for r in rows]
                for m in moods:
                    mood_counts[m] += 1
                daily_scores.append((date, avg_score, moods[0]))
            else:
                daily_scores.append((date, None, None))

        # Text chart
        for date, score, mood in daily_scores:
            day_label = date[-5:]  # MM-DD
            if score is not None:
                bar_len = int(score * 10)
                bar = "█" * bar_len + "░" * (10 - bar_len)
                emoji = {
                    "happy": "😊",
                    "sad": "😢",
                    "angry": "😡",
                    "anxious": "😰",
                    "tired": "😴",
                    "excited": "🤩",
                    "neutral": "😐",
                }.get(mood, "📝")
                lines.append(f"{day_label} {bar} {emoji} {score:.0%}")
            else:
                lines.append(f"{day_label} {'·' * 10} (기록 없음)")

        # Summary
        if mood_counts:
            top = mood_counts.most_common(3)
            summary = ", ".join(f"{m}({c}회)" for m, c in top)
            lines.append(f"\n📈 주요 감정: {summary}")

        return "\n".join(lines)

    def mood_from_mood_py(self, text: str) -> Optional[str]:
        """기존 mood.py 연동."""
        try:
            from salmalm.features.mood import detect_mood

            result = detect_mood(text)
            if result:
                return result.get("mood", "neutral")
        except (ImportError, Exception):
            pass
        return None

    def get_entries_for_date(self, date: str) -> List[Dict]:
        """특정 날짜 엔트리 (API용)."""
        rows = self.conn.execute(
            "SELECT id, content, mood, mood_score, auto_generated, created_at "
            "FROM journal_entries WHERE date=? ORDER BY created_at",
            (date,),
        ).fetchall()
        return [
            {"id": r[0], "content": r[1], "mood": r[2], "mood_score": r[3], "auto": bool(r[4]), "created_at": r[5]}
            for r in rows
        ]


# ── Singleton ──
_journal: Optional[JournalManager] = None


def get_journal(db_path: Optional[Path] = None) -> JournalManager:
    """Get journal."""
    global _journal
    if _journal is None:
        _journal = JournalManager(db_path)
    return _journal


# ── Command handler ──


async def handle_journal_command(cmd: str, session=None, **kw) -> Optional[str]:
    """Handle /journal commands."""
    parts = cmd.strip().split(maxsplit=2)
    if len(parts) < 2:
        return get_journal().today()

    sub = parts[1].lower()
    arg = parts[2].strip() if len(parts) > 2 else ""

    j = get_journal()

    if sub == "write":
        if not arg:
            return "사용법: `/journal write <내용>`"
        return j.write(arg)
    elif sub == "today":
        return j.today()
    elif sub == "review":
        if not arg:
            return "사용법: `/journal review <YYYY-MM-DD>`"
        return j.review(arg)
    elif sub == "mood":
        days = 14
        if arg and arg.isdigit():
            days = int(arg)
        return j.mood_trend(days)
    elif sub == "summary":
        return j.generate_today_summary()
    else:
        return (
            "**일지 명령어:**\n"
            "`/journal write <text>` — 일지 작성\n"
            "`/journal today` — 오늘 일지\n"
            "`/journal review <date>` — 날짜별 조회\n"
            "`/journal mood` — 감정 트렌드\n"
            "`/journal summary` — 오늘 자동 요약"
        )


# ── Registration ──


def register_journal_commands(command_router) -> None:
    """Register /journal command."""
    from salmalm.features.commands import COMMAND_DEFS

    COMMAND_DEFS["/journal"] = "AI Journal (write|today|review|mood|summary)"
    if hasattr(command_router, "_prefix_handlers"):
        command_router._prefix_handlers.append(("/journal", handle_journal_command))


def register_journal_tools():
    """Register journal tools."""
    from salmalm.tools.tool_registry import register_dynamic

    async def _journal_tool(args):
        """Journal tool."""
        sub = args.get("subcommand", "today")
        text = args.get("text", "")
        cmd = f"/journal {sub} {text}".strip()
        return await handle_journal_command(cmd)

    register_dynamic(
        "ai_journal",
        _journal_tool,
        {
            "name": "ai_journal",
            "description": "AI Journal - write entries, review, mood trends",
            "parameters": {
                "type": "object",
                "properties": {
                    "subcommand": {
                        "type": "string",
                        "enum": ["write", "today", "review", "mood", "summary"],
                    },
                    "text": {"type": "string", "description": "Journal text or date"},
                },
                "required": ["subcommand"],
            },
        },
    )
