import {
  BadRequestException,
  Body,
  Controller,
  HttpCode,
  Param,
  Post,
  Request,
  Res,
} from '@nestjs/common';
import type { Response, Request as ExpressRequest } from 'express';
import { SkipTransform } from '@common/decorators/skip-transform.decorator';
import { AgentMessagesService } from '../services/messages.service';
import { resolveActor } from '../utils/auth-resolution.util';

@Controller('agent/messages')
export class AgentMessagesController {
  constructor(private readonly messagesService: AgentMessagesService) {}

  /**
   * POST /api/v1/agent/messages —— 同步版本（一次性返回全部消息）。
   */
  @Post()
  async postMessage(
    @Body() body: { sessionId: string; prompt: string; organizationId?: string },
    @Request() req: ExpressRequest,
  ) {
    if (!body.sessionId || !body.prompt) {
      throw new BadRequestException('sessionId and prompt are required');
    }
    const { orgId, userId } = resolveActor(req, body.organizationId);
    return this.messagesService.runTurn({
      sessionId: body.sessionId,
      organizationId: orgId,
      userId,
      prompt: body.prompt,
    });
  }

  /**
   * POST /api/v1/agent/messages/stream —— SSE 流式版本（PR4a）。
   * 前端用 fetch + ReadableStream 消费 text/event-stream。
   */
  @Post('stream')
  @SkipTransform()
  async postMessageStream(
    @Body() body: { sessionId: string; prompt: string; organizationId?: string },
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    if (!body.sessionId || !body.prompt) {
      throw new BadRequestException('sessionId and prompt are required');
    }
    const { orgId, userId } = resolveActor(req, body.organizationId);

    res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
    res.setHeader('Cache-Control', 'no-cache, no-transform');
    res.setHeader('Connection', 'keep-alive');
    res.setHeader('X-Accel-Buffering', 'no');
    res.flushHeaders?.();

    const writeEvent = (type: string, data: unknown) => {
      try {
        res.write(`event: ${type}\n`);
        res.write(`data: ${JSON.stringify(data)}\n\n`);
        (res as { flush?: () => void }).flush?.();
      } catch {
        // client disconnected
      }
    };

    try {
      for await (const ev of this.messagesService.runTurnStream({
        sessionId: body.sessionId,
        organizationId: orgId,
        userId,
        prompt: body.prompt,
      })) {
        writeEvent(ev.type, ev);
        if (ev.type === 'done' || ev.type === 'error') break;
      }
    } catch (err) {
      writeEvent('error', { message: (err as Error).message });
    } finally {
      res.end();
    }
  }

  /**
   * POST /api/v1/agent/messages/:turnId/cancel —— 取消正在跑的 turn。
   * 跑中的 TAOR loop 下一轮迭代会读到 abort 信号，graceful break；
   * turn 已结束或不存在则返回 cancelled:false。跨 org 拒绝。
   */
  @Post(':turnId/cancel')
  @HttpCode(200)
  async cancelTurn(
    @Param('turnId') turnId: string,
    @Request() req: ExpressRequest,
  ) {
    const { orgId } = resolveActor(req);
    return this.messagesService.cancelTurn(turnId, orgId);
  }
}
