import { prisma } from '@/lib/prisma';
import { getClientIp } from '@/lib/rateLimit';
import { headers } from 'next/headers';

export type AuditAction = 'CREATE' | 'UPDATE' | 'DELETE';
export type EntityType = 'ORDER' | 'MANUAL_SALE' | 'PURCHASE' | 'EXPENSE';

interface AuditChangeSet {
  [field: string]: {
    old: any;
    new: any;
  };
}

/**
 * Log a financial transaction change to the audit trail
 * @param action CREATE, UPDATE, or DELETE
 * @param entityType Type of entity (ORDER, MANUAL_SALE, etc)
 * @param entityId ID of the entity
 * @param changes Object with {field: {old: X, new: Y}}
 * @param amount Optional amount in cents for quick filtering
 * @param reason Why was this changed
 */
export async function logFinancialChange(
  action: AuditAction,
  entityType: EntityType,
  entityId: string,
  changes: AuditChangeSet,
  amount?: number,
  reason?: string
) {
  try {
    const ip = getClientIp(headers());

    await prisma.financialAuditLog.create({
      data: {
        action,
        entityType,
        entityId,
        changes: JSON.stringify(changes),
        amount,
        changedBy: ip,
        reason,
      },
    });
  } catch (err) {
    console.error('Failed to log financial change:', err);
    // Don't throw - audit logging failure shouldn't break the main transaction
  }
}

/**
 * Get audit logs for a specific entity
 */
export async function getEntityAuditTrail(entityType: EntityType, entityId: string) {
  return prisma.financialAuditLog.findMany({
    where: { entityType, entityId },
    orderBy: { changedAt: 'desc' },
  });
}

/**
 * Get all audit logs with optional filtering
 */
export async function getAuditLogs(options: {
  entityType?: EntityType;
  action?: AuditAction;
  fromDate?: Date;
  toDate?: Date;
  minAmount?: number;
  limit?: number;
}) {
  return prisma.financialAuditLog.findMany({
    where: {
      ...(options.entityType && { entityType: options.entityType }),
      ...(options.action && { action: options.action }),
      ...(options.fromDate || options.toDate
        ? {
            changedAt: {
              ...(options.fromDate && { gte: options.fromDate }),
              ...(options.toDate && { lte: options.toDate }),
            },
          }
        : {}),
      ...(options.minAmount && { amount: { gte: options.minAmount } }),
    },
    orderBy: { changedAt: 'desc' },
    take: options.limit || 100,
  });
}

/**
 * Get summary of financial changes (useful for spotting issues)
 */
export async function getAuditSummary(days: number = 30) {
  const fromDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);

  const logs = await prisma.financialAuditLog.findMany({
    where: { changedAt: { gte: fromDate } },
  });

  const summary = {
    total: logs.length,
    byAction: {
      CREATE: logs.filter((l) => l.action === 'CREATE').length,
      UPDATE: logs.filter((l) => l.action === 'UPDATE').length,
      DELETE: logs.filter((l) => l.action === 'DELETE').length,
    },
    byEntity: {
      ORDER: logs.filter((l) => l.entityType === 'ORDER').length,
      MANUAL_SALE: logs.filter((l) => l.entityType === 'MANUAL_SALE').length,
      PURCHASE: logs.filter((l) => l.entityType === 'PURCHASE').length,
      EXPENSE: logs.filter((l) => l.entityType === 'EXPENSE').length,
    },
    deletions: logs.filter((l) => l.action === 'DELETE').map((l) => ({
      entity: l.entityType,
      id: l.entityId,
      at: l.changedAt,
      reason: l.reason,
    })),
  };

  return summary;
}
