/**
 * Sales Invoice Repository Interface
 * Defines the contract for data persistence
 */

import {
  SalesInvoice,
  CreateSalesInvoiceRecord,
  SalesInvoicePaymentMethod,
} from '../domain/sales-invoice.model';

export type CreateSalesInvoiceDto = CreateSalesInvoiceRecord & {
  id?: string; // Pre-generated ID (optional, generated if not provided)
  invoiceNumber?: string; // Pre-generated invoice number (optional, generated if not provided)
  customerName?: string; // Optional, can be looked up from customerId
  secondaryCustomerName?: string; // Optional, can be looked up from secondaryCustomerId
  subTotal?: number; // Calculated, included here for convenience
  lineDiscountTotal?: number; // Calculated
  totalDiscount?: number; // Calculated
  taxAmount?: number; // Calculated
  grandTotal?: number; // Calculated
  amountDue?: number; // Calculated
  paymentStatus?: 'due' | 'partial' | 'paid' | 'overdue'; // Calculated
  postingStatus?: 'draft' | 'saved' | 'posted'; // Default: 'saved'
  shippingStatus?: 'pending' | 'shipped' | 'partial' | 'delivered' | 'cancelled'; // Default: 'pending'
  status?: 'active' | 'delivered' | 'cancelled'; // Default: 'active'
  createdAt?: string; // Set by repository if not provided
};

export interface SalesInvoiceRepository {
  /**
   * Create a new sales invoice
   */
  create(dto: CreateSalesInvoiceDto): Promise<SalesInvoice>;

  /**
   * Get invoice by ID
   */
  getById(id: string): Promise<SalesInvoice | null>;

  /**
   * Get invoice by invoice number
   */
  getByInvoiceNumber(invoiceNumber: string): Promise<SalesInvoice | null>;

  /**
   * Get invoices by customer ID with pagination
   */
  getByCustomerId(
    customerId: string,
    options?: { skip?: number; take?: number }
  ): Promise<SalesInvoice[]>;

  /**
   * List all invoices with optional filtering
   */
  list(options?: {
    skip?: number;
    take?: number;
    status?: string;
    documentType?: 'shipment' | 'tax_invoice';
    customerId?: string;
    search?: string; // Search in invoice number or customer name
    excludeShipments?: boolean;
  }): Promise<{ items: SalesInvoice[]; total: number }>;

  /**
   * Update invoice
   */
  update(id: string, updates: Partial<SalesInvoice>): Promise<SalesInvoice>;

  /**
   * Lock invoice for editing (pessimistic concurrency)
   */
  lock(id: string, userId: string, userName: string): Promise<SalesInvoice>;

  /**
   * Unlock invoice
   */
  unlock(id: string): Promise<SalesInvoice>;

  /**
   * Cancel invoice
   */
  cancel(
    id: string,
    reason: string,
    cancelledBy: string,
    cancelledByName: string
  ): Promise<SalesInvoice>;

  /**
   * Mark invoice as shipped
   */
  markAsShipped(
    id: string,
    shipmentId: string,
    shipmentDate: string,
    shippedBy: string,
    shippedByName: string
  ): Promise<SalesInvoice>;

  /**
   * Mark invoice as delivered
   */
  markAsDelivered(
    id: string,
    deliveredAt: string,
    deliveredBy: string
  ): Promise<SalesInvoice>;

  /**
   * Record payment received
   */
  recordPayment(
    id: string,
    amount: number,
    method: SalesInvoicePaymentMethod,
    recordedBy: string
  ): Promise<SalesInvoice>;

  /**
   * Add activity log entry
   */
  addActivityLog(
    id: string,
    action: string,
    message: string,
    by: string,
    byName?: string,
    details?: Record<string, unknown>
  ): Promise<void>;
}
