import { Injectable } from "@nestjs/common"
import { AppVersion } from "../entities/app-version.entity"
import * as semver from "semver"
import { CreateAppVersionDto } from "../dto/create-app-version.dto"
import { UpdateAppVersionDto } from "../dto/update-app-version.dto"
import { AppVersionRepository } from "../repositories/app.version.repository"
import { successResponse, failureResponse } from "src/common/response/response"
import { messageKey } from "src/constants/message-keys"
import { code } from "src/common/response/response.code"
import { BASELINE_VERSIONS, normalizeVersion } from "src/utils/helpers"

@Injectable()
export class AppVersionService {
  constructor(private readonly appVersionRepository: AppVersionRepository) {}

  async checkUpdate(
    platform: "android" | "ios",
    currentVersion: string,
    userType: string,
  ) {
    const normalizedCurrentVersion = normalizeVersion(currentVersion)

    const config = (await this.appVersionRepository.getByParams({
      where: { platform: platform, type: userType },
      findOne: true,
    })) as AppVersion
    if (!config) {
      return failureResponse(code.DATA_NOT_FOUND, "Platform not configured")
    }

    const minimumSupportedVersion = normalizeVersion(
      config.minimum_supported_version,
    )

    const latestVersion = normalizeVersion(config.latest_version)

    const baselineVersion = BASELINE_VERSIONS?.[platform]?.[userType]

    const isBaselineVersion =
      baselineVersion &&
      semver.eq(normalizedCurrentVersion, normalizeVersion(baselineVersion))
    // Check for force update
    // const forceUpdate =
    //   config.force_update ||
    //   semver.lt(currentVersion, config.minimum_supported_version)

    const forceUpdate =
      config.force_update ||
      semver.lt(normalizedCurrentVersion, minimumSupportedVersion)

    const alert = isBaselineVersion ? false : config.alert

    if (semver.lt(normalizedCurrentVersion, latestVersion) || forceUpdate) {
      return successResponse(code.SUCCESS, messageKey.data_retrieve, {
        updateRequired: true,
        forceUpdate: forceUpdate,
        latestVersion: config.latest_version,
        storeUrl: config.store_url,
        releaseNotes: config.release_notes,
        maintenance: config.maintenance,
        minimum_supported_version: config.minimum_supported_version,
        currentVersion: normalizedCurrentVersion,
        alert: alert,
        alertMessage: config.alert ? config.alert_message : null,
        maintenanceMessage: config.maintenance
          ? config.maintenance_message
          : null,
        type: config?.type,
      })
    }

    return successResponse(code.SUCCESS, messageKey.data_retrieve, {
      updateRequired: false,
      forceUpdate: false,
      latestVersion: config.latest_version,
      maintenance: config.maintenance,
      minimum_supported_version: config.minimum_supported_version,
      currentVersion: normalizedCurrentVersion,
      alert: alert,
      alertMessage: config.alert ? config.alert_message : null,
      maintenanceMessage: config.maintenance
        ? config.maintenance_message
        : null,
      type: config?.type,
    })
  }

  async setVersion(dto: CreateAppVersionDto) {
    let version = (await this.appVersionRepository.getByParams({
      where: { platform: dto.platform, type: dto.type },
      findOne: true,
    })) as AppVersion
    if (version) {
      Object.assign(version, dto)
    } else {
      version = await this.appVersionRepository.save(dto)
    }
    const savedVersion = await this.appVersionRepository.save(version)
    return successResponse(code.CREATED, messageKey.data_add, savedVersion)
  }

  async updateVersion(id: number, dto: UpdateAppVersionDto) {
    await this.appVersionRepository.save(dto, { id })
    const updatedVersion = (await this.appVersionRepository.getByParams({
      where: { id },
      findOne: true,
    })) as AppVersion
    return successResponse(code.SUCCESS, messageKey.data_update, updatedVersion)
  }

  async getAllVersions() {
    const versions = (await this.appVersionRepository.getByParams({
      orderBy: { created_at: "DESC" },
    })) as AppVersion[]
    return successResponse(code.SUCCESS, messageKey.data_retrieve, versions)
  }

  async deleteVersion(id: number) {
    const config = (await this.appVersionRepository.getByParams({
      where: { id },
      findOne: true,
    })) as AppVersion
    if (!config) {
      return failureResponse(code.DATA_NOT_FOUND, messageKey.data_not_found)
    }
    await this.appVersionRepository.remove({ id })
    return successResponse(code.SUCCESS, messageKey.data_removed)
  }
}
