"""
會議 API(階段 4)。

  - POST /api/meetings/upload          ─ 上傳音訊 + 觸發背景處理
  - GET  /api/meetings                 ─ 列出最近會議
  - GET  /api/meetings/{id}            ─ 會議詳情(逐字稿 + 摘要 + 待辦)
  - POST /api/meetings/{id}/action-items/{aid}/convert  ─ action item 轉成 task
"""

import logging
import uuid
from datetime import date as date_type
from pathlib import Path

from fastapi import APIRouter, File, Form, HTTPException, UploadFile, status
from sqlalchemy import select
from sqlalchemy.orm import selectinload

from app.core.deps import CurrentUser, DBSession
from app.models.meeting import Meeting, MeetingActionItem
from app.models.task import Task
from app.schemas.meeting import MeetingDetail, MeetingPublic
from app.services.meeting_processor import trigger_meeting_processing


logger = logging.getLogger("coba.meetings.api")

router = APIRouter(prefix="/api/meetings", tags=["meetings"])


# 音訊檔存放路徑(階段 5 上 NAS 改成 NAS shared dir)
UPLOAD_DIR = Path(__file__).resolve().parent.parent.parent / "uploads" / "meetings"
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)

# 接受的音訊類型
AUDIO_MIME_PREFIXES = ("audio/", "video/")
MAX_AUDIO_SIZE = 200 * 1024 * 1024   # 200 MB(夠 1-2 小時 mp3)


@router.post(
    "/upload",
    response_model=MeetingPublic,
    status_code=status.HTTP_201_CREATED,
    summary="上傳會議音訊 + 觸發背景處理",
)
async def upload_meeting(
    current_user: CurrentUser,
    db: DBSession,
    audio: UploadFile = File(...),
    title: str | None = Form(default=None),
):
    # 1. 驗證檔案類型
    if audio.content_type and not any(audio.content_type.startswith(p) for p in AUDIO_MIME_PREFIXES):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"檔案類型不支援:{audio.content_type}(請上傳音訊檔)",
        )

    # 2. 讀檔內容(限制大小)
    content = await audio.read()
    if len(content) > MAX_AUDIO_SIZE:
        raise HTTPException(
            status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
            detail=f"檔案太大(>200MB)",
        )
    if len(content) == 0:
        raise HTTPException(status_code=400, detail="檔案是空的")

    # 3. 存到磁碟(用 UUID 當檔名避免衝突)
    file_id = uuid.uuid4().hex
    suffix = Path(audio.filename or "").suffix.lower() or ".bin"
    saved_path = UPLOAD_DIR / f"{file_id}{suffix}"
    saved_path.write_bytes(content)

    # 4. 建 Meeting record
    meeting = Meeting(
        title=title or (audio.filename or "未命名會議").replace(suffix, ""),
        status="uploaded",
        audio_path=str(saved_path),
        audio_size_bytes=len(content),
        audio_mime_type=audio.content_type,
        created_by=current_user.id,
    )
    db.add(meeting)
    await db.commit()
    await db.refresh(meeting)

    # 5. 觸發背景處理(不阻塞回應)
    trigger_meeting_processing(meeting.id)

    return meeting


@router.get("", response_model=list[MeetingPublic], summary="列出最近會議")
async def list_meetings(
    current_user: CurrentUser,
    db: DBSession,
    limit: int = 50,
):
    stmt = (
        select(Meeting)
        .where(Meeting.deleted_at.is_(None))
        .order_by(Meeting.created_at.desc())
        .limit(min(limit, 200))
    )
    return list((await db.execute(stmt)).scalars().all())


@router.get("/{meeting_id}", response_model=MeetingDetail, summary="會議詳情")
async def get_meeting(
    meeting_id: uuid.UUID,
    current_user: CurrentUser,
    db: DBSession,
):
    stmt = (
        select(Meeting)
        .options(
            selectinload(Meeting.summary),
            selectinload(Meeting.transcripts),
            selectinload(Meeting.decisions),
            selectinload(Meeting.action_items),
        )
        .where(Meeting.id == meeting_id, Meeting.deleted_at.is_(None))
    )
    meeting = (await db.execute(stmt)).scalar_one_or_none()
    if meeting is None:
        raise HTTPException(status_code=404, detail="找不到此會議")
    # 排序逐字稿
    meeting.transcripts.sort(key=lambda t: t.order_index)
    meeting.decisions.sort(key=lambda d: d.order_index)
    meeting.action_items.sort(key=lambda a: a.order_index)
    return meeting


@router.post(
    "/{meeting_id}/action-items/{action_item_id}/convert",
    summary="把 action item 轉成正式 task",
)
async def convert_action_item_to_task(
    meeting_id: uuid.UUID,
    action_item_id: uuid.UUID,
    current_user: CurrentUser,
    db: DBSession,
) -> dict:
    """一鍵把會議裡抽出的待辦事項變成 Task。"""
    stmt = select(MeetingActionItem).where(
        MeetingActionItem.id == action_item_id,
        MeetingActionItem.meeting_id == meeting_id,
    )
    item = (await db.execute(stmt)).scalar_one_or_none()
    if item is None:
        raise HTTPException(status_code=404, detail="找不到此 action item")
    if item.converted_task_id:
        raise HTTPException(status_code=400, detail="此項已轉成任務")

    # 解析 due_date
    due = None
    if item.suggested_due_date:
        try:
            due = date_type.fromisoformat(item.suggested_due_date)
        except ValueError:
            due = None

    task = Task(
        title=item.description[:480],
        description=f"來自會議「{(await db.execute(select(Meeting.title).where(Meeting.id == meeting_id))).scalar_one()}」自動產出",
        status="todo",
        priority="medium",
        due_date=due,
        created_by=current_user.id,
        assignee_id=item.suggested_assignee_id,
    )
    db.add(task)
    await db.flush()
    item.converted_task_id = task.id
    await db.commit()
    return {
        "task_id": str(task.id),
        "action_item_id": str(item.id),
        "message": "已轉成任務",
    }
