/**
 * Sales Return Domain Service
 * Pure business logic for return processing
 * No infrastructure dependencies
 */

import {
  SalesReturn,
  SalesReturnItem,
  CreateSalesReturnRecord,
  SalesReturnStatus,
} from './sales-return.model';
import type { SalesInvoice, SalesInvoiceItem } from './sales-invoice.model';

/**
 * Validation result type
 */
export type ValidationResult = {
  valid: boolean;
  errors: string[];
};

/**
 * Calculate totals for a return based on returned items
 */
export function calculateSalesReturnTotals(items: SalesReturnItem[]): {
  subTotal: number;
  taxAmount: number;
  totalAmount: number;
} {
  let subTotal = 0;
  
  for (const item of items) {
    subTotal += item.returnValue;
  }
  
  // Tax calculation would need to be based on original invoice
  // For now, return basic calculation
  const taxAmount = 0;
  const totalAmount = subTotal + taxAmount;
  
  return {
    subTotal,
    taxAmount,
    totalAmount,
  };
}

/**
 * Validate a return creation against original invoice
 */
export function validateReturnAgainstInvoice(
  invoice: SalesInvoice,
  input: CreateSalesReturnRecord
): ValidationResult {
  const errors: string[] = [];
  
  // Validate invoice is eligible for returns
  if (invoice.status === 'cancelled') {
    errors.push('Cannot create returns for cancelled invoices');
  }
  
  if (!invoice.items || invoice.items.length === 0) {
    errors.push('Invoice has no items to return');
  }
  
  // Validate each return item against invoice lines
  for (const returnItem of input.items) {
    const invoiceLine = invoice.items.find(
      (line) => line.materialId === returnItem.materialId
    );
    
    if (!invoiceLine) {
      errors.push(
        `Material ${returnItem.materialId} not found in original invoice`
      );
      continue;
    }
    
    // Check return quantity doesn't exceed original
    if (returnItem.returnedQuantity > invoiceLine.quantity) {
      errors.push(
        `Return quantity (${returnItem.returnedQuantity}) exceeds original quantity (${invoiceLine.quantity}) for ${returnItem.materialId}`
      );
    }
    
    if (returnItem.returnedQuantity <= 0) {
      errors.push(
        `Return quantity must be positive for ${returnItem.materialId}`
      );
    }
  }
  
  return {
    valid: errors.length === 0,
    errors,
  };
}

/**
 * Can a return be approved?
 */
export function canApproveReturn(
  returnStatus: SalesReturnStatus
): boolean {
  return returnStatus === 'pending';
}

/**
 * Can a return be received?
 */
export function canReceiveReturn(
  returnStatus: SalesReturnStatus
): boolean {
  return returnStatus === 'approved';
}

/**
 * Can a return be processed (credited/refunded)?
 */
export function canProcessReturn(
  returnStatus: SalesReturnStatus
): boolean {
  return returnStatus === 'received';
}

/**
 * Can a return be rejected?
 */
export function canRejectReturn(
  returnStatus: SalesReturnStatus
): boolean {
  return returnStatus === 'pending';
}

/**
 * Can a return be cancelled?
 */
export function canCancelReturn(
  returnStatus: SalesReturnStatus
): boolean {
  // Can cancel from pending or approved states
  return returnStatus === 'pending' || returnStatus === 'approved';
}

/**
 * Get next status after approval
 */
export function getNextStatusAfterApproval(
  currentStatus: SalesReturnStatus
): SalesReturnStatus {
  if (currentStatus === 'pending') {
    return 'approved';
  }
  return currentStatus;
}

/**
 * Get next status after receiving
 */
export function getNextStatusAfterReceiving(
  currentStatus: SalesReturnStatus
): SalesReturnStatus {
  if (currentStatus === 'approved') {
    return 'received';
  }
  return currentStatus;
}

/**
 * Get next status after processing
 */
export function getNextStatusAfterProcessing(
  currentStatus: SalesReturnStatus
): SalesReturnStatus {
  if (currentStatus === 'received') {
    return 'processed';
  }
  return currentStatus;
}

/**
 * Validate return rejection
 */
export function validateReturnRejection(
  returnStatus: SalesReturnStatus,
  rejectionReason: string
): ValidationResult {
  const errors: string[] = [];
  
  if (!canRejectReturn(returnStatus)) {
    errors.push(`Cannot reject return with status: ${returnStatus}`);
  }
  
  if (!rejectionReason || rejectionReason.trim().length === 0) {
    errors.push('Rejection reason is required');
  }
  
  return {
    valid: errors.length === 0,
    errors,
  };
}

/**
 * Validate return cancellation
 */
export function validateReturnCancellation(
  returnStatus: SalesReturnStatus,
  cancellationReason: string
): ValidationResult {
  const errors: string[] = [];
  
  if (!canCancelReturn(returnStatus)) {
    errors.push(`Cannot cancel return with status: ${returnStatus}`);
  }
  
  if (!cancellationReason || cancellationReason.trim().length === 0) {
    errors.push('Cancellation reason is required');
  }
  
  return {
    valid: errors.length === 0,
    errors,
  };
}

/**
 * Calculate refund amount based on return value and potential restocking fee
 */
export function calculateRefundAmount(
  returnTotalAmount: number,
  restockablePortion: number,
  restockingFeePercent: number = 0
): number {
  const nonRestockableDeduction = returnTotalAmount - restockablePortion;
  const restockingFee = restockablePortion * (restockingFeePercent / 100);
  
  return Math.max(0, returnTotalAmount - nonRestockableDeduction - restockingFee);
}

/**
 * Build invoice lines from return items
 */
export function buildCreditNoteItemsFromReturn(
  returnItems: SalesReturnItem[]
): Array<{
  materialId: string;
  name: string;
  quantity: number;
  unitPrice: number;
  total: number;
}> {
  return returnItems.map((item) => ({
    materialId: item.materialId,
    name: item.name,
    quantity: item.returnedQuantity,
    unitPrice: item.unitPrice,
    total: item.returnValue,
  }));
}
