import { IService } from '../../../../core/interfaces/IService';
import {
  PayrollBatch,
  PayrollEntry,
  PayrollCalculationInput,
  PayrollCalculationResult,
  PayrollSummary,
  PayrollFilter,
  PayrollConfig,
  PayrollStatus,
  PayrollPeriod
} from '../../types/payroll.types';

/**
 * Payroll calculator service interface
 */
export interface IPayrollCalculator extends IService {
  /**
   * Calculate payroll for a period
   */
  calculatePayroll(input: PayrollCalculationInput): Promise<PayrollCalculationResult>;

  /**
   * Create payroll batch
   */
  createPayrollBatch(batch: Omit<PayrollBatch, 'id' | 'createdAt' | 'updatedAt'>): Promise<PayrollBatch>;

  /**
   * Get payroll batch by ID
   */
  getPayrollBatchById(batchId: string): Promise<PayrollBatch | null>;

  /**
   * Get payroll batches with filters
   */
  getPayrollBatches(filter?: PayrollFilter): Promise<PayrollBatch[]>;

  /**
   * Get payroll entry by ID
   */
  getPayrollEntryById(entryId: string): Promise<PayrollEntry | null>;

  /**
   * Get payroll entries by user ID
   */
  getPayrollEntriesByUserId(userId: string, filter?: PayrollFilter): Promise<PayrollEntry[]>;

  /**
   * Update payroll batch status
   */
  updatePayrollBatchStatus(batchId: string, status: PayrollStatus, updatedBy: string): Promise<PayrollBatch>;

  /**
   * Approve payroll batch
   */
  approvePayrollBatch(batchId: string, approvedBy: string): Promise<PayrollBatch>;

  /**
   * Process payroll batch (mark as completed)
   */
  processPayrollBatch(batchId: string): Promise<PayrollBatch>;

  /**
   * Cancel payroll batch
   */
  cancelPayrollBatch(batchId: string, reason: string, cancelledBy: string): Promise<PayrollBatch>;

  /**
   * Get payroll summary for period
   */
  getPayrollSummary(startDate: Date, endDate: Date): Promise<PayrollSummary>;

  /**
   * Get user payroll history
   */
  getUserPayrollHistory(userId: string, limit?: number, offset?: number): Promise<{
    entries: PayrollEntry[];
    total: number;
    totalEarned: number;
  }>;

  /**
   * Recalculate payroll batch
   */
  recalculatePayrollBatch(batchId: string): Promise<PayrollBatch>;

  /**
   * Get payroll configuration
   */
  getPayrollConfig(): Promise<PayrollConfig>;

  /**
   * Update payroll configuration
   */
  updatePayrollConfig(config: Partial<PayrollConfig>): Promise<PayrollConfig>;

  /**
   * Generate payroll report
   */
  generatePayrollReport(batchId: string): Promise<{
    batchInfo: PayrollBatch;
    summary: PayrollSummary;
    entries: PayrollEntry[];
    exportUrl?: string;
  }>;

  /**
   * Validate payroll calculation
   */
  validatePayrollCalculation(input: PayrollCalculationInput): Promise<{
    valid: boolean;
    errors: string[];
    warnings: string[];
  }>;

  /**
   * Get pending payroll batches
   */
  getPendingPayrollBatches(): Promise<PayrollBatch[]>;

  /**
   * Auto-calculate scheduled payrolls
   */
  autoCalculateScheduledPayrolls(): Promise<PayrollBatch[]>;

  /**
   * Get payroll statistics
   */
  getPayrollStatistics(period: PayrollPeriod, count: number): Promise<{
    totalBatches: number;
    totalAmount: number;
    totalParticipants: number;
    averageAmount: number;
    periodBreakdown: Array<{
      period: string;
      amount: number;
      participants: number;
      batches: number;
    }>;
  }>;

  /**
   * Export payroll data
   */
  exportPayrollData(batchId: string, format: 'csv' | 'excel' | 'pdf'): Promise<{
    filename: string;
    url: string;
    size: number;
  }>;

  /**
   * Import payroll adjustments
   */
  importPayrollAdjustments(batchId: string, adjustments: Array<{
    userId: string;
    amount: number;
    reason: string;
  }>): Promise<PayrollBatch>;

  /**
   * Get payroll audit trail
   */
  getPayrollAuditTrail(batchId: string): Promise<Array<{
    action: string;
    performedBy: string;
    performedAt: Date;
    details: Record<string, any>;
  }>>;

  /**
   * Calculate next payroll date
   */
  calculateNextPayrollDate(period: PayrollPeriod, lastPayrollDate?: Date): Promise<Date>;

  /**
   * Get payroll calendar
   */
  getPayrollCalendar(year: number): Promise<Array<{
    period: PayrollPeriod;
    startDate: Date;
    endDate: Date;
    payrollDate: Date;
    status: 'upcoming' | 'current' | 'completed';
  }>>;
}