import {
  Controller,
  Get,
  Post,
  Delete,
  Param,
  Body,
  Headers,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import { ConversationService } from '../../application/services/conversation.service';
import { CreateConversationDto, SendMessageDto } from '../../application/dtos/conversation.dto';

@Controller('conversations')
export class ConversationController {
  constructor(private conversationService: ConversationService) {}

  /**
   * Extract client IP from headers (supports proxies)
   */
  private extractClientIp(
    xForwardedFor?: string,
    xRealIp?: string,
  ): string | undefined {
    // X-Forwarded-For can contain multiple IPs, take the first one (original client)
    if (xForwardedFor) {
      const ips = xForwardedFor.split(',').map((ip) => ip.trim());
      return ips[0] || undefined;
    }
    return xRealIp || undefined;
  }

  /**
   * Create a new conversation
   */
  @Post()
  @HttpCode(HttpStatus.CREATED)
  async createConversation(
    @Headers('x-user-id') userId: string,
    @Headers('x-forwarded-for') xForwardedFor: string,
    @Headers('x-real-ip') xRealIp: string,
    @Headers('user-agent') userAgent: string,
    @Body() dto: CreateConversationDto,
  ) {
    // Build deviceInfo from headers and body
    const clientIp = this.extractClientIp(xForwardedFor, xRealIp);
    const deviceInfo = {
      ip: clientIp || dto.deviceInfo?.ip,
      userAgent: userAgent || dto.deviceInfo?.userAgent,
      fingerprint: dto.deviceInfo?.fingerprint,
      region: dto.deviceInfo?.region,
    };

    const conversation = await this.conversationService.createConversation({
      userId,
      title: dto.title,
      deviceInfo,
    });

    return {
      success: true,
      data: conversation,
    };
  }

  /**
   * Get user's conversations
   */
  @Get()
  async getConversations(@Headers('x-user-id') userId: string) {
    const conversations = await this.conversationService.getUserConversations(userId);

    return {
      success: true,
      data: conversations,
    };
  }

  /**
   * Get a specific conversation
   */
  @Get(':id')
  async getConversation(
    @Headers('x-user-id') userId: string,
    @Param('id') conversationId: string,
  ) {
    const conversation = await this.conversationService.getConversation(
      conversationId,
      userId,
    );

    return {
      success: true,
      data: conversation,
    };
  }

  /**
   * Get conversation messages
   */
  @Get(':id/messages')
  async getMessages(
    @Headers('x-user-id') userId: string,
    @Param('id') conversationId: string,
  ) {
    const messages = await this.conversationService.getMessages(
      conversationId,
      userId,
    );

    return {
      success: true,
      data: messages,
    };
  }

  /**
   * Send a message (non-streaming HTTP endpoint)
   * For streaming, use WebSocket
   */
  @Post(':id/messages')
  async sendMessage(
    @Headers('x-user-id') userId: string,
    @Param('id') conversationId: string,
    @Body() dto: SendMessageDto,
  ) {
    let fullResponse = '';

    for await (const chunk of this.conversationService.sendMessage({
      conversationId,
      userId,
      content: dto.content,
    })) {
      if (chunk.type === 'text' && chunk.content) {
        fullResponse += chunk.content;
      }
    }

    return {
      success: true,
      data: {
        response: fullResponse,
      },
    };
  }

  /**
   * End a conversation
   */
  @Post(':id/end')
  @HttpCode(HttpStatus.OK)
  async endConversation(
    @Headers('x-user-id') userId: string,
    @Param('id') conversationId: string,
  ) {
    await this.conversationService.endConversation(conversationId, userId);

    return {
      success: true,
      message: 'Conversation ended',
    };
  }

  /**
   * Delete a conversation
   */
  @Delete(':id')
  @HttpCode(HttpStatus.OK)
  async deleteConversation(
    @Headers('x-user-id') userId: string,
    @Param('id') conversationId: string,
  ) {
    await this.conversationService.deleteConversation(conversationId, userId);

    return {
      success: true,
      message: 'Conversation deleted',
    };
  }
}
