import { Injectable } from "@nestjs/common"
import { CreateStripeSettingsDto } from "./dto/create-stripe-settings.dto"
import { StripeSettingsRepository } from "./repository/stripe-settings.repository"
import { SubscriptionPlanRepository } from "../subscription-plans/repository/subscription-plan.repository"
import { successResponse, failureResponse } from "src/common/response/response"
import { code } from "src/common/response/response.code"
import { successMessage, errorMessage } from "src/utils/helpers"
import { messageKey } from "src/constants/message-keys"
import { isEmpty } from "class-validator"
import { StripeSettings } from "./entities/stripe-settings.entity"

@Injectable()
export class StripeSettingsService {
  constructor(
    private readonly stripeSettingsRepository: StripeSettingsRepository,
    private readonly subscriptionPlanRepository: SubscriptionPlanRepository,
  ) {}

  async createOrUpdate(dto: CreateStripeSettingsDto) {
    try {
      const existing: any = await this.stripeSettingsRepository.getByParams({
        where: { is_active: 1 },
        findOne: true,
      })

      if (existing) {
        const keysChanged =
          existing.stripe_secret_key !== dto.stripe_secret_key ||
          existing.stripe_publishable_key !== dto.stripe_publishable_key

        existing.stripe_secret_key = dto.stripe_secret_key
        existing.stripe_publishable_key = dto.stripe_publishable_key
        await this.stripeSettingsRepository.save(existing, { id: existing.id })

        if (keysChanged) {
          await this.resetSubscriptionPlanStripeIds()
        }

        return successResponse(
          code.SUCCESS,
          successMessage(messageKey.data_update, {
            ":data": "Stripe settings",
          }),
        )
      }

      const settings = new StripeSettings()
      settings.stripe_secret_key = dto.stripe_secret_key
      settings.stripe_publishable_key = dto.stripe_publishable_key
      settings.is_active = 1

      await this.stripeSettingsRepository.save(settings)

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_add, { ":data": "Stripe settings" }),
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.exception, { ":data": "Stripe settings" }),
      )
    }
  }

  async findActive() {
    try {
      const settings: any = await this.stripeSettingsRepository.getByParams({
        where: { is_active: 1 },
        findOne: true,
      })

      if (isEmpty(settings)) {
        return failureResponse(
          code.SUCCESS,
          errorMessage(messageKey.data_not_found, {
            ":data": "Stripe settings",
          }),
        )
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.detail_found, { ":data": "Stripe settings" }),
        settings,
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.exception, { ":data": "Stripe settings" }),
      )
    }
  }

  async getActiveStripeKeys(): Promise<StripeSettings | null> {
    const settings: any = await this.stripeSettingsRepository.getByParams({
      where: { is_active: 1 },
      findOne: true,
    })
    return settings || null
  }

  private async resetSubscriptionPlanStripeIds() {
    const result: any = await this.subscriptionPlanRepository.getByParams({})
    if (isEmpty(result)) return

    const plans = result?.data ? result.data : result
    if (!Array.isArray(plans)) return

    for (const plan of plans) {
      if (plan.stripe_price_id || plan.stripe_product_id) {
        plan.stripe_price_id = null
        plan.stripe_product_id = null
        await this.subscriptionPlanRepository.save(plan, { id: plan.id })
      }
    }
  }
}
