#!/usr/bin/env python3
"""
一键创建日程（可选：带参与者 + 预定空闲会议室）

流程：
  1. 若需预定会议室 (--book-room)，先搜索空闲会议室；无可用则提前报错退出
  2. 使用 event create 一次性完成日程创建 + 添加参与者 + 预定会议室

用法:
    python calendar_schedule_meeting.py \
        --title "Q1 复盘会" \
        --start "2026-03-15T14:00" \
        --end "2026-03-15T15:00" \
        --users userId1,userId2 \
        --book-room

    python calendar_schedule_meeting.py --dry-run \
        --title "测试" --start "2026-03-15T14:00" --end "2026-03-15T15:00"
"""

import sys
import json
import subprocess
import argparse
from datetime import datetime, timedelta, timezone
from typing import List, Any, Optional, Tuple

TZ = timezone(timedelta(hours=8))


def run_dws(
    args: List[str], dry_run: bool = False,
) -> Optional[Any]:
    cmd = ['dws'] + args
    if dry_run:
        print(f"[dry-run] {' '.join(cmd)}")
        return {'dry_run': True}
    try:
        result = subprocess.run(
            cmd, capture_output=True, text=True, timeout=60
        )
        if result.returncode != 0:
            print(f"  ✗ 错误：{result.stderr.strip()}")
            return None
        return json.loads(result.stdout)
    except (subprocess.TimeoutExpired, json.JSONDecodeError,
            FileNotFoundError) as e:
        print(f"  ✗ 错误：{e}")
        return None


def normalize_time(time_str: str) -> str:
    for fmt in ('%Y-%m-%dT%H:%M', '%Y-%m-%d %H:%M',
                '%Y-%m-%dT%H:%M:%S'):
        try:
            dt = datetime.strptime(time_str, fmt)
            dt = dt.replace(tzinfo=TZ)
            return dt.strftime('%Y-%m-%dT%H:%M:%S+08:00')
        except ValueError:
            continue
    if '+' in time_str or time_str.endswith('Z'):
        return time_str
    raise ValueError(f"无法解析时间：{time_str}")


def parse_group_ids(raw: str) -> List[str]:
    if raw is None:
        return []
    return [part.strip() for part in raw.split(',') if part.strip()]


def extract_room_candidates(payload: Any) -> Tuple[List[dict], str]:
    candidates: Any = []
    if isinstance(payload, list):
        candidates = payload
    elif isinstance(payload, dict):
        if isinstance(payload.get('rooms'), list):
            candidates = payload.get('rooms', [])
        elif isinstance(payload.get('result'), dict):
            nested = payload.get('result', {})
            if isinstance(nested.get('rooms'), list):
                candidates = nested.get('rooms', [])
            elif isinstance(nested.get('result'), list):
                candidates = nested.get('result', [])
        elif isinstance(payload.get('result'), list):
            candidates = payload.get('result', [])

    if not isinstance(candidates, list):
        return [], '返回结构中未找到会议室列表'

    valid_rooms: List[dict] = []
    placeholder_count = 0
    for item in candidates:
        if not isinstance(item, dict):
            continue
        if item.get('roomId') or item.get('id'):
            valid_rooms.append(item)
            continue
        if item.get('labels') is None and len(item) == 1:
            placeholder_count += 1

    if valid_rooms:
        return valid_rooms, f'返回 {len(valid_rooms)} 个有效会议室'
    if placeholder_count:
        return [], '仅返回占位结果（如 labels:null），无有效 roomId'
    if candidates:
        return [], '返回了对象列表，但均不含有效 roomId'
    return [], '未返回任何会议室'


def main():
    parser = argparse.ArgumentParser(
        description='一键创建日程（可选：带参与者 + 预定会议室）'
    )
    parser.add_argument('--title', required=True, help='日程标题')
    parser.add_argument('--start', required=True, help='开始时间')
    parser.add_argument('--end', required=True, help='结束时间')
    parser.add_argument('--desc', default='', help='日程描述')
    parser.add_argument('--users', default='', help='参与者 userId，逗号分隔')
    parser.add_argument(
        '--book-room', action='store_true', help='自动搜索并预定空闲会议室'
    )
    parser.add_argument(
        '--room-group-id', default='',
        help='允许搜索的 groupId；同一地点请只传最相关 group，多个仅用于用户明确允许的多个地点'
    )
    parser.add_argument(
        '--dry-run', action='store_true', help='仅显示命令'
    )
    args = parser.parse_args()

    try:
        start_iso = normalize_time(args.start)
        end_iso = normalize_time(args.end)
    except ValueError as e:
        print(f"错误：{e}")
        sys.exit(1)

    # ── Step 1: 若需预定会议室，先搜索空闲会议室 ──────────────────
    room_id: Optional[str] = None
    room_name: Optional[str] = None

    if args.book_room:
        print('🏢 搜索空闲会议室...')
        group_ids = parse_group_ids(args.room_group_id)
        search_scopes = group_ids or [None]
        selected_room = None
        failure_reasons: List[str] = []

        for group_id in search_scopes:
            scope_label = f'group {group_id}' if group_id else '根目录'
            print(f'  - 查询范围: {scope_label}')
            search_args = [
                'calendar', 'room', 'search',
                '--start', start_iso,
                '--end', end_iso,
                '--available',
                '--format', 'json',
            ]
            if group_id:
                search_args.extend(['--group-id', group_id])
            rooms_data = run_dws(search_args, dry_run=args.dry_run)

            if args.dry_run:
                continue
            if not rooms_data:
                failure_reasons.append(f'{scope_label}: room search 执行失败')
                continue

            rooms, detail = extract_room_candidates(rooms_data)
            if rooms:
                selected_room = rooms[0]
                break
            failure_reasons.append(f'{scope_label}: {detail}')

        if not args.dry_run:
            if selected_room:
                room_id = selected_room.get('roomId') or selected_room.get('id')
                room_name = selected_room.get('roomName') or selected_room.get('name')
                print(f'  ✓ 找到空闲会议室: {room_name} ({room_id})')
            else:
                print(f'  ✗ {start_iso} ~ {end_iso} 时段内无可用会议室')
                for reason in failure_reasons:
                    print(f'    - {reason}')
                print('  请向用户汇报失败，或询问是否放宽范围/改时间。')
                sys.exit(2)

    # ── Step 2: 一次性创建日程（含参与者 + 会议室） ────────────────
    print('\n📅 创建日程...')
    create_args = [
        'calendar', 'event', 'create',
        '--title', args.title,
        '--start', start_iso,
        '--end', end_iso,
        '--format', 'json',
    ]
    if args.desc:
        create_args.extend(['--desc', args.desc])
    if args.users:
        create_args.extend(['--attendees', args.users])
    if room_id:
        create_args.extend(['--rooms', str(room_id)])

    result = run_dws(create_args, dry_run=args.dry_run)
    if not result:
        sys.exit(1)

    # 解析响应
    event_id = None
    if not args.dry_run and isinstance(result, dict):
        # MCP 响应通常嵌套在 result 字段内: {"result": {"id": "..."}}
        inner = result.get('result', result)
        if isinstance(inner, dict):
            event_id = inner.get('eventId') or inner.get('id')
        else:
            event_id = result.get('eventId') or result.get('id')

    # 输出结果摘要
    parts = []
    if event_id:
        parts.append(f'eventId: {event_id}')
    if args.users:
        parts.append(f'参与者: {args.users}')
    if room_name:
        parts.append(f'会议室: {room_name}')
    detail_str = f" ({', '.join(parts)})" if parts else ''
    print(f'  ✓ 日程已创建{detail_str}')

    print('\n✅ 完成!')


if __name__ == '__main__':
    main()
