import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

export type AlertLevel = 'info' | 'warning' | 'critical';

export interface Alert {
  level: AlertLevel;
  /** Short human-readable subject */
  title: string;
  /** Multi-line detail; goes into the alert payload body. */
  body: string;
  /** Optional structured context for downstream filtering/grouping */
  context?: Record<string, unknown>;
}

/**
 * Operational alerter. Today: structured logger output (still visible in
 * stdout / log aggregator). Tomorrow: POST to a webhook (wecom / dingtalk /
 * slack / pagerduty) controlled by env `ALERT_WEBHOOK_URL`.
 *
 * Single seam — every place that needs to alert depends on this service,
 * not on the transport.
 */
@Injectable()
export class AlertService {
  private readonly logger = new Logger(AlertService.name);

  constructor(private readonly config: ConfigService) {}

  async send(alert: Alert): Promise<void> {
    const webhookUrl = this.config.get<string>('alert.webhookUrl') ?? '';
    const line = `[ALERT ${alert.level.toUpperCase()}] ${alert.title}\n${alert.body}`;

    if (alert.level === 'critical') this.logger.error(line);
    else if (alert.level === 'warning') this.logger.warn(line);
    else this.logger.log(line);

    if (webhookUrl) {
      try {
        const payload = webhookUrl.includes('qyapi.weixin.qq.com')
          ? buildWecomPayload(alert)
          : {
              level: alert.level,
              title: alert.title,
              body: alert.body,
              context: alert.context,
              timestamp: new Date().toISOString(),
            };
        const res = await fetch(webhookUrl, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
          signal: AbortSignal.timeout(5_000),
        });
        // 企微即使格式错也回 HTTP 200,错误在 body.errcode — 必须看 body
        const text = await res.text();
        if (!res.ok || /"errcode":\s*[1-9]/.test(text)) {
          this.logger.error(`Alert webhook rejected: HTTP ${res.status} ${text.slice(0, 160)}`);
        }
      } catch (err) {
        this.logger.error(
          `Failed to deliver alert webhook: ${err instanceof Error ? err.message : String(err)}`,
        );
      }
    }
  }
}

/// 企微群机器人 payload(markdown)。颜色:企微只支持 info绿/comment灰/warning橙 → 级别用 emoji 区分。
/// 内容上限 4096 字节 → body 截断;context 逐行附在引用块里。
function buildWecomPayload(alert: Alert): Record<string, unknown> {
  const icon = alert.level === 'critical' ? '🔴' : alert.level === 'warning' ? '🟡' : '🟢';
  const color = alert.level === 'info' ? 'info' : 'warning';
  const ctxLines = alert.context
    ? Object.entries(alert.context)
        .map(([k, v]) => `> ${k}: ${typeof v === 'string' ? v : JSON.stringify(v)}`)
        .join('\n')
    : '';
  const body = alert.body.length > 1500 ? `${alert.body.slice(0, 1500)}…` : alert.body;
  const content = [
    `${icon} **<font color="${color}">[PAC ${alert.level.toUpperCase()}] ${alert.title}</font>**`,
    body,
    ctxLines,
    `> time: ${new Date().toISOString()}`,
  ]
    .filter(Boolean)
    .join('\n');
  return { msgtype: 'markdown', markdown: { content } };
}
