import {
  Controller,
  Post,
  Get,
  Delete,
  Patch,
  Body,
  Param,
  Req,
  Res,
  Header,
  UnauthorizedException,
} from '@nestjs/common';
import { Response } from 'express';
import { AIService } from './ai.service';
import { ChatMessageDto } from './dto/chat-message.dto';
import { FeedbackDto } from './dto/feedback.dto';
import { Public } from '../auth/decorators/public.decorator';

@Controller('api/v1/ai')
export class AIController {
  constructor(private readonly aiService: AIService) {}

  @Post('chat')
  async chat(@Req() req: any, @Body() chatDto: ChatMessageDto) {
    const userId = req.user?.userId;
    if (!userId) {
      throw new UnauthorizedException('Authentication required');
    }
    const response = await this.aiService.chat(userId, chatDto);
    return {
      success: true,
      data: response,
    };
  }

  /**
   * Streaming chat endpoint
   * Returns Server-Sent Events (SSE) for real-time streaming responses
   */
  @Post('chat/stream')
  @Header('Content-Type', 'text/event-stream')
  @Header('Cache-Control', 'no-cache')
  @Header('Connection', 'keep-alive')
  async chatStream(
    @Req() req: any,
    @Body() chatDto: ChatMessageDto,
    @Res() res: Response,
  ) {
    const userId = req.user?.userId;
    if (!userId) {
      res.status(401).json({ error: 'Authentication required' });
      return;
    }

    // Set up SSE headers
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');
    res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering

    try {
      // Stream the response
      await this.aiService.chatStream(userId, chatDto, (chunk) => {
        // Send each chunk as an SSE event
        res.write(`data: ${JSON.stringify(chunk)}\n\n`);
      });

      // Send completion event
      res.write(`data: ${JSON.stringify({ type: 'done' })}\n\n`);
      res.end();
    } catch (error) {
      // Send error event
      res.write(
        `data: ${JSON.stringify({ type: 'error', message: error.message })}\n\n`,
      );
      res.end();
    }
  }

  @Get('conversations')
  async getConversations(@Req() req: any) {
    const userId = req.user?.userId;
    if (!userId) {
      throw new UnauthorizedException('Authentication required');
    }
    const conversations = await this.aiService.getUserConversations(userId);
    return {
      success: true,
      data: { conversations },
    };
  }

  @Get('conversations/:id')
  async getConversation(@Req() req: any, @Param('id') conversationId: string) {
    const userId = req.user?.userId;
    if (!userId) {
      throw new UnauthorizedException('Authentication required');
    }
    const conversation = await this.aiService.getConversation(
      userId,
      conversationId,
    );
    return {
      success: true,
      data: { conversation },
    };
  }

  @Delete('conversations/:id')
  async deleteConversation(
    @Req() req: any,
    @Param('id') conversationId: string,
  ) {
    await this.aiService.deleteConversation(req.user.userId, conversationId);
    return {
      success: true,
      message: 'Conversation deleted successfully',
    };
  }

  @Patch('conversations/:id/group')
  async updateConversationGroup(
    @Req() req: any,
    @Param('id') conversationId: string,
    @Body() body: { groupName: string | null },
  ) {
    const userId = req.user?.userId;
    if (!userId) {
      throw new UnauthorizedException('Authentication required');
    }
    const conversation = await this.aiService.updateConversationGroup(
      userId,
      conversationId,
      body.groupName,
    );
    return {
      success: true,
      data: { conversation },
    };
  }

  @Get('groups')
  async getConversationGroups(@Req() req: any) {
    const userId = req.user?.userId;
    if (!userId) {
      throw new UnauthorizedException('Authentication required');
    }
    const groups = await this.aiService.getConversationGroups(userId);
    return {
      success: true,
      data: { groups },
    };
  }

  @Public() // Public for testing
  @Get('provider-status')
  async getProviderStatus() {
    const status = this.aiService.getProviderStatus();
    return {
      success: true,
      data: status,
    };
  }

  @Post('feedback')
  async submitFeedback(@Req() req: any, @Body() feedbackDto: FeedbackDto) {
    const userId = req.user?.userId;
    if (!userId) {
      throw new UnauthorizedException('Authentication required');
    }
    await this.aiService.submitFeedback(
      userId,
      feedbackDto.conversationId,
      feedbackDto.messageId,
      feedbackDto.feedbackType,
      feedbackDto.feedbackText,
    );
    return {
      success: true,
      message: 'Feedback submitted successfully',
    };
  }

  // Embeddings testing endpoints
  @Public() // Public for testing
  @Post('test/embeddings/generate')
  async testGenerateEmbedding(@Body() body: { text: string }) {
    const embeddingsService = this.aiService['embeddingsService'];
    const result = await embeddingsService.generateEmbedding(body.text);
    return {
      success: true,
      data: {
        dimensions: result.embedding.length,
        tokenCount: result.tokenCount,
        model: result.model,
        preview: result.embedding.slice(0, 5), // First 5 dimensions
      },
    };
  }

  @Public() // Public for testing
  @Post('test/embeddings/search')
  async testSearchSimilar(
    @Body()
    body: {
      query: string;
      userId?: string;
      threshold?: number;
      limit?: number;
    },
  ) {
    const embeddingsService = this.aiService['embeddingsService'];
    const userId = body.userId || 'test_user_123';
    const results = await embeddingsService.searchSimilarConversations(
      body.query,
      userId,
      {
        similarityThreshold: body.threshold || 0.7,
        limit: body.limit || 5,
      },
    );
    return {
      success: true,
      data: { results },
    };
  }

  @Public() // Public for testing
  @Get('test/embeddings/health')
  async testEmbeddingsHealth() {
    const embeddingsService = this.aiService['embeddingsService'];
    const health = await embeddingsService.healthCheck();
    return {
      success: true,
      data: health,
    };
  }

  @Public() // Public for testing
  @Get('test/embeddings/stats/:userId')
  async testEmbeddingsStats(@Param('userId') userId: string) {
    const embeddingsService = this.aiService['embeddingsService'];
    const stats = await embeddingsService.getUserEmbeddingStats(
      userId || 'test_user_123',
    );
    return {
      success: true,
      data: stats,
    };
  }
}
