import { prisma } from "@/lib/prisma";
import {
  ConversionTier,
  DEFAULT_COUNTED_TIERS,
  getDefaultTier,
  humanizeType,
} from "./tiers";
import { canonicalConversionType } from "@/lib/conversion-taxonomy";

export interface EffectiveConfig {
  conversionType: string;
  tier: ConversionTier | "unknown";
  isCounted: boolean;
  displayLabel: string;
  isCustom: boolean;
}

const CACHE_TTL = 60_000;
type CacheEntry = { data: Record<string, EffectiveConfig>; ts: number };
const configCache = new Map<string, CacheEntry>();

function buildEffective(
  conversionType: string,
  override: { isCounted: boolean; tierOverride: string | null; displayLabel: string | null } | null,
): EffectiveConfig {
  const tier = (override?.tierOverride as ConversionTier | null) ?? getDefaultTier(conversionType);
  const isCounted = override != null
    ? override.isCounted
    : DEFAULT_COUNTED_TIERS.includes(tier as ConversionTier);
  return {
    conversionType,
    tier,
    isCounted,
    displayLabel: override?.displayLabel ?? humanizeType(conversionType),
    isCustom: override != null,
  };
}

export async function getEffectiveConversionConfig(
  brandId: string,
  conversionType: string,
): Promise<EffectiveConfig> {
  const row = await (prisma as any).brandConversionConfig.findUnique({
    where: { brandId_conversionType: { brandId, conversionType } },
    select: { isCounted: true, tierOverride: true, displayLabel: true },
  }).catch(() => null);
  return buildEffective(conversionType, row);
}

export async function getAllEffectiveConfigs(brandId: string): Promise<Record<string, EffectiveConfig>> {
  const cached = configCache.get(brandId);
  if (cached && Date.now() - cached.ts < CACHE_TTL) return cached.data;

  const rows = await (prisma as any).brandConversionConfig.findMany({
    where: { brandId },
    select: { conversionType: true, isCounted: true, tierOverride: true, displayLabel: true },
  }).catch(() => []) as Array<{
    conversionType: string;
    isCounted: boolean;
    tierOverride: string | null;
    displayLabel: string | null;
  }>;

  const overrideMap = new Map(rows.map((r) => [canonicalConversionType(r.conversionType) ?? r.conversionType, r]));

  // Keys are canonical types (e.g. "phone_call"). Callers look up by
  // raw event type; getConfigForType canonicalizes the lookup key so
  // overrides stored as "click_to_call" match raw events of "phone_call".
  const result: Record<string, EffectiveConfig> = {};
  for (const [type, override] of overrideMap) {
    result[type] = buildEffective(type, override);
  }

  const entry: CacheEntry = { data: result, ts: Date.now() };
  configCache.set(brandId, entry);
  return result;
}

export function getConfigForType(
  configs: Record<string, EffectiveConfig>,
  conversionType: string,
): EffectiveConfig {
  const key = canonicalConversionType(conversionType) ?? conversionType;
  return configs[key] ?? buildEffective(conversionType, null);
}

export function invalidateConfigCache(brandId: string): void {
  configCache.delete(brandId);
}
