import { eq, and, sql } from 'drizzle-orm';
import { db } from '@/db';
import { promptUrlCache } from '@banatie/database';
import type { PromptUrlCacheEntry, NewPromptUrlCacheEntry } from '@/types/models';
import { computeSHA256 } from '@/utils/helpers';

export class PromptCacheService {
  /**
   * Compute SHA-256 hash of prompt for cache lookup
   */
  computePromptHash(prompt: string): string {
    return computeSHA256(prompt);
  }

  /**
   * Check if prompt exists in cache for a project
   */
  async getCachedEntry(
    promptHash: string,
    projectId: string
  ): Promise<PromptUrlCacheEntry | null> {
    const entry = await db.query.promptUrlCache.findFirst({
      where: and(
        eq(promptUrlCache.promptHash, promptHash),
        eq(promptUrlCache.projectId, projectId)
      ),
    });

    return entry || null;
  }

  /**
   * Create a new cache entry
   */
  async createCacheEntry(data: NewPromptUrlCacheEntry): Promise<PromptUrlCacheEntry> {
    const [entry] = await db.insert(promptUrlCache).values(data).returning();
    if (!entry) {
      throw new Error('Failed to create cache entry');
    }
    return entry;
  }

  /**
   * Update hit count and last hit time for a cache entry
   */
  async recordCacheHit(id: string): Promise<void> {
    await db
      .update(promptUrlCache)
      .set({
        hitCount: sql`${promptUrlCache.hitCount} + 1`,
        lastHitAt: new Date(),
      })
      .where(eq(promptUrlCache.id, id));
  }

  /**
   * Get cache statistics for a project
   */
  async getCacheStats(projectId: string): Promise<{
    totalEntries: number;
    totalHits: number;
    avgHitCount: number;
  }> {
    const entries = await db.query.promptUrlCache.findMany({
      where: eq(promptUrlCache.projectId, projectId),
    });

    const totalEntries = entries.length;
    const totalHits = entries.reduce((sum, entry) => sum + entry.hitCount, 0);
    const avgHitCount = totalEntries > 0 ? totalHits / totalEntries : 0;

    return {
      totalEntries,
      totalHits,
      avgHitCount,
    };
  }

  /**
   * Clear old cache entries (can be called periodically)
   */
  async clearOldEntries(daysOld: number): Promise<number> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - daysOld);

    const result = await db
      .delete(promptUrlCache)
      .where(
        and(
          eq(promptUrlCache.hitCount, 0),
          // Only delete entries with 0 hits that are old
        )
      )
      .returning();

    return result.length;
  }
}
