import { FastifyInstance, FastifyPluginOptions } from 'fastify';
import type { DataStore } from '../modules/data-store/index.js';
import type { ConversationEngine } from '../modules/conversation-engine/index.js';
import { createModuleLogger } from '../utils/logger.js';

const log = createModuleLogger('routes-conversations');

interface ConversationRoutesOpts extends FastifyPluginOptions {
  dataStore: DataStore;
  conversationEngine: ConversationEngine;
}

export default async function conversationRoutes(
  app: FastifyInstance,
  opts: ConversationRoutesOpts,
): Promise<void> {
  const { dataStore, conversationEngine } = opts;

  // GET /characters/:id/conversations — List all conversations for a character
  app.get('/characters/:id/conversations', async (request, reply) => {
    const { id } = request.params as { id: string };

    try {
      const character = await dataStore.getCharacter(id);
      if (!character) {
        return reply.status(404).send({
          success: false,
          error: `Character not found: ${id}`,
        });
      }

      const conversations = await dataStore.listConversations(id);

      const summaries = conversations.map((c) => {
        let lastMessagePreview: string | null = null;
        if (c.messages && c.messages.length > 0) {
          const lastMsg = c.messages[c.messages.length - 1];
          lastMessagePreview = lastMsg.content ? lastMsg.content.substring(0, 50) : null;
        }
        return {
          telegramUserId: c.telegramUserId,
          userName: c.userName ?? c.userInfo?.name ?? null,
          totalMessages: c.totalMessages,
          totalStarsSpent: c.totalStarsSpent,
          lastActivity: c.lastActivity,
          lastMessagePreview,
        };
      });

      return reply.status(200).send({ success: true, data: summaries });
    } catch (err: any) {
      log.error({ characterId: id, error: err.message }, 'Failed to list conversations');
      return reply.status(500).send({
        success: false,
        error: 'Failed to list conversations',
      });
    }
  });

  // GET /characters/:id/conversations/:userId — Get conversation history for a specific user
  app.get('/characters/:id/conversations/:userId', async (request, reply) => {
    const { id, userId } = request.params as { id: string; userId: string };

    try {
      const character = await dataStore.getCharacter(id);
      if (!character) {
        return reply.status(404).send({
          success: false,
          error: `Character not found: ${id}`,
        });
      }

      const numericUserId = Number(userId);
      if (Number.isNaN(numericUserId)) {
        return reply.status(400).send({
          success: false,
          error: 'Invalid userId: must be a number',
        });
      }

      const history = await dataStore.getConversationHistory(id, numericUserId);
      if (!history) {
        return reply.status(404).send({
          success: false,
          error: `Conversation not found for user: ${userId}`,
        });
      }

      return reply.status(200).send({ success: true, data: history });
    } catch (err: any) {
      log.error({ characterId: id, userId, error: err.message }, 'Failed to get conversation');
      return reply.status(500).send({
        success: false,
        error: 'Failed to get conversation history',
      });
    }
  });

  // GET /characters/:id/conversations/:userId/messages — Paginated message list
  app.get('/characters/:id/conversations/:userId/messages', async (request, reply) => {
    const { id, userId } = request.params as { id: string; userId: string };
    const { page: pageStr, limit: limitStr } = request.query as { page?: string; limit?: string };

    try {
      const character = await dataStore.getCharacter(id);
      if (!character) {
        return reply.status(404).send({
          success: false,
          error: `Character not found: ${id}`,
        });
      }

      const numericUserId = Number(userId);
      if (Number.isNaN(numericUserId)) {
        return reply.status(400).send({
          success: false,
          error: 'Invalid userId: must be a number',
        });
      }

      const history = await dataStore.getConversationHistory(id, numericUserId);
      if (!history) {
        return reply.status(404).send({
          success: false,
          error: `Conversation not found for user: ${userId}`,
        });
      }

      const page = Math.max(1, parseInt(pageStr || '1', 10) || 1);
      const limit = Math.min(100, Math.max(1, parseInt(limitStr || '50', 10) || 50));

      // Messages sorted by timestamp ascending (oldest first)
      const sorted = [...history.messages].sort(
        (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),
      );

      const total = sorted.length;
      const startIndex = (page - 1) * limit;
      const paginatedMessages = sorted.slice(startIndex, startIndex + limit);
      const hasMore = startIndex + limit < total;

      return reply.status(200).send({
        success: true,
        data: {
          messages: paginatedMessages,
          total,
          page,
          limit,
          hasMore,
        },
      });
    } catch (err: any) {
      log.error({ characterId: id, userId, error: err.message }, 'Failed to get paginated messages');
      return reply.status(500).send({
        success: false,
        error: 'Failed to get conversation messages',
      });
    }
  });

  // DELETE /characters/:id/conversations/:userId — Delete conversation history
  app.delete('/characters/:id/conversations/:userId', async (request, reply) => {
    const { id, userId } = request.params as { id: string; userId: string };

    try {
      const character = await dataStore.getCharacter(id);
      if (!character) {
        return reply.status(404).send({
          success: false,
          error: `Character not found: ${id}`,
        });
      }

      const numericUserId = Number(userId);
      if (Number.isNaN(numericUserId)) {
        return reply.status(400).send({
          success: false,
          error: 'Invalid userId: must be a number',
        });
      }

      const deleted = await dataStore.deleteConversation(id, numericUserId);
      if (!deleted) {
        return reply.status(404).send({
          success: false,
          error: `Conversation not found for user: ${userId}`,
        });
      }

      return reply.status(200).send({
        success: true,
        data: { message: `Conversation with user ${userId} deleted` },
      });
    } catch (err: any) {
      log.error({ characterId: id, userId, error: err.message }, 'Failed to delete conversation');
      return reply.status(500).send({
        success: false,
        error: 'Failed to delete conversation',
      });
    }
  });
}
