import type { Logger } from './logger.js';

export class TelegramNotifier {
  private apiBase: string;
  private chatId: string;
  private enabled: boolean;

  constructor(botToken: string, chatId: string) {
    this.apiBase = `https://api.telegram.org/bot${botToken}`;
    this.chatId = chatId;
    this.enabled = Boolean(botToken && chatId);
  }

  async send(text: string, logger: Logger): Promise<boolean> {
    if (!this.enabled) {
      logger.warn('Telegram not configured — notification skipped');
      return false;
    }

    try {
      const response = await fetch(`${this.apiBase}/sendMessage`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          chat_id: this.chatId,
          text,
          parse_mode: 'Markdown',
        }),
        signal: AbortSignal.timeout(10_000),
      });

      if (!response.ok) {
        const body = await response.text();
        // If Markdown parsing failed, retry without parse_mode
        if (response.status === 400 && body.includes("can't parse entities")) {
          logger.warn('Telegram Markdown parse error, retrying as plain text');
          const retryResp = await fetch(`${this.apiBase}/sendMessage`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ chat_id: this.chatId, text }),
            signal: AbortSignal.timeout(10_000),
          });
          return retryResp.ok;
        }
        logger.error('Telegram API error', { status: response.status, body });
        return false;
      }

      return true;
    } catch (err) {
      logger.error('Failed to send Telegram notification', {
        error: err instanceof Error ? err.message : String(err),
      });
      return false;
    }
  }



  /** Ask user via InnerVoice bridge and return answer, or null on timeout/error */
  async askViaBridge(question: string, logger: Logger, timeoutMs = 120_000): Promise<string | null> {
    try {
      const response = await fetch('http://localhost:3456/ask', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ question, timeout: timeoutMs }),
        signal: AbortSignal.timeout(timeoutMs + 5_000),
      });

      if (!response.ok) {
        logger.warn('Bridge /ask failed', { status: response.status });
        return null;
      }

      const data = await response.json() as { answer?: string };
      return data.answer ?? null;
    } catch (err) {
      logger.warn('Bridge /ask error', {
        error: err instanceof Error ? err.message : String(err),
      });
      return null;
    }
  }

  /** Create a Claude task via InnerVoice bridge */
  async createTaskViaBridge(message: string, logger: Logger): Promise<boolean> {
    try {
      const response = await fetch('http://localhost:3456/tasks', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ message }),
        signal: AbortSignal.timeout(10_000),
      });

      if (!response.ok) {
        logger.error('Bridge /tasks failed', { status: response.status });
        return false;
      }

      const data = await response.json() as { success?: boolean; task?: { id: number } };
      if (data.success) {
        logger.info('Task created via bridge', { taskId: data.task?.id });
      }
      return data.success ?? false;
    } catch (err) {
      logger.error('Bridge /tasks error', {
        error: err instanceof Error ? err.message : String(err),
      });
      return false;
    }
  }

  formatServiceDown(
    serviceName: string,
    error: string,
    consecutiveFailures: number,
    critical: boolean,
  ): string {
    const icon = critical ? '🔴 *КРИТИЧЕСКАЯ ИНФРАСТРУКТУРА*' : '🔴 *СЕРВИС НЕДОСТУПЕН*';
    const time = new Date().toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' });
    const lines = [
      icon,
      '',
      `*Сервис:* ${serviceName}`,
      `*Ошибка:* ${error}`,
      `*Время:* ${time}`,
      `*Последовательных ошибок:* ${consecutiveFailures}`,
    ];
    if (critical) {
      lines.push('', '⚠️ _Это влияет на ВСЕ сервисы платформы!_');
    }
    return lines.join('\n');
  }

  formatAutoFix(serviceName: string, action: string, success: boolean, output: string): string {
    const result = success ? 'Выполнено' : 'Ошибка';
    const time = new Date().toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' });
    return [
      '🔧 *АВТОИСПРАВЛЕНИЕ*',
      '',
      `*Сервис:* ${serviceName}`,
      `*Действие:* ${action}`,
      `*Результат:* ${result}`,
      output ? `*Вывод:* \`${output.slice(0, 200)}\`` : '',
      `*Время:* ${time}`,
      '',
      '_Проверка через 60 секунд..._',
    ]
      .filter(Boolean)
      .join('\n');
  }

  formatRecovered(serviceName: string, downtimeMs: number): string {
    const time = new Date().toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' });
    const minutes = Math.ceil(downtimeMs / 60_000);
    return [
      '🟢 *СЕРВИС ВОССТАНОВЛЕН*',
      '',
      `*Сервис:* ${serviceName}`,
      `*Время простоя:* ~${minutes} мин`,
      `*Восстановлен в:* ${time}`,
    ].join('\n');
  }

  formatFlapping(serviceName: string): string {
    const time = new Date().toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' });
    return [
      '⚠️ *НЕСТАБИЛЬНЫЙ СЕРВИС*',
      '',
      `*Сервис:* ${serviceName}`,
      '*Статус:* Нестабильный (вкл/выкл за последние 10 мин)',
      '*Алерты приостановлены* до стабилизации',
      `*Время:* ${time}`,
    ].join('\n');
  }

  formatDeployPaused(): string {
    return ['⏸ *Мониторинг приостановлен* — идёт деплой', '', '_Проверки возобновятся после завершения._'].join(
      '\n',
    );
  }

  formatStarted(intervalMs: number): string {
    const seconds = Math.round(intervalMs / 1000);
    return `🟢 *Мониторинг запущен*\nИнтервал проверок: ${seconds} сек`;
  }

  formatEndpointResolved(serviceName: string, endpoints: string[]): string {
    const list = endpoints.map((ep) => `  • \`${ep}\``).join('\n');
    return [
      '✅ *API-ЭНДПОИНТ РЕАЛИЗОВАН*',
      '',
      `*Сервис:* ${serviceName}`,
      list,
      '',
      '_Убрано из бэклога._',
    ].join('\n');
  }

  formatApiErrors(
    serviceName: string,
    serverErrors: { endpoint: string; page: string; error?: string }[],
    forbidden: { endpoint: string; page: string; error?: string }[],
  ): string {
    const time = new Date().toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' });
    const lines: string[] = ['🔴 ОШИБКИ API', '', `Сервис: ${serviceName}`];

    if (serverErrors.length > 0) {
      lines.push('', 'Серверные ошибки (500):');
      for (const ep of serverErrors) {
        lines.push(`  - ${ep.endpoint} (${ep.page}) — ${ep.error ?? 'Internal Server Error'}`);
      }
    }

    if (forbidden.length > 0) {
      lines.push('', 'Ошибки доступа (403):');
      for (const ep of forbidden) {
        lines.push(`  - ${ep.endpoint} (${ep.page}) — ${ep.error ?? 'Forbidden'}`);
      }
    }

    lines.push('', `Время: ${time}`);
    return lines.join('\n');
  }

  formatMultipleDown(count: number, total: number): string {
    const time = new Date().toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' });
    return [
      '🔴 *МНОЖЕСТВЕННЫЙ СБОЙ*',
      '',
      `*Недоступно сервисов:* ${count} из ${total}`,
      '*Возможна проблема на уровне хоста!*',
      `*Время:* ${time}`,
    ].join('\n');
  }
}
