import { Injectable } from '@nestjs/common';
import { NotificationChannel, NotificationStatus } from '@prisma/client';
import { AuditService } from '../audit/audit.service';
import { resolveEstateScope } from '../common/estate-scope';
import { RequestUser } from '../common/request-user';
import { PrismaService } from '../database/prisma.service';
import { SendNotificationDto } from './dto/send-notification.dto';

@Injectable()
export class NotificationsService {
  constructor(
    private readonly audit: AuditService,
    private readonly prisma: PrismaService
  ) {}

  async send(dto: SendNotificationDto, user: RequestUser) {
    const estateId = resolveEstateScope(user, dto.estateId);
    const notification = await this.prisma.appNotification.create({
      data: {
        estateId,
        channel: this.normalizeChannel(dto.channel),
        status: NotificationStatus.PENDING,
        title: String(dto.metadata?.title ?? 'GateWise notification'),
        body: dto.message,
        data: {
          recipient: dto.recipient,
          requestedBy: user.id,
          ...dto.metadata
        }
      }
    });

    await this.audit.record({
      estateId,
      actorType: 'SYSTEM',
      actorId: 'notification-service',
      action: 'NOTIFICATION_QUEUED',
      metadata: {
        channel: dto.channel,
        recipient: dto.recipient,
        message: dto.message,
        requestedBy: user.id,
        ...dto.metadata
      }
    });

    return {
      status: 'QUEUED',
      notificationId: notification.id,
      channel: dto.channel,
      criticalPath: false
    };
  }

  listMine(user: RequestUser, unreadOnly?: string) {
    return this.prisma.appNotification.findMany({
      where: {
        estateId: user.estateId ?? undefined,
        userId: user.id,
        readAt: unreadOnly === 'true' ? null : undefined
      },
      orderBy: { createdAt: 'desc' },
      take: 100
    });
  }

  async markRead(id: string, user: RequestUser) {
    const notification = await this.prisma.appNotification.updateMany({
      where: { id, userId: user.id, estateId: user.estateId ?? undefined },
      data: { status: NotificationStatus.READ, readAt: new Date() }
    });
    return { updated: notification.count };
  }

  private normalizeChannel(channel: SendNotificationDto['channel']) {
    if (channel === 'SMS') {
      return NotificationChannel.SMS;
    }
    if (channel === 'PUSH') {
      return NotificationChannel.PUSH;
    }
    return NotificationChannel.IN_APP;
  }
}
