import { Injectable } from '@nestjs/common';
import { Prisma, SyncItemStatus } from '@prisma/client';
import { resolveEstateScope } from '../common/estate-scope';
import { RequestUser } from '../common/request-user';
import { PrismaService } from '../database/prisma.service';
import { OfflineSyncDto } from './dto/offline.dto';

@Injectable()
export class OfflineService {
  constructor(private readonly prisma: PrismaService) {}

  async bootstrap(user: RequestUser, estateId: string) {
    const scopedEstateId = resolveEstateScope(user, estateId);
    const now = new Date();
    const endOfToday = new Date(now);
    endOfToday.setHours(23, 59, 59, 999);

    const [activePasses, residents, recentLogs] = await Promise.all([
      this.prisma.visitorPass.findMany({
        where: {
          estateId: scopedEstateId,
          status: 'ACTIVE',
          validFrom: { lte: endOfToday },
          validUntil: { gte: now }
        },
        include: { visitor: true, hostResident: true },
        take: 500
      }),
      this.prisma.resident.findMany({
        where: { estateId: scopedEstateId, status: 'ACTIVE' },
        select: { id: true, name: true, unit: true, phone: true },
        take: 1000
      }),
      this.prisma.auditLog.findMany({
        where: { estateId: scopedEstateId },
        orderBy: { timestamp: 'desc' },
        take: 100
      })
    ]);

    return {
      serverTime: now,
      activePasses,
      residents,
      recentLogs
    };
  }

  async sync(dto: OfflineSyncDto, user: RequestUser) {
    const estateId = resolveEstateScope(user, dto.estateId);
    const results = [];

    for (const item of dto.items) {
      const record = await this.prisma.offlineSyncItem.upsert({
        where: {
          deviceId_clientEventId: {
            deviceId: dto.deviceId,
            clientEventId: item.clientEventId
          }
        },
        create: {
          estateId,
          deviceId: dto.deviceId,
          clientEventId: item.clientEventId,
          eventType: item.eventType,
          payload: item.payload as Prisma.InputJsonValue,
          status: SyncItemStatus.APPLIED,
          appliedAt: new Date()
        },
        update: {}
      });
      results.push(record);
    }

    return {
      accepted: results.length,
      items: results
    };
  }
}
