"""
Lyric API Router

이 모듈은 가사 관련 API 엔드포인트를 정의합니다.
모든 엔드포인트는 재사용 가능하도록 설계되었습니다.

엔드포인트 목록:
    - POST /lyric/generate: 가사 생성
    - GET /lyric/status/{task_id}: 가사 생성 상태 조회
    - GET /lyric/{task_id}: 가사 상세 조회
    - GET /lyrics: 가사 목록 조회 (페이지네이션)

사용 예시:
    from app.lyric.api.routers.v1.lyric import router
    app.include_router(router, prefix="/api/v1")

다른 서비스에서 재사용:
    # 이 파일의 헬퍼 함수들을 import하여 사용 가능
    from app.lyric.api.routers.v1.lyric import (
        get_lyric_status_by_task_id,
        get_lyric_by_task_id,
    )

    # 페이지네이션은 pagination 모듈 사용
    from app.utils.pagination import PaginatedResponse, get_paginated
"""

from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.database.session import get_session
from app.home.models import Project
from app.lyric.models import Lyric
from app.lyric.schemas.lyric import (
    GenerateLyricRequest,
    GenerateLyricResponse,
    LyricDetailResponse,
    LyricListItem,
    LyricStatusResponse,
)
from app.lyric.worker.lyric_task import generate_lyric_background
from app.utils.chatgpt_prompt import ChatgptService
from app.utils.pagination import PaginatedResponse, get_paginated

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


# =============================================================================
# Reusable Service Functions (다른 모듈에서 import하여 사용 가능)
# =============================================================================


async def get_lyric_status_by_task_id(
    session: AsyncSession, task_id: str
) -> LyricStatusResponse:
    """task_id로 가사 생성 작업의 상태를 조회합니다.

    Args:
        session: SQLAlchemy AsyncSession
        task_id: 작업 고유 식별자

    Returns:
        LyricStatusResponse: 상태 정보

    Raises:
        HTTPException: 404 - task_id에 해당하는 가사가 없는 경우

    Usage:
        # 다른 서비스에서 사용
        from app.lyric.api.routers.v1.lyric import get_lyric_status_by_task_id

        status_info = await get_lyric_status_by_task_id(session, "some-task-id")
        if status_info.status == "completed":
            # 완료 처리
    """
    print(f"[get_lyric_status_by_task_id] START - task_id: {task_id}")
    result = await session.execute(
        select(Lyric)
        .where(Lyric.task_id == task_id)
        .order_by(Lyric.created_at.desc())
        .limit(1)
    )
    lyric = result.scalar_one_or_none()

    if not lyric:
        print(f"[get_lyric_status_by_task_id] NOT FOUND - task_id: {task_id}")
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"task_id '{task_id}'에 해당하는 가사를 찾을 수 없습니다.",
        )

    status_messages = {
        "processing": "가사 생성 중입니다.",
        "completed": "가사 생성이 완료되었습니다.",
        "failed": "가사 생성에 실패했습니다.",
    }

    print(
        f"[get_lyric_status_by_task_id] SUCCESS - task_id: {task_id}, status: {lyric.status}"
    )
    return LyricStatusResponse(
        task_id=lyric.task_id,
        status=lyric.status,
        message=status_messages.get(lyric.status, "알 수 없는 상태입니다."),
    )


async def get_lyric_by_task_id(
    session: AsyncSession, task_id: str
) -> LyricDetailResponse:
    """task_id로 생성된 가사 상세 정보를 조회합니다.

    Args:
        session: SQLAlchemy AsyncSession
        task_id: 작업 고유 식별자

    Returns:
        LyricDetailResponse: 가사 상세 정보

    Raises:
        HTTPException: 404 - task_id에 해당하는 가사가 없는 경우

    Usage:
        # 다른 서비스에서 사용
        from app.lyric.api.routers.v1.lyric import get_lyric_by_task_id

        lyric = await get_lyric_by_task_id(session, task_id)
    """
    print(f"[get_lyric_by_task_id] START - task_id: {task_id}")
    result = await session.execute(
        select(Lyric)
        .where(Lyric.task_id == task_id)
        .order_by(Lyric.created_at.desc())
        .limit(1)
    )
    lyric = result.scalar_one_or_none()

    if not lyric:
        print(f"[get_lyric_by_task_id] NOT FOUND - task_id: {task_id}")
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"task_id '{task_id}'에 해당하는 가사를 찾을 수 없습니다.",
        )

    print(f"[get_lyric_by_task_id] SUCCESS - task_id: {task_id}, lyric_id: {lyric.id}")
    return LyricDetailResponse(
        id=lyric.id,
        task_id=lyric.task_id,
        project_id=lyric.project_id,
        status=lyric.status,
        lyric_prompt=lyric.lyric_prompt,
        lyric_result=lyric.lyric_result,
        created_at=lyric.created_at,
    )


# =============================================================================
# API Endpoints
# =============================================================================


@router.post(
    "/generate",
    summary="가사 생성",
    description="""
고객 정보를 기반으로 ChatGPT를 이용하여 가사를 생성합니다.
백그라운드에서 비동기로 처리되며, 즉시 task_id를 반환합니다.

## 요청 필드
- **task_id**: 작업 고유 식별자 (이미지 업로드 시 생성된 task_id, 필수)
- **customer_name**: 고객명/가게명 (필수)
- **region**: 지역명 (필수)
- **detail_region_info**: 상세 지역 정보 (선택)
- **language**: 가사 출력 언어 (Korean, English, Chinese, Japanese, Thai, Vietnamese)

## 반환 정보
- **success**: 요청 접수 성공 여부
- **task_id**: 작업 고유 식별자
- **lyric**: null (백그라운드 처리 중)
- **language**: 가사 언어
- **error_message**: 에러 메시지 (요청 접수 실패 시)

## 상태 확인
- GET /lyric/status/{task_id} 로 처리 상태 확인
- GET /lyric/{task_id} 로 생성된 가사 조회

## 사용 예시
```
POST /lyric/generate
{
    "task_id": "0694b716-dbff-7219-8000-d08cb5fce431",
    "customer_name": "스테이 머뭄",
    "region": "군산",
    "detail_region_info": "군산 신흥동 말랭이 마을",
    "language": "Korean"
}
```

## 응답 예시
```json
{
    "success": true,
    "task_id": "0694b716-dbff-7219-8000-d08cb5fce431",
    "lyric": null,
    "language": "Korean",
    "error_message": null
}
```
    """,
    response_model=GenerateLyricResponse,
    responses={
        200: {"description": "가사 생성 요청 접수 성공"},
        500: {"description": "서버 내부 오류"},
    },
)
async def generate_lyric(
    request_body: GenerateLyricRequest,
    background_tasks: BackgroundTasks,
    session: AsyncSession = Depends(get_session),
) -> GenerateLyricResponse:
    """고객 정보를 기반으로 가사를 생성합니다. (백그라운드 처리)"""
    import time

    request_start = time.perf_counter()
    task_id = request_body.task_id

    print(f"[generate_lyric] ========== START ==========")
    print(
        f"[generate_lyric] task_id: {task_id}, "
        f"customer_name: {request_body.customer_name}, "
        f"region: {request_body.region}"
    )

    try:
        # ========== Step 1: ChatGPT 서비스 초기화 및 프롬프트 생성 ==========
        step1_start = time.perf_counter()
        print(f"[generate_lyric] Step 1: 서비스 초기화 및 프롬프트 생성...")

        service = ChatgptService(
            customer_name=request_body.customer_name,
            region=request_body.region,
            detail_region_info=request_body.detail_region_info or "",
            language=request_body.language,
        )
        prompt = service.build_lyrics_prompt()

        step1_elapsed = (time.perf_counter() - step1_start) * 1000
        print(f"[generate_lyric] Step 1 완료 - 프롬프트 {len(prompt)}자 ({step1_elapsed:.1f}ms)")

        # ========== Step 2: Project 테이블에 데이터 저장 ==========
        step2_start = time.perf_counter()
        print(f"[generate_lyric] Step 2: Project 저장...")

        project = Project(
            store_name=request_body.customer_name,
            region=request_body.region,
            task_id=task_id,
            detail_region_info=request_body.detail_region_info,
            language=request_body.language,
        )
        session.add(project)
        await session.commit()
        await session.refresh(project)

        step2_elapsed = (time.perf_counter() - step2_start) * 1000
        print(f"[generate_lyric] Step 2 완료 - project_id: {project.id} ({step2_elapsed:.1f}ms)")

        # ========== Step 3: Lyric 테이블에 데이터 저장 ==========
        step3_start = time.perf_counter()
        print(f"[generate_lyric] Step 3: Lyric 저장 (processing)...")

        lyric = Lyric(
            project_id=project.id,
            task_id=task_id,
            status="processing",
            lyric_prompt=prompt,
            lyric_result=None,
            language=request_body.language,
        )
        session.add(lyric)
        await session.commit()
        await session.refresh(lyric)

        step3_elapsed = (time.perf_counter() - step3_start) * 1000
        print(f"[generate_lyric] Step 3 완료 - lyric_id: {lyric.id} ({step3_elapsed:.1f}ms)")

        # ========== Step 4: 백그라운드 태스크 스케줄링 ==========
        step4_start = time.perf_counter()
        print(f"[generate_lyric] Step 4: 백그라운드 태스크 스케줄링...")

        background_tasks.add_task(
            generate_lyric_background,
            task_id=task_id,
            prompt=prompt,
            language=request_body.language,
        )

        step4_elapsed = (time.perf_counter() - step4_start) * 1000
        print(f"[generate_lyric] Step 4 완료 ({step4_elapsed:.1f}ms)")

        # ========== 완료 ==========
        total_elapsed = (time.perf_counter() - request_start) * 1000
        print(f"[generate_lyric] ========== COMPLETE ==========")
        print(f"[generate_lyric] API 응답 소요시간: {total_elapsed:.1f}ms")
        print(f"[generate_lyric]   - Step 1 (프롬프트 생성): {step1_elapsed:.1f}ms")
        print(f"[generate_lyric]   - Step 2 (Project 저장): {step2_elapsed:.1f}ms")
        print(f"[generate_lyric]   - Step 3 (Lyric 저장): {step3_elapsed:.1f}ms")
        print(f"[generate_lyric]   - Step 4 (태스크 스케줄링): {step4_elapsed:.1f}ms")
        print(f"[generate_lyric] (GPT API 호출은 백그라운드에서 별도 진행)")

        # 5. 즉시 응답 반환
        return GenerateLyricResponse(
            success=True,
            task_id=task_id,
            lyric=None,
            language=request_body.language,
            error_message=None,
        )

    except Exception as e:
        elapsed = (time.perf_counter() - request_start) * 1000
        print(f"[generate_lyric] EXCEPTION - task_id: {task_id}, error: {e} ({elapsed:.1f}ms)")
        await session.rollback()
        return GenerateLyricResponse(
            success=False,
            task_id=task_id,
            lyric=None,
            language=request_body.language,
            error_message=str(e),
        )


@router.get(
    "/status/{task_id}",
    summary="가사 생성 상태 조회",
    description="""
task_id로 가사 생성 작업의 현재 상태를 조회합니다.

## 상태 값
- **processing**: 가사 생성 중
- **completed**: 가사 생성 완료
- **failed**: 가사 생성 실패

## 사용 예시
```
GET /lyric/status/019123ab-cdef-7890-abcd-ef1234567890
```
    """,
    response_model=LyricStatusResponse,
    responses={
        200: {"description": "상태 조회 성공"},
        404: {"description": "해당 task_id를 찾을 수 없음"},
    },
)
async def get_lyric_status(
    task_id: str,
    session: AsyncSession = Depends(get_session),
) -> LyricStatusResponse:
    """task_id로 가사 생성 작업 상태를 조회합니다."""
    return await get_lyric_status_by_task_id(session, task_id)


@router.get(
    "s",
    summary="가사 목록 조회 (페이지네이션)",
    description="""
생성 완료된 가사를 페이지네이션으로 조회합니다.

## 파라미터
- **page**: 페이지 번호 (1부터 시작, 기본값: 1)
- **page_size**: 페이지당 데이터 수 (기본값: 20, 최대: 100)

## 반환 정보
- **items**: 가사 목록 (completed 상태만)
- **total**: 전체 데이터 수
- **page**: 현재 페이지
- **page_size**: 페이지당 데이터 수
- **total_pages**: 전체 페이지 수
- **has_next**: 다음 페이지 존재 여부
- **has_prev**: 이전 페이지 존재 여부

## 사용 예시
```
GET /lyrics                           # 기본 조회 (1페이지, 20개)
GET /lyrics?page=2                    # 2페이지 조회
GET /lyrics?page=1&page_size=50       # 50개씩 조회
```

## 참고
- 생성 완료(completed)된 가사만 조회됩니다.
- processing, failed 상태의 가사는 조회되지 않습니다.
    """,
    response_model=PaginatedResponse[LyricListItem],
    responses={
        200: {"description": "가사 목록 조회 성공"},
    },
)
async def list_lyrics(
    page: int = Query(1, ge=1, description="페이지 번호 (1부터 시작)"),
    page_size: int = Query(20, ge=1, le=100, description="페이지당 데이터 수"),
    session: AsyncSession = Depends(get_session),
) -> PaginatedResponse[LyricListItem]:
    """페이지네이션으로 완료된 가사 목록을 조회합니다."""
    return await get_paginated(
        session=session,
        model=Lyric,
        item_schema=LyricListItem,
        page=page,
        page_size=page_size,
        filters={"status": "completed"},
        order_by="created_at",
        order_desc=True,
    )


@router.get(
    "/{task_id}",
    summary="가사 상세 조회",
    description="""
task_id로 생성된 가사의 상세 정보를 조회합니다.

## 반환 정보
- **id**: 가사 ID
- **task_id**: 작업 고유 식별자
- **project_id**: 프로젝트 ID
- **status**: 처리 상태
- **lyric_prompt**: 가사 생성에 사용된 프롬프트
- **lyric_result**: 생성된 가사 (완료 시)
- **created_at**: 생성 일시

## 사용 예시
```
GET /lyric/019123ab-cdef-7890-abcd-ef1234567890
```
    """,
    response_model=LyricDetailResponse,
    responses={
        200: {"description": "가사 조회 성공"},
        404: {"description": "해당 task_id를 찾을 수 없음"},
    },
)
async def get_lyric_detail(
    task_id: str,
    session: AsyncSession = Depends(get_session),
) -> LyricDetailResponse:
    """task_id로 생성된 가사를 조회합니다."""
    return await get_lyric_by_task_id(session, task_id)
