import { Component, inject, signal, OnInit, computed, effect } from '@angular/core'; import { CommonModule, DatePipe } from '@angular/common'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { NzCardModule } from 'ng-zorro-antd/card'; import { NzButtonModule } from 'ng-zorro-antd/button'; import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzTagModule } from 'ng-zorro-antd/tag'; import { NzSpinModule } from 'ng-zorro-antd/spin'; import { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm'; import { NzTableModule } from 'ng-zorro-antd/table'; import { ApiService } from '../../../core/services/api.service'; import { AuthService } from '../../../core/services/auth.service'; import { NotificationService } from '../../../core/services/notification.service'; import { SettingsService } from '../../../core/services/settings.service'; import { KeyCacheService, ResolvedKey } from '../../../core/services/key-cache.service'; import { UserCacheService, ResolvedUser } from '../../../core/services/user-cache.service'; import { Message, Delivery } from '../../../core/models'; import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe'; import { MetadataGridComponent, MetadataValueComponent } from '../../../shared/components/metadata-grid'; @Component({ selector: 'app-message-detail', standalone: true, imports: [ CommonModule, DatePipe, NzCardModule, NzButtonModule, NzIconModule, NzTagModule, NzSpinModule, NzPopconfirmModule, NzTableModule, RouterLink, RelativeTimePipe, MetadataGridComponent, MetadataValueComponent, ], templateUrl: './message-detail.component.html', styleUrl: './message-detail.component.scss' }) export class MessageDetailComponent implements OnInit { private route = inject(ActivatedRoute); private router = inject(Router); private apiService = inject(ApiService); private authService = inject(AuthService); private notification = inject(NotificationService); private settingsService = inject(SettingsService); private keyCacheService = inject(KeyCacheService); private userCacheService = inject(UserCacheService); message = signal(null); resolvedKey = signal(null); resolvedChannelOwner = signal(null); deliveries = signal([]); loading = signal(true); deleting = signal(false); loadingDeliveries = signal(false); expertMode = this.settingsService.expertMode; isChannelOwner = computed(() => { const msg = this.message(); const userId = this.authService.getUserId(); return msg !== null && userId !== null && msg.channel_owner_user_id === userId; }); showDeliveries = computed(() => this.expertMode() && this.isChannelOwner()); constructor() { // Watch for expert mode changes and load deliveries when it becomes visible effect(() => { if (this.showDeliveries() && this.message() && this.deliveries().length === 0 && !this.loadingDeliveries()) { this.loadDeliveries(this.message()!.message_id); } }); } ngOnInit(): void { const messageId = this.route.snapshot.paramMap.get('id'); if (messageId) { this.loadMessage(messageId); } } loadMessage(messageId: string): void { this.loading.set(true); this.apiService.getMessage(messageId).subscribe({ next: (message) => { this.message.set(message); this.loading.set(false); this.resolveKey(message.used_key_id); this.resolveChannelOwner(message.channel_owner_user_id); this.loadDeliveries(messageId); }, error: () => { this.loading.set(false); } }); } private loadDeliveries(messageId: string): void { if (!this.showDeliveries()) { return; } this.loadingDeliveries.set(true); this.apiService.getDeliveries(messageId).subscribe({ next: (response) => { this.deliveries.set(response.deliveries); this.loadingDeliveries.set(false); }, error: () => { this.loadingDeliveries.set(false); } }); } private resolveKey(keyId: string): void { this.keyCacheService.resolveKey(keyId).subscribe({ next: (resolved) => this.resolvedKey.set(resolved) }); } private resolveChannelOwner(userId: string): void { this.userCacheService.resolveUser(userId).subscribe({ next: (resolved) => this.resolvedChannelOwner.set(resolved) }); } goBack(): void { this.router.navigate(['/messages']); } deleteMessage(): void { const message = this.message(); if (!message) return; this.deleting.set(true); this.apiService.deleteMessage(message.message_id).subscribe({ next: () => { this.notification.success('Message deleted'); this.router.navigate(['/messages']); }, error: () => { this.deleting.set(false); } }); } getPriorityLabel(priority: number): string { switch (priority) { case 0: return 'Low'; case 1: return 'Normal'; case 2: return 'High'; default: return 'Unknown'; } } getPriorityColor(priority: number): string { switch (priority) { case 0: return 'default'; case 1: return 'blue'; case 2: return 'red'; default: return 'default'; } } getStatusColor(status: string): string { switch (status) { case 'SUCCESS': return 'green'; case 'FAILED': return 'red'; case 'RETRY': return 'orange'; default: return 'default'; } } }