using System.Net.Http.Json; using System.Text; using System.Text.Json; using TaxBaik.Application.Services; namespace TaxBaik.Web.Services; public class TelegramInquiryNotificationService : IInquiryNotificationService { private readonly IHttpClientFactory _httpClientFactory; private readonly IConfiguration _configuration; private readonly ILogger _logger; private readonly string _baseUrl; public TelegramInquiryNotificationService(IHttpClientFactory httpClientFactory, IConfiguration configuration, ILogger logger) { _httpClientFactory = httpClientFactory; _configuration = configuration; _logger = logger; _baseUrl = (_configuration["App:PublicBaseUrl"] ?? "http://178.104.200.7/taxbaik").TrimEnd('/'); } public async Task NotifyCreatedAsync(int inquiryId, string name, string phone, string serviceType, string message, string? ipAddress, DateTime createdAtUtc, CancellationToken ct = default) { var botToken = _configuration["Telegram:BotToken"]; var chatId = _configuration["Telegram:ChatId"]; if (string.IsNullOrWhiteSpace(botToken) || string.IsNullOrWhiteSpace(chatId)) { _logger.LogWarning("텔레그램 새 문의 알림 설정이 누락되었습니다. Telegram:BotToken 또는 Telegram:ChatId를 확인하세요."); return; } var adminLink = $"{_baseUrl}/admin/inquiries"; var summary = message.Length > 180 ? message[..180] + "..." : message; var createdAtKst = createdAtUtc.AddHours(9); var text = new StringBuilder() .AppendLine("🆕 새 문의가 접수되었습니다.") .AppendLine() .AppendLine($"문의 번호: #{inquiryId}") .AppendLine($"제목: {serviceType}") .AppendLine($"이름: {name}") .AppendLine($"연락처: {phone}") .AppendLine($"접수 시각: {createdAtKst:yyyy-MM-dd HH:mm:ss} KST") .AppendLine($"IP: {(string.IsNullOrWhiteSpace(ipAddress) ? "-" : ipAddress)}") .AppendLine() .AppendLine("내용 요약:") .AppendLine(summary) .AppendLine() .AppendLine($"답변 목록 링크: {adminLink}") .ToString(); var client = _httpClientFactory.CreateClient(); var url = $"https://api.telegram.org/bot{botToken}/sendMessage"; var payload = new { chat_id = chatId, text, disable_web_page_preview = false }; try { var response = await client.PostAsJsonAsync(url, payload, ct); var responseBody = await response.Content.ReadAsStringAsync(ct); if (!response.IsSuccessStatusCode) { _logger.LogWarning("텔레그램 알림 전송 실패: {StatusCode} {ResponseBody}", response.StatusCode, Truncate(responseBody)); } else { _logger.LogInformation("텔레그램 새 문의 알림 전송 성공: #{InquiryId}, message_id={MessageId}", inquiryId, TryGetMessageId(responseBody)); } } catch (Exception ex) { _logger.LogWarning(ex, "텔레그램 알림 전송 중 오류 발생"); } } public async Task NotifyStatusChangedAsync(int inquiryId, string name, string phone, string serviceType, string previousStatus, string newStatus, string? changedBy = null, CancellationToken ct = default) { var botToken = _configuration["Telegram:BotToken"]; var chatId = _configuration["Telegram:ChatId"]; if (string.IsNullOrWhiteSpace(botToken) || string.IsNullOrWhiteSpace(chatId)) { _logger.LogWarning("텔레그램 상태 변경 알림 설정이 누락되었습니다. Telegram:BotToken 또는 Telegram:ChatId를 확인하세요."); return; } var adminLink = $"{_baseUrl}/admin/inquiries"; var text = new StringBuilder() .AppendLine("✏️ 문의 상태가 변경되었습니다.") .AppendLine() .AppendLine($"문의 번호: #{inquiryId}") .AppendLine($"제목: {serviceType}") .AppendLine($"이름: {name}") .AppendLine($"연락처: {phone}") .AppendLine($"상태: {FormatStatus(previousStatus)} -> {FormatStatus(newStatus)}") .AppendLine($"변경자: {(string.IsNullOrWhiteSpace(changedBy) ? "-" : changedBy)}") .AppendLine() .AppendLine($"답변 목록 링크: {adminLink}") .ToString(); var client = _httpClientFactory.CreateClient(); var url = $"https://api.telegram.org/bot{botToken}/sendMessage"; var payload = new { chat_id = chatId, text, disable_web_page_preview = false }; try { var response = await client.PostAsJsonAsync(url, payload, ct); var responseBody = await response.Content.ReadAsStringAsync(ct); if (!response.IsSuccessStatusCode) { _logger.LogWarning("텔레그램 상태 변경 알림 실패: {StatusCode} {ResponseBody}", response.StatusCode, Truncate(responseBody)); } else { _logger.LogInformation("텔레그램 상태 변경 알림 전송 성공: #{InquiryId}, message_id={MessageId}", inquiryId, TryGetMessageId(responseBody)); } } catch (Exception ex) { _logger.LogWarning(ex, "텔레그램 상태 변경 알림 중 오류 발생"); } } private static string FormatStatus(string status) => status switch { "new" => "신규", "contacted" => "연락함", "completed" => "완료", _ => status }; private static string TryGetMessageId(string responseBody) { try { using var document = JsonDocument.Parse(responseBody); if (document.RootElement.TryGetProperty("result", out var result) && result.TryGetProperty("message_id", out var messageId)) { return messageId.ToString(); } } catch (JsonException) { return "unknown"; } return "unknown"; } private static string Truncate(string value) => value.Length <= 500 ? value : value[..500] + "..."; }