#!/usr/bin/env python3
"""
Inbox 메시지 시스템
봇 간 inbox 디렉토리를 통해 JSON 메시지를 주고받는 유틸리티.

스펙:
- 파일명: YYYY-MM-DDTHH-MM-SS_from-<team>.json
- JSON 키: from, to, subject, body, timestamp, read
- read_inbox: unread(read=false)만 반환
- CLI: --from, --to, --subject, --body 플래그 방식
"""

import argparse
import json
import sys
import time as _time
from datetime import datetime
from pathlib import Path
from typing import Dict, List

INBOX_BASE = Path("/home/jay/workspace/memory/inbox")
try:
    from utils.org_loader import get_dev_team_ids as _get_dev_team_ids

    VALID_TEAMS: list[str] = _get_dev_team_ids() + ["anu"]
except ImportError:
    VALID_TEAMS = ["dev1-team", "dev2-team", "dev3-team", "anu"]


def _ensure_dirs(base: Path = None):
    """모든 팀의 inbox 디렉토리를 생성한다."""
    b = base or INBOX_BASE
    for team in VALID_TEAMS:
        (b / team).mkdir(parents=True, exist_ok=True)


def send_message(from_team: str, to_team: str, subject: str, body: str, base: Path = None) -> str:
    """메시지를 보낸다. 생성된 파일명을 반환한다."""
    b = base or INBOX_BASE
    (b / to_team).mkdir(parents=True, exist_ok=True)
    now = datetime.now()
    timestamp = now.strftime("%Y-%m-%dT%H-%M-%S")
    filename = f"{timestamp}_from-{from_team}.json"
    filepath = b / to_team / filename
    # 파일명 충돌 시 밀리초 추가
    if filepath.exists():
        timestamp = now.strftime("%Y-%m-%dT%H-%M-%S") + f"-{now.microsecond // 1000:03d}"
        filename = f"{timestamp}_from-{from_team}.json"
        filepath = b / to_team / filename
    message = {
        "from": from_team,
        "to": to_team,
        "subject": subject,
        "body": body,
        "timestamp": now.isoformat(),
        "read": False,
    }
    filepath.write_text(json.dumps(message, ensure_ascii=False, indent=2), encoding="utf-8")
    return filename


def read_inbox(team: str, base: Path = None) -> List[Dict]:
    """해당 팀의 읽지 않은(unread) 메시지 목록을 반환한다."""
    b = base or INBOX_BASE
    inbox_dir = b / team
    if not inbox_dir.exists():
        return []
    unread = []
    for f in sorted(inbox_dir.glob("*.json")):
        data = json.loads(f.read_text(encoding="utf-8"))
        if not data.get("read", False):
            data["_filename"] = f.name
            unread.append(data)
    return unread


def mark_read(team: str, filename: str, base: Path = None) -> bool:
    """메시지를 읽음 처리한다. 성공 여부를 반환한다."""
    b = base or INBOX_BASE
    filepath = b / team / filename
    if not filepath.exists():
        return False
    data = json.loads(filepath.read_text(encoding="utf-8"))
    data["read"] = True
    filepath.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
    return True


def get_all_messages(team: str, base: Path = None) -> List[Dict]:
    """해당 팀의 전체 메시지 목록을 반환한다."""
    b = base or INBOX_BASE
    inbox_dir = b / team
    if not inbox_dir.exists():
        return []
    messages = []
    for f in sorted(inbox_dir.glob("*.json")):
        data = json.loads(f.read_text(encoding="utf-8"))
        data["_filename"] = f.name
        messages.append(data)
    return messages


def clear_inbox(team: str, base: Path = None) -> int:
    """해당 팀의 inbox를 비운다 (JSON 파일만 삭제). 삭제된 메시지 수를 반환한다."""
    b = base or INBOX_BASE
    inbox_dir = b / team
    if not inbox_dir.exists():
        return 0
    count = 0
    for f in inbox_dir.glob("*.json"):
        f.unlink()
        count += 1
    return count


# ── CLI 인터페이스 ──


def cli_send(args):
    filename = send_message(args.from_team, args.to, args.subject, args.body)
    print(json.dumps({"status": "sent", "filename": filename, "to": args.to}, ensure_ascii=False))


def cli_read(args):
    messages = read_inbox(args.team)
    print(json.dumps(messages, ensure_ascii=False, indent=2))


def cli_list(args):
    messages = get_all_messages(args.team)
    print(json.dumps(messages, ensure_ascii=False, indent=2))


def main():
    parser = argparse.ArgumentParser(description="inbox 메시지 시스템")
    sub = parser.add_subparsers(dest="command")

    # send
    p_send = sub.add_parser("send", help="메시지 보내기")
    p_send.add_argument("--from", dest="from_team", required=True, help="보내는 팀")
    p_send.add_argument("--to", required=True, help="받는 팀")
    p_send.add_argument("--subject", required=True, help="제목")
    p_send.add_argument("--body", required=True, help="본문")

    # read (unread only)
    p_read = sub.add_parser("read", help="읽지 않은 메시지 조회")
    p_read.add_argument("--team", required=True, help="팀명")

    # list (all)
    p_list = sub.add_parser("list", help="전체 메시지 조회")
    p_list.add_argument("--team", required=True, help="팀명")

    args = parser.parse_args()
    if args.command == "send":
        cli_send(args)
    elif args.command == "read":
        cli_read(args)
    elif args.command == "list":
        cli_list(args)
    else:
        parser.print_help()
        sys.exit(1)


# ── assert 기반 테스트 ──


def run_tests():
    """assert 기반 단위 테스트 (임시 디렉토리 사용, 프로덕션 데이터 안전)"""
    import tempfile

    with tempfile.TemporaryDirectory() as tmpdir:
        base = Path(tmpdir)

        # 1) send_message 테스트
        fname = send_message("dev1-team", "anu", "테스트 제목", "테스트 본문입니다", base=base)
        assert fname.endswith("_from-dev1-team.json"), f"파일명 형식 오류: {fname}"
        assert "T" in fname, f"파일명에 T 구분자 없음: {fname}"
        fpath = base / "anu" / fname
        assert fpath.exists(), "메시지 파일이 생성되지 않음"

        data = json.loads(fpath.read_text(encoding="utf-8"))
        assert data["from"] == "dev1-team", f"from 필드 오류: {data['from']}"
        assert data["to"] == "anu", f"to 필드 오류: {data['to']}"
        assert data["subject"] == "테스트 제목", f"subject 오류: {data['subject']}"
        assert data["body"] == "테스트 본문입니다", f"body 오류: {data['body']}"
        assert data["read"] is False, "read 초기값이 False가 아님"
        assert "timestamp" in data, "timestamp 필드 없음"
        print("[PASS] send_message")

        # 2) read_inbox 테스트 (unread만)
        unread = read_inbox("anu", base=base)
        assert len(unread) == 1, f"unread 수 오류: {len(unread)}"
        assert unread[0]["subject"] == "테스트 제목"
        assert "_filename" in unread[0], "_filename 메타데이터 없음"
        print("[PASS] read_inbox (unread only)")

        # 3) mark_read 테스트
        result = mark_read("anu", fname, base=base)
        assert result is True, "mark_read 실패"
        data2 = json.loads(fpath.read_text(encoding="utf-8"))
        assert data2["read"] is True, "read 플래그가 True로 변경되지 않음"

        # mark_read 후 read_inbox에서 안 보여야 함
        unread2 = read_inbox("anu", base=base)
        assert len(unread2) == 0, f"mark_read 후 unread가 비어있지 않음: {len(unread2)}"
        print("[PASS] mark_read")

        # 4) get_all_messages 테스트 (읽은 것 + 안 읽은 것 모두)
        _time.sleep(1)  # 파일명 충돌 방지
        send_message("dev2-team", "anu", "두 번째", "내용2", base=base)
        all_msgs = get_all_messages("anu", base=base)
        assert len(all_msgs) == 2, f"전체 메시지 수 오류: {len(all_msgs)}"
        read_count = sum(1 for m in all_msgs if m["read"])
        assert read_count == 1, f"읽은 메시지 수 오류: {read_count}"
        print("[PASS] get_all_messages")

        # 5) clear_inbox 테스트
        cleared = clear_inbox("anu", base=base)
        assert cleared == 2, f"삭제 수 오류: {cleared}"
        remaining = get_all_messages("anu", base=base)
        assert len(remaining) == 0, f"clear 후 메시지 남음: {len(remaining)}"
        print("[PASS] clear_inbox")

        # 6) 존재하지 않는 파일 mark_read
        result2 = mark_read("anu", "nonexistent.json", base=base)
        assert result2 is False, "존재하지 않는 파일에 대해 True 반환"
        print("[PASS] mark_read (nonexistent)")

        # 7) UTF-8 인코딩 테스트
        send_message("dev3-team", "dev1-team", "한글 제목", "이모지와 한글 본문 테스트", base=base)
        msgs = read_inbox("dev1-team", base=base)
        assert len(msgs) == 1, f"UTF-8 메시지 수 오류: {len(msgs)}"
        assert msgs[0]["subject"] == "한글 제목"
        assert msgs[0]["body"] == "이모지와 한글 본문 테스트"
        print("[PASS] UTF-8 encoding")

        # 8) 빈 inbox 읽기
        empty = read_inbox("dev2-team", base=base)
        assert len(empty) == 0, "빈 inbox에서 메시지 반환됨"
        print("[PASS] empty inbox")

        # 9) 빈 inbox clear
        cleared2 = clear_inbox("dev2-team", base=base)
        assert cleared2 == 0, f"빈 inbox clear 시 삭제 수가 0이 아님: {cleared2}"
        print("[PASS] clear empty inbox")

    print("\n=== 모든 테스트 통과 (9/9) ===")


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "test":
        run_tests()
    else:
        main()
