import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import type { Authenticator } from '../auth/authenticator.js';
import { AgentHarness } from '../harness/agent-harness.js';
import type { InboundMessage } from '../types/messages.js';
import { randomUUID } from 'crypto';

import type { ProviderConfig } from '../llm/provider.js';

export interface TelegramHandlerConfig {
  authenticator: Authenticator;
  providerConfig: ProviderConfig;
  telegramBotToken: string;
}

interface TelegramUpdate {
  update_id: number;
  message?: {
    message_id: number;
    from: {
      id: number;
      first_name: string;
      username?: string;
    };
    chat: {
      id: number;
      type: string;
    };
    text?: string;
    photo?: Array<{
      file_id: string;
      file_size: number;
    }>;
  };
}

/**
 * Telegram webhook handler
 */
export class TelegramHandler {
  private config: TelegramHandlerConfig;
  private sessions = new Map<string, AgentHarness>();

  constructor(config: TelegramHandlerConfig) {
    this.config = config;
  }

  /**
   * Register Telegram webhook routes
   */
  register(app: FastifyInstance): void {
    app.post('/webhook/telegram', async (request: FastifyRequest, reply: FastifyReply) => {
      await this.handleWebhook(request, reply, app);
    });
  }

  /**
   * Handle Telegram webhook
   */
  private async handleWebhook(
    request: FastifyRequest,
    reply: FastifyReply,
    app: FastifyInstance
  ): Promise<void> {
    const logger = app.log;

    try {
      const update = request.body as TelegramUpdate;

      if (!update.message?.text) {
        // Ignore non-text messages for now
        reply.code(200).send({ ok: true });
        return;
      }

      const telegramUserId = update.message.from.id.toString();
      const chatId = update.message.chat.id;
      const text = update.message.text;

      logger.info({ telegramUserId, chatId, text }, 'Received Telegram message');

      // Authenticate
      const authContext = await this.config.authenticator.authenticateTelegram(telegramUserId);
      if (!authContext) {
        logger.warn({ telegramUserId }, 'Telegram user not authenticated');
        await this.sendTelegramMessage(
          chatId,
          'Please link your Telegram account to Dexorder first.'
        );
        reply.code(200).send({ ok: true });
        return;
      }

      // Get or create harness
      let harness = this.sessions.get(authContext.sessionId);
      if (!harness) {
        harness = new AgentHarness({
          userId: authContext.userId,
          sessionId: authContext.sessionId,
          license: authContext.license,
          providerConfig: this.config.providerConfig,
          logger,
        });
        await harness.initialize();
        this.sessions.set(authContext.sessionId, harness);
      }

      // Process message
      const inboundMessage: InboundMessage = {
        messageId: randomUUID(),
        userId: authContext.userId,
        sessionId: authContext.sessionId,
        content: text,
        timestamp: new Date(),
      };

      const response = await harness.handleMessage(inboundMessage);

      // Send response back to Telegram
      await this.sendTelegramMessage(chatId, response.content);

      reply.code(200).send({ ok: true });
    } catch (error) {
      logger.error({ error }, 'Error handling Telegram webhook');
      reply.code(500).send({ ok: false, error: 'Internal server error' });
    }
  }

  /**
   * Send message to Telegram chat
   */
  private async sendTelegramMessage(chatId: number, text: string): Promise<void> {
    const url = `https://api.telegram.org/bot${this.config.telegramBotToken}/sendMessage`;

    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          chat_id: chatId,
          text,
          parse_mode: 'Markdown',
        }),
      });

      if (!response.ok) {
        throw new Error(`Telegram API error: ${response.statusText}`);
      }
    } catch (error) {
      console.error('Failed to send Telegram message:', error);
      throw error;
    }
  }

  /**
   * Cleanup old sessions (call periodically)
   */
  async cleanupSessions(maxAgeMs = 30 * 60 * 1000): Promise<void> {
    // TODO: Track session last activity and cleanup
    // For now, sessions persist until server restart
  }
}
