import { Injectable } from '@nestjs/common'
import { PrismaService } from '../prisma/prisma.service'
import { AppVersionMapper } from '../mappers/app-version.mapper'
import {
  AppVersion,
  AppVersionRepository,
  Platform,
  VersionCode,
} from '../../../domain/version-management'
import { Platform as PrismaPlatform } from '@prisma/client'

@Injectable()
export class AppVersionRepositoryImpl implements AppVersionRepository {
  constructor(
    private readonly prisma: PrismaService,
    private readonly mapper: AppVersionMapper,
  ) {}

  async save(appVersion: AppVersion): Promise<AppVersion> {
    const data = this.mapper.toPersistence(appVersion)
    const created = await this.prisma.appVersion.create({
      data: {
        ...data,
        createdAt: appVersion.createdAt,
        updatedAt: appVersion.updatedAt,
      },
    })
    return this.mapper.toDomain(created)
  }

  async findById(id: string): Promise<AppVersion | null> {
    const found = await this.prisma.appVersion.findUnique({ where: { id } })
    return found ? this.mapper.toDomain(found) : null
  }

  async findLatestByPlatform(platform: Platform): Promise<AppVersion | null> {
    const found = await this.prisma.appVersion.findFirst({
      where: { platform: platform as PrismaPlatform, isEnabled: true },
      orderBy: { versionCode: 'desc' },
    })
    return found ? this.mapper.toDomain(found) : null
  }

  async findAllByPlatform(
    platform: Platform,
    includeDisabled = false,
  ): Promise<AppVersion[]> {
    const results = await this.prisma.appVersion.findMany({
      where: includeDisabled
        ? { platform: platform as PrismaPlatform }
        : { platform: platform as PrismaPlatform, isEnabled: true },
      orderBy: { versionCode: 'desc' },
    })
    return results.map((r) => this.mapper.toDomain(r))
  }

  async findAll(includeDisabled = false): Promise<AppVersion[]> {
    const results = await this.prisma.appVersion.findMany({
      where: includeDisabled ? {} : { isEnabled: true },
      orderBy: { createdAt: 'desc' },
    })
    return results.map((r) => this.mapper.toDomain(r))
  }

  async findByPlatformAndVersionCode(
    platform: Platform,
    versionCode: VersionCode,
  ): Promise<AppVersion | null> {
    const found = await this.prisma.appVersion.findFirst({
      where: {
        platform: platform as PrismaPlatform,
        versionCode: versionCode.value,
      },
    })
    return found ? this.mapper.toDomain(found) : null
  }

  async update(appVersion: AppVersion): Promise<AppVersion> {
    const data = this.mapper.toPersistence(appVersion)
    const updated = await this.prisma.appVersion.update({
      where: { id: appVersion.id },
      data: {
        downloadUrl: data.downloadUrl,
        fileSize: data.fileSize,
        fileSha256: data.fileSha256,
        changelog: data.changelog,
        isForceUpdate: data.isForceUpdate,
        isEnabled: data.isEnabled,
        minOsVersion: data.minOsVersion,
        releaseDate: data.releaseDate,
        updatedBy: data.updatedBy,
        updatedAt: new Date(),
      },
    })
    return this.mapper.toDomain(updated)
  }

  async delete(id: string): Promise<void> {
    await this.prisma.appVersion.delete({ where: { id } })
  }
}
