import { createClient } from 'redis';

const redis = createClient({ url: process.env.REDIS_URL });
redis.connect().catch((err) => console.error('[audit-log] Redis connect error:', err));

export interface AuditEntry {
  customerId: string;
  tool: string;
  args: Record<string, unknown>;
  result: 'success' | 'error';
  errorMessage?: string;
  durationMs: number;
  timestamp: string;
}

// Retain 90 days of logs per customer. Key: logs:{customerId}:{ISO-date}:{seq}
export async function logToolCall(entry: AuditEntry): Promise<void> {
  const date = entry.timestamp.slice(0, 10); // YYYY-MM-DD
  const seqKey = `log_seq:${entry.customerId}:${date}`;
  const seq = await redis.incr(seqKey);
  // Expire the sequence key after 95 days so it cleans up
  if (seq === 1) await redis.expire(seqKey, 60 * 60 * 24 * 95);

  const logKey = `logs:${entry.customerId}:${date}:${String(seq).padStart(8, '0')}`;
  await redis.set(logKey, JSON.stringify(entry), { EX: 60 * 60 * 24 * 90 });
}

// Retrieve logs for one customer for a date range — customerId is REQUIRED
export async function getCustomerLogs(
  customerId: string,
  fromDate: string, // YYYY-MM-DD
  toDate: string    // YYYY-MM-DD
): Promise<AuditEntry[]> {
  const dates = getDatesInRange(fromDate, toDate);
  const entries: AuditEntry[] = [];

  for (const date of dates) {
    const pattern = `logs:${customerId}:${date}:*`;
    const keys = await redis.keys(pattern);
    for (const key of keys) {
      const raw = await redis.get(key);
      if (raw) entries.push(JSON.parse(raw) as AuditEntry);
    }
  }

  return entries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
}

function getDatesInRange(from: string, to: string): string[] {
  const dates: string[] = [];
  const current = new Date(from);
  const end = new Date(to);
  while (current <= end) {
    dates.push(current.toISOString().slice(0, 10));
    current.setDate(current.getDate() + 1);
  }
  return dates;
}

// Convenience wrapper for tool handlers — call before and after
export function createToolAudit(customerId: string, tool: string) {
  const start = Date.now();
  return {
    success: async (args: Record<string, unknown>) => {
      await logToolCall({
        customerId, tool, args,
        result: 'success',
        durationMs: Date.now() - start,
        timestamp: new Date().toISOString(),
      });
    },
    error: async (args: Record<string, unknown>, errorMessage: string) => {
      await logToolCall({
        customerId, tool, args,
        result: 'error', errorMessage,
        durationMs: Date.now() - start,
        timestamp: new Date().toISOString(),
      });
    },
  };
}
