import { Telegraf } from 'telegraf';
import { message } from 'telegraf/filters';
import type { Env } from './env.js';
import { createChatGuard } from './guard.js';
import { TrelloClient } from './trello/client.js';
import { openDb } from './db/sqlite.js';
import { insertMessage } from './db/messages.js';
import { helpHandler } from './commands/help.js';
import { makeListHandler } from './commands/list.js';
import { makeBtwHandler } from './commands/btw.js';
import { makeTodoHandler } from './commands/todo.js';
import { makeDoingHandler } from './commands/doing.js';
import { makeDoneHandler } from './commands/done.js';
import { makeStatusHandler } from './commands/status.js';
import { makeSubHandler } from './commands/sub.js';
import { makeSummarizeHandler } from './commands/summarize.js';
import { makeSearchHandler } from './commands/search.js';
import { makeVoiceHandler } from './commands/voice.js';
import { makeMentionHandler } from './commands/mention.js';
import { makeDynamicCommandHandler } from './dynamic-commands.js';
import { logger } from './utils/logger.js';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));

export function createBot(env: Env): Telegraf {
  const bot = new Telegraf(env.TELEGRAM_BOT_TOKEN);

  const trello = new TrelloClient(env.TRELLO_API_KEY, env.TRELLO_TOKEN, env.TRELLO_BOARD_ID);
  const db = openDb(join(__dirname, '../data/messages.db'));

  // Security: silently ignore unauthorized chats
  bot.use(createChatGuard(env.TELEGRAM_ALLOWED_CHAT_IDS));

  // Reply interceptor: capture bot replies into the message log
  bot.use(async (ctx, next) => {
    const origReply = ctx.reply.bind(ctx);
    (ctx as typeof ctx & { reply: typeof ctx.reply }).reply = async (text: string, extra?: Parameters<typeof ctx.reply>[1]) => {
      const result = await origReply(text, extra);
      try {
        const chatId = ctx.chat?.id;
        const botInfo = ctx.botInfo;
        if (chatId && typeof text === 'string' && text.trim()) {
          insertMessage(db, {
            message_id: result.message_id,
            chat_id: chatId,
            user_id: botInfo?.id ?? 0,
            username: botInfo?.username ?? null,
            first_name: botInfo?.first_name ?? 'Bot',
            text,
            date: Math.floor(Date.now() / 1000),
          });
        }
      } catch { /* best-effort */ }
      return result;
    };
    return next();
  });

  // Message logger: store every text message for /summarize
  bot.on(message('text'), (ctx, next) => {
    try {
      const from = ctx.message.from;
      insertMessage(db, {
        message_id: ctx.message.message_id,
        chat_id: ctx.message.chat.id,
        user_id: from?.id ?? null,
        username: from?.username ?? null,
        first_name: from?.first_name ?? null,
        text: ctx.message.text,
        date: ctx.message.date,
      });
    } catch (err) {
      logger.debug('message log failed', { error: String(err) });
    }
    return next();
  });

  // Dynamic commands fetched from botmaster
  bot.use(makeDynamicCommandHandler());

  // Commands
  bot.command('help', helpHandler);
  bot.command('list', makeListHandler(trello));
  bot.command('btw', makeBtwHandler(trello, env.TRELLO_BTW_LIST_ID));
  bot.command('todo', makeTodoHandler(trello));
  bot.command('doing', makeDoingHandler(trello));
  bot.command('done', makeDoneHandler(trello));
  bot.command('status', makeStatusHandler(trello, env.GOOGLE_API_KEY));
  bot.command(
    'sub',
    makeSubHandler({
      claudeBin: env.CLAUDE_BIN,
      repoPath: env.HETZI_REPO_PATH,
      timeoutMs: env.CLAUDE_TIMEOUT_MS,
    }),
  );
  bot.command(
    'summarize',
    makeSummarizeHandler({
      db,
      chatId: env.TELEGRAM_ALLOWED_CHAT_IDS[0]!,
      googleApiKey: env.GOOGLE_API_KEY,
    }),
  );

  bot.command(
    'search',
    makeSearchHandler({
      db,
      chatId: env.TELEGRAM_ALLOWED_CHAT_IDS[0]!,
      googleApiKey: env.GOOGLE_API_KEY,
    }),
  );

  // @HetziBot mention handler - context-aware Q&A with chat history
  bot.on(
    message('text'),
    makeMentionHandler({
      repoPath: env.HETZI_REPO_PATH,
      trello,
      githubRepo: env.GITHUB_REPO,
      githubToken: env.GITHUB_TOKEN,
      db,
      chatId: env.TELEGRAM_ALLOWED_CHAT_IDS[0]!,
      googleApiKey: env.GOOGLE_API_KEY,
    }),
  );

  // Voice messages: transcribe and store
  bot.on(
    message('voice'),
    makeVoiceHandler({
      db,
      botToken: env.TELEGRAM_BOT_TOKEN,
      googleApiKey: env.GOOGLE_API_KEY,
    }),
  );

  // Global error handler
  bot.catch((err, ctx) => {
    logger.error('Unhandled bot error', {
      error: err instanceof Error ? err.message : String(err),
      chatId: ctx.chat?.id,
      command: ctx.message && 'text' in ctx.message ? ctx.message.text?.split(' ')[0] : undefined,
    });
    ctx.reply('An internal error occurred. Please try again.').catch(() => undefined);
  });

  return bot;
}
