import { db } from '../config/database.js';
import { auditLogs } from '../db/schema.js';
import { logger } from '../utils/logger.js';

/**
 * Zaloguje audit event
 */
export const logAuditEvent = async ({
  userId = null,
  action,
  resource,
  resourceId = null,
  oldValue = null,
  newValue = null,
  ipAddress = null,
  userAgent = null,
  success = true,
  errorMessage = null,
}) => {
  try {
    await db.insert(auditLogs).values({
      userId,
      action,
      resource,
      resourceId,
      oldValue: oldValue ? JSON.stringify(oldValue) : null,
      newValue: newValue ? JSON.stringify(newValue) : null,
      ipAddress,
      userAgent,
      success,
      errorMessage,
    });

    logger.audit(
      `${action} on ${resource}${resourceId ? ` (${resourceId})` : ''} ${success ? 'SUCCESS' : 'FAILED'}${userId ? ` by user ${userId}` : ''}`
    );
  } catch (error) {
    logger.error('Nepodarilo sa zaznamenať audit event', error);
  }
};

/**
 * Pomocné funkcie pre špecifické audit eventy
 */

export const logLoginAttempt = async (username, success, ipAddress, userAgent, errorMessage = null) => {
  await logAuditEvent({
    action: 'login_attempt',
    resource: 'user',
    resourceId: username,
    ipAddress,
    userAgent,
    success,
    errorMessage,
  });
};

export const logPasswordChange = async (userId, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'password_change',
    resource: 'user',
    resourceId: userId,
    ipAddress,
    userAgent,
    success: true,
  });
};

export const logEmailLink = async (userId, email, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'email_linked',
    resource: 'user',
    resourceId: userId,
    newValue: { email },
    ipAddress,
    userAgent,
    success: true,
  });
};

export const logRoleChange = async (adminId, userId, oldRole, newRole, ipAddress, userAgent) => {
  await logAuditEvent({
    userId: adminId,
    action: 'role_change',
    resource: 'user',
    resourceId: userId,
    oldValue: { role: oldRole },
    newValue: { role: newRole },
    ipAddress,
    userAgent,
    success: true,
  });
};

export const logUserCreation = async (adminId, newUserId, username, role, ipAddress, userAgent) => {
  await logAuditEvent({
    userId: adminId,
    action: 'user_created',
    resource: 'user',
    resourceId: newUserId,
    newValue: { username, role },
    ipAddress,
    userAgent,
    success: true,
  });
};

// Projects
export const logProjectCreated = async (userId, projectId, projectName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'project_created',
    resource: 'project',
    resourceId: projectId,
    newValue: { name: projectName },
    ipAddress,
    userAgent,
  });
};

export const logProjectDeleted = async (userId, projectId, projectName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'project_deleted',
    resource: 'project',
    resourceId: projectId,
    oldValue: { name: projectName },
    ipAddress,
    userAgent,
  });
};

// Todos
export const logTodoCreated = async (userId, todoId, todoTitle, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'todo_created',
    resource: 'todo',
    resourceId: todoId,
    newValue: { title: todoTitle },
    ipAddress,
    userAgent,
  });
};

export const logTodoCompleted = async (userId, todoId, todoTitle, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'todo_completed',
    resource: 'todo',
    resourceId: todoId,
    newValue: { title: todoTitle },
    ipAddress,
    userAgent,
  });
};

export const logTodoDeleted = async (userId, todoId, todoTitle, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'todo_deleted',
    resource: 'todo',
    resourceId: todoId,
    oldValue: { title: todoTitle },
    ipAddress,
    userAgent,
  });
};

// Time Tracking
export const logTimerStarted = async (userId, entryId, projectName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'timer_started',
    resource: 'time_entry',
    resourceId: entryId,
    newValue: { project: projectName },
    ipAddress,
    userAgent,
  });
};

export const logTimerStopped = async (userId, entryId, projectName, duration, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'timer_stopped',
    resource: 'time_entry',
    resourceId: entryId,
    newValue: { project: projectName, duration },
    ipAddress,
    userAgent,
  });
};

export const logTimerPaused = async (userId, entryId, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'timer_paused',
    resource: 'time_entry',
    resourceId: entryId,
    ipAddress,
    userAgent,
  });
};

export const logTimerResumed = async (userId, entryId, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'timer_resumed',
    resource: 'time_entry',
    resourceId: entryId,
    ipAddress,
    userAgent,
  });
};

// Companies
export const logCompanyCreated = async (userId, companyId, companyName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_created',
    resource: 'company',
    resourceId: companyId,
    newValue: { name: companyName },
    ipAddress,
    userAgent,
  });
};

export const logCompanyDeleted = async (userId, companyId, companyName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_deleted',
    resource: 'company',
    resourceId: companyId,
    oldValue: { name: companyName },
    ipAddress,
    userAgent,
  });
};

// Auth
export const logLogin = async (userId, username, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'login',
    resource: 'auth',
    resourceId: userId,
    newValue: { username },
    ipAddress,
    userAgent,
  });
};

export const logLogout = async (userId, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'logout',
    resource: 'auth',
    resourceId: userId,
    ipAddress,
    userAgent,
  });
};

// User deletion
export const logUserDeleted = async (adminId, deletedUserId, username, ipAddress, userAgent) => {
  await logAuditEvent({
    userId: adminId,
    action: 'user_deleted',
    resource: 'user',
    resourceId: deletedUserId,
    oldValue: { username },
    ipAddress,
    userAgent,
  });
};

// Contacts
export const logContactLinkedToCompany = async (userId, contactId, companyId, companyName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'contact_linked_to_company',
    resource: 'contact',
    resourceId: contactId,
    newValue: { companyId, companyName },
    ipAddress,
    userAgent,
  });
};

export const logCompanyCreatedFromContact = async (userId, contactId, companyId, companyName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_created_from_contact',
    resource: 'contact',
    resourceId: contactId,
    newValue: { companyId, companyName },
    ipAddress,
    userAgent,
  });
};

// Notes
export const logNoteCreated = async (userId, noteId, noteContent, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'note_created',
    resource: 'note',
    resourceId: noteId,
    newValue: { content: noteContent?.substring(0, 100) },
    ipAddress,
    userAgent,
  });
};

export const logNoteUpdated = async (userId, noteId, oldContent, newContent, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'note_updated',
    resource: 'note',
    resourceId: noteId,
    oldValue: { content: oldContent?.substring(0, 100) },
    newValue: { content: newContent?.substring(0, 100) },
    ipAddress,
    userAgent,
  });
};

export const logNoteDeleted = async (userId, noteId, noteContent, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'note_deleted',
    resource: 'note',
    resourceId: noteId,
    oldValue: { content: noteContent?.substring(0, 100) },
    ipAddress,
    userAgent,
  });
};

// Company - updates and user management
export const logCompanyUpdated = async (userId, companyId, oldValues, newValues, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_updated',
    resource: 'company',
    resourceId: companyId,
    oldValue: oldValues,
    newValue: newValues,
    ipAddress,
    userAgent,
  });
};

export const logCompanyUserAssigned = async (userId, companyId, assignedUserId, companyName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_user_assigned',
    resource: 'company',
    resourceId: companyId,
    newValue: { assignedUserId, companyName },
    ipAddress,
    userAgent,
  });
};

export const logCompanyUserRemoved = async (userId, companyId, removedUserId, companyName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_user_removed',
    resource: 'company',
    resourceId: companyId,
    oldValue: { removedUserId, companyName },
    ipAddress,
    userAgent,
  });
};

// Company reminders
export const logCompanyReminderCreated = async (userId, reminderId, companyId, reminderDate, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_reminder_created',
    resource: 'company_reminder',
    resourceId: reminderId,
    newValue: { companyId, reminderDate },
    ipAddress,
    userAgent,
  });
};

export const logCompanyReminderUpdated = async (userId, reminderId, companyId, oldDate, newDate, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_reminder_updated',
    resource: 'company_reminder',
    resourceId: reminderId,
    oldValue: { companyId, reminderDate: oldDate },
    newValue: { companyId, reminderDate: newDate },
    ipAddress,
    userAgent,
  });
};

export const logCompanyReminderDeleted = async (userId, reminderId, companyId, reminderDate, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'company_reminder_deleted',
    resource: 'company_reminder',
    resourceId: reminderId,
    oldValue: { companyId, reminderDate },
    ipAddress,
    userAgent,
  });
};

// Project - updates and user management
export const logProjectUpdated = async (userId, projectId, oldValues, newValues, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'project_updated',
    resource: 'project',
    resourceId: projectId,
    oldValue: oldValues,
    newValue: newValues,
    ipAddress,
    userAgent,
  });
};

export const logProjectUserAssigned = async (userId, projectId, assignedUserId, projectName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'project_user_assigned',
    resource: 'project',
    resourceId: projectId,
    newValue: { assignedUserId, projectName },
    ipAddress,
    userAgent,
  });
};

export const logProjectUserRemoved = async (userId, projectId, removedUserId, projectName, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'project_user_removed',
    resource: 'project',
    resourceId: projectId,
    oldValue: { removedUserId, projectName },
    ipAddress,
    userAgent,
  });
};

// Todos - update and uncomplete
export const logTodoUpdated = async (userId, todoId, oldValues, newValues, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'todo_updated',
    resource: 'todo',
    resourceId: todoId,
    oldValue: oldValues,
    newValue: newValues,
    ipAddress,
    userAgent,
  });
};

export const logTodoUncompleted = async (userId, todoId, todoTitle, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'todo_uncompleted',
    resource: 'todo',
    resourceId: todoId,
    newValue: { title: todoTitle },
    ipAddress,
    userAgent,
  });
};

// Time Entry - update and delete
export const logTimeEntryUpdated = async (userId, entryId, oldValues, newValues, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'time_entry_updated',
    resource: 'time_entry',
    resourceId: entryId,
    oldValue: oldValues,
    newValue: newValues,
    ipAddress,
    userAgent,
  });
};

export const logTimeEntryDeleted = async (userId, entryId, projectName, duration, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'time_entry_deleted',
    resource: 'time_entry',
    resourceId: entryId,
    oldValue: { project: projectName, duration },
    ipAddress,
    userAgent,
  });
};

// Timesheets
export const logTimesheetUploaded = async (userId, timesheetId, year, month, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'timesheet_uploaded',
    resource: 'timesheet',
    resourceId: timesheetId,
    newValue: { year, month },
    ipAddress,
    userAgent,
  });
};

export const logTimesheetDeleted = async (userId, timesheetId, year, month, ipAddress, userAgent) => {
  await logAuditEvent({
    userId,
    action: 'timesheet_deleted',
    resource: 'timesheet',
    resourceId: timesheetId,
    oldValue: { year, month },
    ipAddress,
    userAgent,
  });
};
