import { FastifyInstance } from 'fastify';
import { requireAuth } from '../middleware/auth.js';
import { readRateLimit, writeRateLimit } from '../middleware/rateLimit.js';
import { getPrismaClient } from '../db/prisma.js';

const MAX_SERVER_CHATS = 5;

export async function chatRoutes(fastify: FastifyInstance) {
  // Get client ID from request (for now, use a simple identifier)
  // In production, this could come from auth token, session, etc.
  function getClientId(request: any): string {
    // For now, use a default client ID or extract from headers
    // In the future, this could be from auth token
    return request.headers['x-client-id'] as string || 'default-client';
  }

  // Save chat history (up to MAX_SERVER_CHATS per client)
  fastify.post('/api/chats', {
    preHandler: [requireAuth, writeRateLimit],
  }, async (request, reply) => {
    const body = request.body as any;
    const clientId = getClientId(request);
    const logger = (request as any).logger;

    try {
      const prisma = await getPrismaClient();

      // Check how many chats this client already has
      const existingChats = await prisma.chatHistory.findMany({
        where: { clientId },
        orderBy: { lastMessageAt: 'desc' },
      });

      // If we have MAX_SERVER_CHATS, remove the oldest
      if (existingChats.length >= MAX_SERVER_CHATS) {
        const oldestChat = existingChats[existingChats.length - 1];
        await prisma.chatHistory.delete({
          where: { id: oldestChat.id },
        });
        logger?.info('Removed oldest chat to maintain limit', { clientId, removedId: oldestChat.id });
      }

      // Create or update chat
      const chatData = {
        clientId,
        agentName: body.agentName,
        agentDescription: body.agentDescription || null,
        messages: body.messages || [],
        lastMessageAt: new Date(body.lastMessageAt || Date.now()),
      };

      // If body.id exists, try to update; otherwise create new
      let chat;
      if (body.id) {
        try {
          chat = await prisma.chatHistory.update({
            where: { id: body.id },
            data: chatData,
          });
        } catch {
          // If update fails (not found), create new
          chat = await prisma.chatHistory.create({
            data: chatData,
          });
        }
      } else {
        chat = await prisma.chatHistory.create({
          data: chatData,
        });
      }

      logger?.info('Chat saved to server', { chatId: chat.id, clientId });

      reply.status(201);
      return {
        success: true,
        chat: {
          id: chat.id,
          agentName: chat.agentName,
          agentDescription: chat.agentDescription,
          messages: chat.messages,
          createdAt: chat.createdAt,
          lastMessageAt: chat.lastMessageAt,
        },
      };
    } catch (error: any) {
      logger?.error('Failed to save chat', { error: error.message });
      return reply.status(500).send({
        error: 'Failed to save chat',
        message: error.message,
      });
    }
  });

  // List all chats for this client
  fastify.get('/api/chats', {
    preHandler: [requireAuth, readRateLimit],
  }, async (request, reply) => {
    const clientId = getClientId(request);
    const logger = (request as any).logger;

    try {
      const prisma = await getPrismaClient();

      const chats = await prisma.chatHistory.findMany({
        where: { clientId },
        orderBy: { lastMessageAt: 'desc' },
        take: MAX_SERVER_CHATS,
      });

      return {
        success: true,
        chats: chats.map(chat => ({
          id: chat.id,
          agentName: chat.agentName,
          agentDescription: chat.agentDescription,
          messages: chat.messages,
          createdAt: chat.createdAt,
          lastMessageAt: chat.lastMessageAt,
        })),
        count: chats.length,
        max: MAX_SERVER_CHATS,
      };
    } catch (error: any) {
      logger?.error('Failed to list chats', { error: error.message });
      return reply.status(500).send({
        error: 'Failed to list chats',
        message: error.message,
      });
    }
  });

  // Get a specific chat by ID
  fastify.get('/api/chats/:id', {
    preHandler: [requireAuth, readRateLimit],
  }, async (request, reply) => {
    const { id } = request.params as { id: string };
    const clientId = getClientId(request);
    const logger = (request as any).logger;

    try {
      const prisma = await getPrismaClient();

      const chat = await prisma.chatHistory.findFirst({
        where: {
          id,
          clientId, // Ensure client owns this chat
        },
      });

      if (!chat) {
        return reply.status(404).send({
          error: 'Chat not found',
        });
      }

      return {
        success: true,
        chat: {
          id: chat.id,
          agentName: chat.agentName,
          agentDescription: chat.agentDescription,
          messages: chat.messages,
          createdAt: chat.createdAt,
          lastMessageAt: chat.lastMessageAt,
        },
      };
    } catch (error: any) {
      logger?.error('Failed to get chat', { error: error.message });
      return reply.status(500).send({
        error: 'Failed to get chat',
        message: error.message,
      });
    }
  });
}

