import { AppSetting } from "@/db/models";
import { isSettingsMysql } from "@/db/activeDatabase";
import {
  getCommerceSettingsMysql,
  setCommerceSettingsMysql,
} from "@/db/mysql/settings";

export type RefundTier = Array<{ hoursBeforeCheckIn: number; refundPercent: number }>;

export type CommerceSettings = {
  walletEnabled: boolean;
  loyaltyEnabled: boolean;
  couponsEnabled: boolean;
  /** Points earned per 1 LYD paid */
  pointsPerLyd: number;
  /** LYD value of 1 redeemed point (as TND discount uses exchange at quote time via points→TND) */
  tndPerPoint: number;
  minRedeemPoints: number;
  maxRedeemPercentOfSubtotal: number;
  ownerRejectRefundPercent: number;
  refundTiers: RefundTier;
};

export const DEFAULT_COMMERCE: CommerceSettings = {
  walletEnabled: true,
  loyaltyEnabled: true,
  couponsEnabled: true,
  pointsPerLyd: 1,
  tndPerPoint: 0.01,
  minRedeemPoints: 100,
  maxRedeemPercentOfSubtotal: 20,
  ownerRejectRefundPercent: 100,
  refundTiers: [
    { hoursBeforeCheckIn: 48, refundPercent: 100 },
    { hoursBeforeCheckIn: 24, refundPercent: 50 },
    { hoursBeforeCheckIn: 0, refundPercent: 0 },
  ],
};

export async function getCommerceSettings(): Promise<CommerceSettings> {
  if (isSettingsMysql()) {
    return getCommerceSettingsMysql();
  }
  const doc = await AppSetting.findOne({ key: "commerce" }).lean();
  if (!doc?.value || typeof doc.value !== "object") {
    await AppSetting.findOneAndUpdate(
      { key: "commerce" },
      { $set: { value: { ...DEFAULT_COMMERCE } } },
      { upsert: true },
    );
    return { ...DEFAULT_COMMERCE };
  }
  return { ...DEFAULT_COMMERCE, ...(doc.value as Partial<CommerceSettings>) };
}

export async function setCommerceSettings(
  patch: Partial<CommerceSettings>,
): Promise<CommerceSettings> {
  const current = await getCommerceSettings();
  const next = { ...current, ...patch };
  if (patch.refundTiers) {
    next.refundTiers = [...patch.refundTiers].sort(
      (a, b) => b.hoursBeforeCheckIn - a.hoursBeforeCheckIn,
    );
  }
  if (isSettingsMysql()) {
    return setCommerceSettingsMysql(next);
  }
  await AppSetting.findOneAndUpdate(
    { key: "commerce" },
    { $set: { value: next } },
    { upsert: true, new: true },
  );
  return next;
}

export function refundPercentForHours(tiers: RefundTier, hoursUntilCheckIn: number): number {
  const sorted = [...tiers].sort((a, b) => b.hoursBeforeCheckIn - a.hoursBeforeCheckIn);
  for (const tier of sorted) {
    if (hoursUntilCheckIn >= tier.hoursBeforeCheckIn) return tier.refundPercent;
  }
  return 0;
}
