export type Installment = {
    date: Date;
    amount: number;
}

export type FinancialRecord = {
  id: string;
  requestId?: string;
  description: string;
  totalAmount: number; // For advances, this is the principal. For deductions/bonuses, it's the amount.
  installments: Installment[];
};

export type LeaveRequest = {
  id: string;
  employeeId: string;
  employeeName: string;
  reason: string;
  status: 'pending' | 'approved' | 'rejected';
  requestType: 'leave' | 'advance' | 'shift-swap';
  
  // For leave
  from?: Date;
  to?: Date;

  // For advance
  amount?: number;

  // For shift-swap
  shiftDate?: Date;
  toEmployeeId?: string;
  toEmployeeName?: string;
};

export type AttendanceRecord = {
  date: string; // YYYY-MM-DD
  checkIn: string; // ISO String
  checkOut: string | null; // ISO String or null
};

// New attendance system types
export type AttendanceRecordType = 'present' | 'absent' | 'late' | 'sick' | 'leave';
export type AttendanceDevice = 'web' | 'biometric' | 'face_recognition' | 'mobile';
export type AttendanceStatus = 'pending' | 'approved' | 'rejected';
export type JustificationType = 'sick-leave' | 'personal-leave' | 'permission';

export type NewAttendanceRecord = {
  id: string;
  employeeId: string;
  date: string; // YYYY-MM-DD
  recordType: AttendanceRecordType;
  
  // Check-in and check-out times
  checkInTime?: string; // ISO
  checkOutTime?: string; // ISO
  durationHours?: number;
  lateMinutes?: number;
  
  // Device information
  device: AttendanceDevice;
  deviceId?: string; // Biometric ID or device MAC
  ipAddress?: string;
  
  // Notes and justification
  notes?: string;
  justification?: string;
  justificationType?: JustificationType;
  
  // Approval tracking
  status: AttendanceStatus;
  approvedBy?: string;
  approvalDate?: string;
  approvalReason?: string;
  
  // Metadata
  createdAt: string;
  createdBy?: string;
  updatedAt: string;
  updatedBy?: string;
};

export type AttendanceAuditEntry = {
  id: string;
  recordId: string;
  action: 'created' | 'updated' | 'approved' | 'rejected' | 'deleted';
  changedBy: string;
  changedAt: string;
  previousValue?: Record<string, any>;
  newValue?: Record<string, any>;
  reason?: string;
};

export type AttendanceCorrectionStatus = 'pending' | 'approved' | 'rejected';

export type AttendanceCorrectionRequest = {
  id: string;
  recordId: string;
  employeeId: string;
  reason: string;
  requestedRecordType?: AttendanceRecordType;
  requestedCheckInTime?: string;
  requestedCheckOutTime?: string;
  status: AttendanceCorrectionStatus;
  reviewedBy?: string;
  reviewedAt?: string;
  reviewReason?: string;
  createdAt: string;
  updatedAt: string;
};

export type EmployeeBiometricMapping = {
  id: string;
  employeeId: string;
  employeeName: string;
  biometricId: string; // Fingerprint ID or device ID
  deviceType: 'fingerprint' | 'face' | 'iris' | 'other';
  deviceMacAddress?: string;
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
};

export type SystemRole = 'admin' | 'employee' | 'pos';

export type EmployeePermissionKey =
  | 'admin.dashboard'
  | 'admin.employees'
  | 'admin.leave-requests'
  | 'admin.advance-requests'
  | 'admin.shifts'
  | 'admin.hr-attendance'
  | 'admin.production'
  | 'admin.sales'
  | 'admin.pos'
  | 'admin.purchases'
  | 'admin.checks'
  | 'admin.expense-recurring'
  | 'admin.work-tasks'
  | 'admin.accounting'
  | 'admin.monitoring'
  | 'admin.materials'
  | 'admin.parties'
  | 'admin.cancel-invoices'
  | 'settings.manage'
  | 'employee.dashboard'
  | 'employee.statement'
  | 'employee.leave'
  | 'employee.advance'
  | 'employee.shift-swap'
  | 'employee.work-tasks'
  | 'employee.my-tasks';

export type EmployeePermissionProfile = {
  id: string;
  name: string;
  description?: string;
  role: SystemRole;
  permissions: EmployeePermissionKey[];
};


export type Employee = {
  id: string;
  name: string;
  employeeCode?: string;
  nationalId?: string;
  workEmail?: string;
  birthDate?: string;
  gender?: 'male' | 'female' | 'other';
  hireDate?: string;
  department?: string;
  managerName?: string;
  workLocation?: string;
  emergencyContactName?: string;
  emergencyContactPhone?: string;
  employeeCashAccountId?: string;
  employeeCashAccountCode?: string;
  employeeChecksAccountId?: string;
  employeeChecksAccountCode?: string;
  payrollExpenseAccountCode?: string;
  payrollLiabilityAccountCode?: string;
  employeeAdvanceAccountCode?: string;
  role: SystemRole;
  permissionProfileId?: string;
  businessRole?: string; // وظيفة الموظف التشغيلية (مثل: موظف، مندوب مبيعات، محاسب)
  username: string;
  password?: string;
  phone?: string;
  region?: string;
  commissionRate?: number;
  salaryType: 'monthly' | 'daily';
  salary: number;
  allowedPto: number; // in days
  status: 'permanent' | 'temporary';
  defaultShift: 'first' | 'second' | 'none';
  warehouseIds?: string[]; // المستودعات التي يتبع لها الموظف
  financialRecords: FinancialRecord[];
  attendance: AttendanceRecord[];
  leaveRequests: Omit<LeaveRequest, 'employeeId' | 'employeeName' | 'toEmployeeName'>[];
};

export type StatementRow = {
    month: string;
    grossSalary: number;
    deductions: number;
    bonuses: number;
    netSalary: number;
    isPaid: boolean;
}

export type CustomerCategory = {
  id: string;
  name: string;
  categoryNumber?: string;
  nameEn?: string;
  discountPercent?: number;
  description?: string;
};

export type ItemGroup = {
  id: string;
  groupNumber?: string;
  name: string;
  isPosEnabled: boolean;
  usesDefaultTax?: boolean; // Use default tax rate or override with custom taxRate
  taxRate?: number; // Tax rate percentage (0-100) for this item group (overrides default)
};

export type ManagedUnit = {
  id: string;
  unitNumber: string;
  description: string;
  unitType?: 'primary' | 'secondary';
  shortCode?: string;
  notes?: string;
};

export type Shelf = {
  id: string;
  shelfNumber?: string;
  name: string;
  sequence: number;
  notes?: string;
  inactive?: boolean;
};

export type Warehouse = {
  id: string;
  warehouseNumber?: string;
  name: string;
  branchName?: string;
  departments?: string[];
  warehouseType?: 'main' | 'branch' | 'returns' | 'transit';
  managerEmployeeId?: string;
  managerName?: string;
  operatingStatus?: 'active' | 'stopped' | 'inventory';
  city?: string;
  address?: string;
  contactPhone?: string;
  allowIssueWithoutStock?: boolean;
  useInPos?: boolean;
  location?: string;
  notes?: string;
  inactive?: boolean;
  shelves: Shelf[];
};

export type StockLocationBalance = {
  materialId: string;
  warehouseId: string;
  warehouseName: string;
  shelfId: string;
  shelfName: string;
  quantity: number;
};

export type RestaurantServiceChannel = 'dine_in' | 'takeaway' | 'delivery';

export type RestaurantTableStatus = 'available' | 'occupied' | 'reserved' | 'cleaning' | 'out_of_service';

export type RestaurantOrderSessionStatus =
  | 'open'
  | 'in_preparation'
  | 'ready'
  | 'served'
  | 'partially_paid'
  | 'closed'
  | 'cancelled';

export type RestaurantArea = {
  id: string;
  areaCode?: string;
  name: string;
  displayOrder?: number;
  colorHex?: string;
  inactive?: boolean;
};

export type RestaurantTable = {
  id: string;
  tableCode?: string;
  name: string;
  areaId?: string;
  seatsCount?: number;
  status: RestaurantTableStatus;
  inactive?: boolean;
};

export type RestaurantOrderSession = {
  id: string;
  sessionNumber: string;
  channel: RestaurantServiceChannel;
  areaId?: string;
  tableId?: string;
  invoiceId?: string;
  guestCount: number;
  status: RestaurantOrderSessionStatus;
  startedAt: string;
  closedAt?: string;
};

export type RestaurantTableEventType =
  | 'session_opened'
  | 'table_assigned'
  | 'table_merged'
  | 'item_transferred'
  | 'bill_split'
  | 'partial_checkout'
  | 'session_closed'
  | 'session_cancelled';

export type RestaurantTableEvent = {
  id: string;
  sessionId: string;
  tableId?: string;
  eventType: RestaurantTableEventType;
  eventAt: string;
  actorName?: string;
  actorId?: string;
  reason?: string;
  payload?: Record<string, unknown>;
};

export type MaterialStockReport = {
  materialId: string;
  locations: StockLocationBalance[];
};

export type MaterialMovementEntry = {
  id: string;
  date: string;
  materialId: string;
  materialName: string;
  referenceType: 'purchase' | 'sale' | 'sale-return' | 'transfer' | 'transfer-doc' | 'purchase-return' | 'purchase-return-cancel' | 'disassembly';
  referenceNumber: string;
  direction: 'in' | 'out';
  quantity: number;
  warehouseId?: string;
  warehouseName?: string;
  shelfId?: string;
  shelfName?: string;
  note?: string;
  sourceParentItemId?: string;
  sourceParentItemName?: string;
  sourceParentRecordId?: string;
};

export type MaterialExpiryFifoRow = {
  materialId: string;
  materialName: string;
  locationSummary?: string;
  purchaseOrderId: string;
  purchaseOrderNumber: string;
  purchaseDate: string;
  expiryDate: string;
  shelfLifeDays: number;
  remainingQuantity: number;
  remainingDays: number;
  status: 'expired' | 'near-expiry' | 'valid';
};

export type ShipmentType = 'internal' | 'adjustment' | 'reverse' | 'inventory_count';

export type ShipmentStatus = 'pending' | 'partial' | 'completed' | 'cancelled' | 'locked';

export type Shipment = {
  id: string;
  shipmentNumber: string;
  shipmentType: ShipmentType;
  sequenceNumber: number;
  fiscalYear: number;
  date: string;
  status: ShipmentStatus;
  invoiceId?: string;
  hasInventoryMovement?: boolean;
  periodCloseDate?: string;
  inventoryCloseDate?: string;
};

export type ShipmentSequence = {
  id: string;
  shipmentType: ShipmentType;
  fiscalYear: number;
  lastNumber: number;
};

export type ShipmentItem = {
  id?: string;
  shipmentId: string;
  materialId: string;
  quantity: number;
  warehouseId: string;
  shelfId: string;
  costPerUnitOriginal: number;
  currencyCode: string;
  taxRate: number;
  discountRate: number;
  fxRate: number;
};

export type InventoryMovement = {
  id: string;
  date: string;
  materialId: string;
  warehouseId: string;
  shelfId: string;
  quantityIn: number;
  quantityOut: number;
  referenceType: string;
  referenceId: string;
  shipmentId?: string;
  invoiceId?: string;
  costPerUnitOriginal?: number;
  sourceParentItemId?: string;
  sourceParentRecordId?: string;
  note?: string;
};

export type InternalTransfer = {
  id: string;
  transferNumber: string;
  date: string;
  materialId: string;
  quantity: number;
  fromWarehouseId: string;
  fromShelfId: string;
  toWarehouseId: string;
  toShelfId: string;
  note?: string;
  createdBy: string;
  createdAt: string;
};

export type TransferLock = {
  materialId: string;
  userId: string;
  userName: string;
  lockedAt: string;
  expiresAt: string;
};

export type InternalTransferItem = {
  lineId?: string;
  materialId: string;
  quantity: number;
  unitCostSnapshot?: number;
  receivedQuantity?: number;
  receiptDistributions?: Array<{
    shelfId: string;
    quantity: number;
  }>;
  rejectedQuantity?: number;
  overReceivedQuantity?: number;
  overApprovedQuantity?: number;
  overageStatus?: 'pending' | 'approved' | 'rejected';
  overageSourceShelfId?: string;
  fromWarehouseId: string;
  fromShelfId: string;
  toWarehouseId: string;
  toShelfId: string;
  note?: string;
};

export type InternalTransferDocument = {
  id: string;
  transferNumber: string;
  date: string;
  status: 'active' | 'cancelled';
  receiptStatus?: 'pending' | 'partial' | 'received' | 'pending-approval';
  supplierId?: string;
  supplierName?: string;
  supplierInvoiceNumber?: string;
  sourcePurchaseOrderId?: string;
  sourcePurchaseOrderNumber?: string;
  sourcePurchaseDocumentType?: 'shipment' | 'tax_invoice';
  enableWarehouseTransfer: boolean;
  enableShelfTransfer: boolean;
  allowZeroItems: boolean;
  items: InternalTransferItem[];
  note?: string;
  createdBy: string;
  createdAt: string;
  receivedBy?: string;
  receivedAt?: string;
  receiptNote?: string;
  shortageResolutionType?: 'supplier' | 'employee' | 'wastage' | 'resend';
  shortageResolutionNote?: string;
  shortageResolvedBy?: string;
  shortageResolvedAt?: string;
  shortageJournalEntryId?: string;
  shortageValue?: number;
  cancelledBy?: string;
  cancelledAt?: string;
  cancelledReason?: string;
};

export type Customer = {
  id: string;
  name: string;
  balance: number; // Positive balance means they owe us money
  category: string;
  customerNumber: string;
  accountId?: string;
  accountCode?: string;
  phone?: string;
  creditLimit?: number;
  address?: string;
  allowedDiscount?: number; // Discount percentage (0-100)
  salesRepId?: string;
};

export type SalesRep = {
  id: string;
  name: string;
  phone?: string;
  region?: string;
  commissionRate?: number; // Percentage (0-100)
};

export type Coupon = {
  id: string;
  couponNumber: string;
  couponCode: string;
  title: string;
  originalAmount: number;
  remainingAmount: number;
  originalAmountBase?: number;
  remainingAmountBase?: number;
  status: 'active' | 'used' | 'expired' | 'cancelled';
  currencyCode?: string;
  baseCurrencyCode?: string;
  exchangeRate?: number; // Base currency per 1 unit of coupon currency
  rateDate?: string; // Historical rate capture date at issuance
  cumulativeFxDifferenceBase?: number; // Signed cumulative realized FX difference in base currency
  lastFxSettlementAt?: string;
  lastFxReferenceId?: string;
  customerType?: 'cash' | 'customer';
  customerId?: string;
  customerName?: string;
  customerAccountCode?: string;
  paymentMethod?: 'cash' | 'check' | 'credit';
  settlementAccountCode?: string;
  settlementAccountName?: string;
  liabilityAccountCode?: string;
  liabilityAccountName?: string;
  soldAt: string;
  expiryDate?: string;
  notes?: string;
  createdBy?: string;
  createdAt: string;
  updatedAt?: string;
  lastUsedAt?: string;
  lastUsedBy?: string;
  lastReferenceId?: string;
};

export type CampaignStatus = 'active' | 'scheduled' | 'expired' | 'inactive';
export type CampaignType = 'multi_buy' | 'mix_match' | 'buy_x_get_y' | 'tier_pricing' | 'fixed_bundle';

export type CampaignItem = {
  id: string;
  campaignId: string;
  productId?: string;
  categoryId?: string;
  minQty: number;
  bundlePrice: number;
  regularUnitPrice?: number;
  maxApplications?: number;
};

export type Campaign = {
  id: string;
  name: string;
  type: CampaignType;
  startDate: string;
  endDate: string;
  status: CampaignStatus;
  description?: string;
  branchIds?: string[];
  customerTags?: string[];
  autoApplyInPos?: boolean;
  allowRepeats?: boolean;
  allowStacking?: boolean;
  priority?: number;
  maxApplicationsPerInvoice?: number;
  items: CampaignItem[];
  createdAt: string;
  createdBy?: string;
  updatedAt?: string;
};

export type PaymentMethod = 'cash' | 'visa' | 'receivables' | 'coupon' | 'check' | 'bank_transfer' | 'credit';

export type PaymentBreakdown = {
  method: PaymentMethod;
  amount: number;
  // For receivables: optional customer name to display
  customerName?: string;
  // For visa: optional bank account id for routing
  bankAccountId?: string;
  // For coupon: coupon code and optional coupon id
  couponCode?: string;
  couponId?: string;
};

export type SalesPaymentAllocation = {
  invoiceId: string;
  invoiceNumber?: string;
  invoiceCurrencyCode?: string;
  invoiceExchangeRate?: number;
  invoiceRateDate?: string;
  amount: number;
  amountBase?: number;
  fxDifferenceBase?: number;
};

export type CustomerPayment = {
  id: string;
  date: string;
  status?: 'active' | 'cancelled';
  customerId: string;
  amount: number;
  amountBase?: number;
  currencyCode?: string;
  baseCurrencyCode?: string;
  exchangeRate?: number;
  rateDate?: string;
  isAdvance?: boolean;
  method?: PaymentMethod; // Payment method used (cash, visa, receivables)
  postingStatus?: 'draft' | 'saved' | 'posted';
  reference?: string;
  notes?: string;
  allocations?: SalesPaymentAllocation[];
  appliedAmount?: number;
  unappliedAmount?: number;
  totalFxDifferenceBase?: number;
  createdBy?: string;
  cancelledAt?: string;
  cancelledBy?: string;
  cancelledReason?: string;
  salesRepId?: string;
  // New fields for mixed payment support
  breakdown?: PaymentBreakdown[]; // Breakdown of payment methods if using multiple
};

export type SupplierPaymentAllocation = {
  id: string;
  purchaseOrderId: string;
  purchaseOrderNumber?: string;
  invoiceCurrencyCode: string;
  invoiceExchangeRate: number;
  invoiceRateDate?: string;
  amount: number; // Amount allocated in invoice/payment currency
  amountBase: number; // Amount allocated in base currency using payment rate
  fxDifferenceBase?: number; // Payment base - invoice base for this allocation
};

export type SupplierPayment = {
  id: string;
  date: string;
  status?: 'active' | 'cancelled';
  postingStatus?: 'draft' | 'saved' | 'posted';
  paymentMethod?: 'cash' | 'check' | 'bank_transfer' | 'credit';
  checkSource?: 'issued' | 'incoming';
  incomingCheckIds?: string[];
  cancelledAt?: string;
  cancelledBy?: string;
  cancelledReason?: string;
  supplierId: string;
  amount: number; // Entered amount in payment currency
  amountBase?: number; // Converted amount in base currency using payment rate
  currencyCode?: string; // Payment currency code
  baseCurrencyCode?: string; // System base currency at payment time
  exchangeRate?: number; // Base per 1 unit of payment currency
  rateDate?: string; // Date the rate was captured
  isAdvance?: boolean; // True when not allocated to invoices
  allocations?: SupplierPaymentAllocation[]; // Optional invoice allocations
  totalFxDifferenceBase?: number;
  reference?: string;
  notes?: string;
};

export type ProductShape = {
  id: string;
  name: string;
  salePrice: number;
  costPrice?: number;
  type?: string;
  isActive?: boolean;
};

export type SecondaryUnit = {
  unit?: string;
  barcode?: string;
  quantity?: number;
  price?: number;
};

export type ProductionFormulaLine = {
  materialId: string;
  quantity: number;
  unit?: string;
  notes?: string;
  wastePercent?: number;
};

export type DisassemblyTemplateLine = {
  partItemId: string;
  quantity: number;
  expectedSalePrice?: number;
  notes?: string;
};

export type DisassemblyRecordPart = {
  partItemId: string;
  partName: string;
  quantity: number;
  expectedSalePrice: number;
  allocatedCost: number;
  costPerUnit: number;
  sourceParentItemId: string;
  notes?: string;
};

export type DisassemblyRecord = {
  id: string;
  recordNumber: string;
  date: string;
  parentItemId: string;
  parentItemName: string;
  parentQuantity: number;
  sourceWarehouseId?: string;
  sourceShelfId?: string;
  targetWarehouseId?: string;
  targetShelfId?: string;
  purchaseCost: number;
  additionalCost?: number;
  totalCostAllocated: number;
  parts: DisassemblyRecordPart[];
  notes?: string;
  createdBy: string;
  createdAt: string;
};

export type RealEstateAllocationMethod = 'area' | 'sale-value' | 'manual-share';
export type RealEstateUnitStatus = 'planned' | 'available' | 'reserved' | 'sold';
export type RealEstateInstallmentStatus = 'pending' | 'partially-paid' | 'paid' | 'overdue';

export type RealEstateInstallment = {
  id: string;
  title?: string;
  dueDate?: string;
  amount: number;
  paidAmount?: number;
  status?: RealEstateInstallmentStatus;
  notes?: string;
};

export type RealEstateDirectCostEntry = {
  id: string;
  phase?: string;
  title?: string;
  amount: number;
  date?: string;
  notes?: string;
};

export type RealEstateFloorUnitDetail = {
  id: string;
  unitLabel?: string;
  area?: number;
  estimatedSaleValue?: number;
  notes?: string;
};

export type RealEstateFloorDetail = {
  id: string;
  floorLabel?: string;
  usageType?: string;
  description?: string;
  unitCount?: number;
  unitArea?: number;
  estimatedUnitSaleValue?: number;
  unitDetails?: RealEstateFloorUnitDetail[];
  notes?: string;
};

export type RealEstateUnit = {
  id: string;
  unitCode?: string;
  name: string;
  floor?: string;
  area: number;
  saleValue?: number;
  actualSaleValue?: number;
  directCost?: number;
  directCostEntries?: RealEstateDirectCostEntry[];
  buyerCustomerId?: string;
  buyerName?: string;
  contractDate?: string;
  handoverDate?: string;
  collectedAmount?: number;
  lastCollectionDate?: string;
  installments?: RealEstateInstallment[];
  status?: RealEstateUnitStatus;
  notes?: string;
};

export type RealEstateSharedCostAllocation = {
  unitId: string;
  percentage: number;
};

export type RealEstateSharedCost = {
  id: string;
  title: string;
  category?: string;
  amount: number;
  allocationMethod: RealEstateAllocationMethod;
  notes?: string;
  unitAllocations?: RealEstateSharedCostAllocation[];
};

export type RealEstateAccountingSetup = {
  projectsRootAccountId?: string;
  projectsRootAccountCode?: string;
  directCostAccountId?: string;
  directCostAccountCode?: string;
  sharedCostAccountId?: string;
  sharedCostAccountCode?: string;
  salesRevenueAccountId?: string;
  salesRevenueAccountCode?: string;
  costOfSalesAccountId?: string;
  costOfSalesAccountCode?: string;
  projectAccountId?: string;
  projectAccountCode?: string;
};

export type RealEstateProject = {
  id: string;
  name: string;
  code: string;
  location?: string;
  startDate?: string;
  targetCompletionDate?: string;
  floorCount?: number;
  designSummary?: string;
  floorDetails?: RealEstateFloorDetail[];
  status: 'draft' | 'active' | 'completed';
  notes?: string;
  units: RealEstateUnit[];
  sharedCosts: RealEstateSharedCost[];
  sharedCostAllocationMethod?: RealEstateAllocationMethod;
  sharedCostUnitAllocations?: RealEstateSharedCostAllocation[];
  accounting?: RealEstateAccountingSetup;
  createdBy: string;
  createdAt: string;
  updatedAt?: string;
};

export type ItemUnitStatus = 'available' | 'in_stock' | 'sold' | 'returned' | 'damaged';

export type ItemUnit = {
  id: string;
  itemId: string;
  serialNumber?: string;
  rfidCode?: string;
  status: ItemUnitStatus;
  warehouseId?: string;
  location?: string;
  notes?: string;
  invoiceId?: string;
  createdAt: string;
};

export type PrinterConnectionType = 'network' | 'windows' | 'usb';
export type PrinterPaperWidth = '58mm' | '80mm' | 'a4';
export type PrinterRole = 'receipt' | 'prep' | 'both';
export type PrintTransportMode = 'browser' | 'native-bridge';

export type PrinterConfig = {
  id: string;
  name: string;
  connectionType?: PrinterConnectionType;
  ipAddress?: string;
  port?: number;
  shareName?: string;
  paperWidth?: PrinterPaperWidth;
  role?: PrinterRole;
  enabled?: boolean;
};

export type PrintSectionConfig = {
  id: string;
  name: string;
  printerId?: string;
  copies?: number;
  printPrices?: boolean;
  enabled?: boolean;
};

export type PrintingSettings = {
  customPrintersEnabled?: boolean;
  printerAutoPrintEnabled?: boolean;
  printTransportMode?: PrintTransportMode;
  defaultCustomerReceiptPrinterId?: string;
  printHeaderLeftText?: string;
  printHeaderCenterText?: string;
  printHeaderRightText?: string;
  printHeaderText?: string;
  printFooterText?: string;
  printerConfigs?: PrinterConfig[];
  printSections?: PrintSectionConfig[];
};

export type ItemCategory = 'inventory' | 'service' | 'non_stock' | 'bundle';

export type ProductionItem = {
  id: string; // use item number as id
  name: string;
  itemCategory?: ItemCategory;
  reorderMinimumQty?: number;
  reorderUnit?: string;
  itemSymbolName?: string;
  globalReferenceNumber?: string;
  itemNumber: string;
  barcode?: string;
  secondaryBarcode?: string;
  additionalBarcodes?: string[];
  primaryUnit?: string;
  primaryUnitQuantity?: number;
  secondaryUnit?: string;
  secondaryUnitQuantity?: number;
  secondaryUnitPrice?: number;
  secondaryUnits?: SecondaryUnit[];
  isWeighed?: boolean;
  isSized?: boolean;
  isManufactured?: boolean;
  productionOutputQuantity?: number;
  productionFormula?: ProductionFormulaLine[];
  isDisassemblable?: boolean;
  disassemblyTemplate?: DisassemblyTemplateLine[];
  shelfLifeYears?: number;
  shelfLifeMonths?: number;
  shelfLifeDays?: number;
  storeSectionId?: string;
  storeBranchId?: string;
  printSectionId?: string;
  excludeFromPrepTicket?: boolean;
  printLabelOverride?: string;
  realEstateProjectId?: string;
  realEstateUnitId?: string;
  realEstateCostType?: 'general' | 'direct-unit' | 'shared-project';
  realEstateAllocationMethod?: RealEstateAllocationMethod;
  alternativeItemIds?: string[];
  groupId?: string;
  additionalDetails?: string;
  imageUrl?: string;
  purchasePrice?: number;
  purchaseCurrencyCode?: string;
  salePrice: number;
  // Per-category override prices keyed by customer category id (empty when none)
  categoryPrices: Record<string, number>;
  allowDescriptionEdit?: boolean;
  hasSerialNumber?: boolean;
  hasRfid?: boolean;
  usesDefaultTax?: boolean; // Use default tax rate or override with custom taxRate
  taxRate?: number; // Tax rate percentage (0-100) for this item (overrides group tax rate)
  enableProfitMargin?: boolean;
  profitMargin?: number;
  usesProductShapes?: boolean;
  productShapeType?: string;
  productShapes?: ProductShape[];
  // Accounting account codes - optional overrides for journal entries
  revenueAccountCode?: string;      // حساب الإيرادات (افتراضي: 4110)
  inventoryAccountCode?: string;    // حساب المخزون (افتراضي: 1170)
  cogsAccountCode?: string;         // تكلفة البضاعة المباعة (افتراضي: 5110)
  purchaseAccountCode?: string;     // حساب المشتريات (افتراضي: 5110)
}

export type ProductionDebt = {
  customerName: string; // For new customers or one-off
  amount: number;
};

export type ProductionDebtPayment = {
  customerId: string;
  amount: number;
};

export type ProductionConsumption = {
  materialId: string;
  value: number;
};

export type ProductionExpense = {
  expenseId: string;
  value: number;
};

export type ProductionReport = {
  id: string; // e.g., '2024-07-25'
  date: string; // ISO string
  submittedBy: string; // employee name
  dailySales: number;
  newDebts: ProductionDebt[];
  debtPayments: ProductionDebtPayment[];
  consumedMaterials: ProductionConsumption[];
  expenses: ProductionExpense[];
  cashboxInventory: number;
};

export type CustomerPriceInfo = {
  materialId: string;
  price: number;
};

export type CustomerBonusInfo = {
  materialId: string;
  buyQuantity: number;
  bonusQuantity: number;
};

export type CustomerPricing = {
  category: string;
  prices: CustomerPriceInfo[];
  bonus?: CustomerBonusInfo;
};

export type SalesInvoiceItem = {
  materialId: string;
  name: string;
  description?: string;
  itemUnitId?: string;
  serialNumber?: string;
  rfidCode?: string;
  realEstateProjectId?: string;
  realEstateProjectName?: string;
  realEstateUnitId?: string;
  realEstateUnitName?: string;
  quantity: number;
  unitPrice: number;
  bonus: number;
  discount?: number;
  total: number;
  warehouseId?: string;
  shelfId?: string;
  printSectionId?: string;
  printLabel?: string;
  excludeFromPrepTicket?: boolean;
};

export type SalesInvoice = {
  id: string;
  invoiceNumber: string; // Format: S/YYYY/XXXX (e.g., S/2025/0001)
  date: string;
  customerId: string;
  customerName: string;
  secondaryCustomerId?: string;
  secondaryCustomerName?: string;
  primaryCoveragePercent?: number;
  secondaryCoveragePercent?: number;
  primaryCoverageAmount?: number;
  secondaryCoverageAmount?: number;
  salesRepId?: string;
  type?: 'sale' | 'return';
  items: SalesInvoiceItem[];
  subTotal: number;
  grandTotal: number;
  discountAmount?: number;
  campaignDiscountAmount?: number;
  amountPaid: number;
  amountDue: number;
  realEstateProjectId?: string;
  realEstateProjectName?: string;
  realEstateUnitId?: string;
  realEstateUnitName?: string;
  realEstateContractNumber?: string;
  realEstateContractDate?: string;
  realEstateHandoverDate?: string;
  realEstateContractValue?: number;
  realEstateDownPayment?: number;
  realEstateDeferredAmount?: number;
  realEstateInstallmentMode?: 'existing' | 'auto';
  realEstateInstallmentCount?: number;
  realEstateFirstDueDate?: string;
  realEstateInstallmentInterval?: 'monthly' | 'quarterly';
  paymentMethod?: 'cash' | 'check' | 'credit'; // طريقة الدفع
  checkDetails?: {
    checkNumber: string;
    bankId: string;
    bankName: string;
    checkDate: string;
    amount: number;
    currency?: string;
    status?: 'pending' | 'cleared' | 'rejected' | 'returned';
    reference?: string;
  };
  status: 'active' | 'cancelled'; // active or cancelled
  createdBy: string; // User who created the invoice
  createdAt: string; // ISO date string
  lockedBy?: string; // User currently editing the invoice
  lockedAt?: string; // ISO date string when lock was acquired
  cancelledAt?: string; // ISO date string when invoice was cancelled
  cancelledBy?: string; // User who cancelled the invoice
  cancelledReason?: string; // Reason for cancellation
  documentType?: 'shipment' | 'tax_invoice'; // Delivery note (inventory only) vs full tax invoice
};

// Accounting Types
export type AccountNature = 'debit' | 'credit';
export type AccountType = 'header' | 'account';

export type ChartOfAccount = {
  id: string;
  code: string;
  nameAr: string;
  nameEn: string;
  type: AccountType;
  parentId: string | null;
  nature?: AccountNature; // Only for accounts, not headers
  inactive?: boolean;
};

export type JournalEntryLine = {
  accountId: string;
  accountCode: string;
  accountName: string;
  debit: number;
  credit: number;
  description?: string;
  /** The original transaction currency (e.g. USD) if different from base currency */
  currencyCode?: string;
  /** Debit amount in the original transaction currency */
  originalDebit?: number;
  /** Credit amount in the original transaction currency */
  originalCredit?: number;
};

export type JournalEntry = {
  id: string;
  date: string; // ISO date string
  description: string;
  status?: 'draft' | 'posted' | 'reversed'; // draft = GRNI/preliminary, posted = final
  referenceType: 'sales_invoice' | 'payment' | 'supplier_payment' | 'expense' | 'production' | 'salary' | 'advance' | 'purchase_order' | 'purchase_return' | 'purchase_return_cancel' | 'manual';
  referenceId: string; // ID of the related document
  invoiceId?: string;
  shipmentId?: string;
  shipmentType?: ShipmentType;
  lines: JournalEntryLine[];
  createdBy: string;
  createdAt: string;
  /** Original transaction currency code if the document was created in a foreign currency */
  currencyCode?: string;
  /** Exchange rate used: 1 unit of currencyCode = fxRate units of base currency */
  fxRate?: number;
};

// Purchases Types
export type Supplier = {
  id: string;
  name: string;
  supplierNumber: string;
  balance: number; // Positive balance means we owe them money
  accountId?: string; // Linked account in chart of accounts
  accountCode?: string; // Cached code for quick use
  inactive?: boolean; // Mark supplier/account as inactive instead of delete when locked
  phone?: string;
  address?: string;
  paymentTerms?: number; // Payment terms in days
  taxNumber?: string;
};

export type PurchaseRealEstateLinkMode = 'none' | 'order' | 'line-items';
export type PurchaseRealEstateScope = 'project' | 'floor' | 'part';

export type PurchaseOrderItem = {
  materialId: string;
  name: string;
  quantity: number;
  unitPrice: number;
  total: number;
  lineDiscountPercent?: number;
  lineDiscountAmount?: number;
  lineDiscount?: number;
  bonus?: number;
  warehouseId?: string;
  taxRate?: number; // Applied tax rate for this line (0-100)
  taxAmount?: number; // Calculated tax amount for this line
  shelfId?: string;
  realEstateProjectId?: string;
  realEstateProjectName?: string;
  realEstateScope?: PurchaseRealEstateScope;
  realEstateFloorLabel?: string;
  realEstatePartLabel?: string;
  realEstateAllocationMethod?: RealEstateAllocationMethod;
};

export type PurchaseOrderDocument = {
  id: string;
  name: string;
  filePath: string;
  mimeType?: string;
  size?: number;
  uploadedAt: string;
  uploadedBy?: string;
};

export type PurchaseOrderPaymentMethod = {
  id: string;
  method: 'cash' | 'check' | 'bank_transfer' | 'credit';
  amount: number;
  currencyCode?: string;
  checkSource?: 'issued' | 'incoming';
  incomingCheckIds?: string[];
  checkNumber?: string;
  checkDate?: string;
  bankId?: string;
  bankName?: string;
  reference?: string;
};

export type PurchaseOrderLogEntry = {
  id: string;
  at: string;
  action: 'created' | 'updated' | 'posting-status' | 'notes' | 'transfer-doc-cancelled';
  message: string;
  by?: string;
};

export type PurchaseOrder = {
  id: string;
  orderNumber: string; // Format: P/YYYY/XXXX (e.g., P/2026/0001)
  date: string;
  currencyCode?: string; // Currency used for this PO
  baseCurrencyCode?: string; // System base currency at creation time
  exchangeRate?: number; // Base currency per 1 unit of currencyCode
  rateDate?: string; // Date the rate was captured for historical purposes
  rateSource?: string; // Source/provider of the rate
  isAutoRate?: boolean; // Whether the rate was auto-fetched
  grandTotalBase?: number; // Converted grand total in base currency at capture time
  amountPaidBase?: number; // Converted amount paid in base currency
  amountDueBase?: number; // Converted amount due in base currency
  supplierInvoiceNumber?: string;
  supplierInvoiceDate?: string;
  warehouseId?: string;
  realEstateLinkMode?: PurchaseRealEstateLinkMode;
  realEstateProjectId?: string;
  realEstateProjectName?: string;
  realEstateScope?: PurchaseRealEstateScope;
  realEstateFloorLabel?: string;
  realEstatePartLabel?: string;
  realEstateAllocationMethod?: RealEstateAllocationMethod;
  supplierId: string;
  supplierName: string;
  notes?: string;
  activityLog?: PurchaseOrderLogEntry[];
  documents?: PurchaseOrderDocument[];
  items: PurchaseOrderItem[];
  subTotal: number;
  invoiceDiscountPercent?: number;
  invoiceDiscountAmount?: number;
  lineDiscountTotal?: number;
  totalDiscount?: number;
  taxMethod?: 'tax-inclusive' | 'invoice-level' | 'line-level' | 'tax-exempt'; // Tax calculation method (default from settings)
  taxAmount?: number; // Total tax amount (for invoice-level) or sum of line taxes
  grandTotal: number;
  amountPaid: number;
  amountDue: number;
  paymentMethods?: PurchaseOrderPaymentMethod[];
  documentType?: 'shipment' | 'tax_invoice'; // 'tax_invoice' is the default (backward compat)
  linkedShipmentIds?: string[]; // On tax_invoice: IDs of linked shipment receipts
  taxInvoiceId?: string; // On shipment: ID of the tax invoice that consumed it
  postingStatus?: 'draft' | 'saved' | 'posted';
  purchaseTransferCreationMode?: 'direct_internal_transfer' | 'work_task' | 'none';
  status: 'active' | 'cancelled' | 'received';
  lockedById?: string;
  lockedByName?: string;
  lockedAt?: string;
  createdBy: string;
  createdAt: string;
  receivedAt?: string; // ISO date string when goods were received
  receivedBy?: string; // User who received the goods
  cancelledAt?: string; // ISO date string when order was cancelled
  cancelledBy?: string; // User who cancelled the order
  cancelledReason?: string; // Reason for cancellation
};

export type PurchaseReturnItem = {
  id: string;
  purchaseOrderId: string;
  materialId: string;
  quantity: number;
  warehouseId: string;
  shelfId: string;
  costPerUnitOriginal: number;
  currencyCode: string;
  baseCurrencyCode: string;
  fxRateInvoice: number;
  amount: number; // Currency amount (invoice currency)
  amountBase: number; // Converted using fxRateInvoice
};

export type PurchaseReturn = {
  id: string;
  returnNumber: string;
  purchaseOrderId: string;
  supplierId: string;
  settlementMode?: 'physical' | 'financial_only';
  status: 'draft' | 'approved' | 'posted' | 'locked' | 'cancelled';
  currencyCode: string;
  baseCurrencyCode: string;
  fxRateInvoice: number;
  rateDate?: string;
  totalAmount: number;
  totalAmountBase: number;
  reasonCode?: 'normal' | 'employee_error' | 'natural_loss';
  journalEntryId?: string;
  shipmentId?: string;
  createdBy: string;
  createdAt: string;
  items: PurchaseReturnItem[];
};
// Bank Types
export type Bank = {
  id: string;
  code: string; // Bank code/identifier (legacy)
  name: string; // Display name
  nameEn: string; // English name (legacy)
  accountId?: string; // Linked account id in chart of accounts
  accountCode?: string; // Linked account code in chart of accounts
  accountNumber?: string; // Account number at the bank
  bankNumber?: string; // Internal bank number/code
  fullName?: string; // Full bank name
  branch?: string; // Bank branch
  iban?: string; // Bank account IBAN
  swiftCode?: string; // SWIFT/BIC code
  contactName?: string; // Bank contact person
  contactPhone?: string; // Bank contact phone
  notes?: string; // Internal notes
  isActive?: boolean; // Active/archived status
  currencyCode?: string; // Default bank currency
  createdAt?: string;
  createdBy?: string;
};

// General/Public Banks (for customer checks, incoming payment references)
export type GeneralBank = {
  id: string;
  code: string; // Bank code/routing number (SWIFT-like or local routing code)
  name: string; // Bank name in Arabic
  nameEn: string; // Bank name in English
  accountId?: string; // Optional linked account id in chart of accounts
  accountCode?: string; // Optional linked account code in chart of accounts
  swiftCode?: string; // ISO 9362 SWIFT/BIC code (11 or 8 characters)
  branchCode?: string; // Branch code/number (if applicable)
  branch?: string; // Branch name
  country?: string; // Country code (ISO 3166-1 alpha-2, e.g., 'JO', 'US', 'AE')
  city?: string; // City name
  address?: string; // Physical address
  phone?: string; // Contact phone
  email?: string; // Contact email
  ibanPattern?: string; // IBAN pattern (e.g., 'JO94CBJO0010000000000131000302')
  isActive?: boolean; // Whether bank is active in system
  notes?: string; // Additional notes
  createdAt?: string;
  createdBy?: string;
  updatedAt?: string;
};

// Currency Types
export type Currency = {
  id: string;
  currencyNumber?: string;
  code: string; // e.g., 'USD', 'JOD', 'EUR'
  name: string; // Arabic name
  nameEn: string; // English name
  exchangeRate: number; // Exchange rate relative to base currency (JOD)
  isDefault: boolean; // Whether this is the default system currency
  symbol: string; // Currency symbol
  source?: string; // Exchange rate source (URL or provider name)
  lastUpdatedAt?: string;
  createdAt?: string;
  createdBy?: string;
};

export type DailyExchangeRate = {
  id: string;
  baseCurrency: string; // Base currency code
  currency: string; // Target currency code
  rate: number; // base per 1 target
  date: string; // ISO date string (yyyy-MM-dd)
  source?: string;
  isAuto?: boolean;
  createdAt: string;
};

// Check Types
export type CheckStatus = 'pending' | 'cleared' | 'rejected' | 'returned';
export type EndorsementStatus = 'none' | 'transferred-to-collection' | 'endorsed-to-party';
export type EndorsementType = 'customer' | 'supplier';
export type ReservationStatus = 'available' | 'reserved' | 'endorsed';

export type CheckReservationEvent = {
  id: string;
  checkId: string;
  checkNumber: string;
  action: 'reserved' | 'released' | 'endorsed' | 'reverse_endorsed';
  purchaseOrderId?: string;
  purchaseOrderNumber?: string;
  supplierId?: string;
  supplierName?: string;
  amount: number;
  currency: string;
  reason?: string;
  createdAt: string;
  createdBy: string;
};

export type IncomingCheck = {
  id: string;
  checkNumber: string;
  bankId: string; // Reference to bank
  bankName: string;
  checkDate: string; // ISO date
  amount: number;
  currency: string; // Currency code (USD, JOD, etc.)
  convertedAmount?: number; // Amount converted to default currency
  exchangeRate?: number; // Exchange rate used
  customerId: string;
  customerName: string;
  reference?: string; // Payment voucher reference
  status: CheckStatus;
  clearedDate?: string; // ISO date when check cleared
  rejectedReason?: string; // Reason for rejection
  returnedDate?: string; // ISO date when check was returned
  
  // Reservation state (3-state model: available | reserved | endorsed)
  reservationStatus?: ReservationStatus;
  reservedAt?: string; // ISO date when reserved in draft PO
  reservedByPurchaseOrderId?: string; // PO ID that reserved this check
  
  // Endorsement fields (permanent commitment)
  endorsementStatus?: EndorsementStatus; // 'none', 'transferred-to-collection', 'endorsed-to-party'
  endorsedToId?: string; // Party ID (customer or supplier)
  endorsedToName?: string; // Party name
  endorsedToType?: EndorsementType; // 'customer' or 'supplier'
  endorsedAt?: string; // ISO date when check was endorsed
  endorsementReference?: string; // PO number or reference for audit
  endorsementType?: string; // 'payment' | 'transfer' | etc
  
  notes?: string;
  createdAt: string;
  createdBy: string;
  updatedAt: string;
};

export type CheckReturnEvent = {
  id: string;
  checkId: string;
  checkNumber: string;
  customerId: string;
  customerName: string;
  supplierId: string;
  supplierName: string;
  reason: string;
  bankFeeAmount: number;
  chargeFeeToCustomer: boolean;
  amountBase: number;
  currency: string;
  amountOriginal: number;
  journalEntryId: string;
  notes?: string;
  createdAt: string;
  createdBy: string;
};

export type IssuedCheck = {
  id: string;
  checkNumber: string;
  bankId: string; // Reference to bank
  bankName: string;
  checkDate: string; // ISO date
  amount: number;
  currency: string; // Currency code
  convertedAmount?: number; // Amount converted to default currency
  exchangeRate?: number; // Exchange rate used
  supplierId: string;
  supplierName: string;
  reference?: string; // Payment voucher reference
  status: CheckStatus;
  clearedDate?: string;
  rejectedReason?: string;
  returnedDate?: string;
  notes?: string;
  createdAt: string;
  createdBy: string;
  updatedAt: string;
};

// Purchase Credit Note Types
export type PurchaseCreditNoteItem = {
  id: string;
  creditNoteId: string;
  materialId: string;
  name: string;
  quantity: number; // Quantity of returned goods
  unitPrice: number;
  lineDiscountPercent?: number;
  lineDiscountAmount?: number;
  lineDiscount?: number;
  taxRate?: number;
  taxAmount?: number;
  total: number; // Line total amount
  warehouseId?: string;
  shelfId?: string;
};

export type PurchaseCreditNote = {
  id: string;
  creditNoteNumber: string; // Format: CN/YYYY/XXXX (e.g., CN/2026/0001)
  date: string; // ISO date
  creditScope?: 'items' | 'invoice-total' | 'supplier-total';
  invoiceId?: string; // Linked Purchase Order ID (optional for supplier-level notes)
  invoiceNumber?: string; // Supplier's original invoice number
  supplierId: string;
  supplierName: string;
  warehouseId?: string;
  currencyCode?: string;
  baseCurrencyCode?: string;
  exchangeRate?: number;
  rateDate?: string;
  rateSource?: string;
  isAutoRate?: boolean;
  items: PurchaseCreditNoteItem[];
  subTotal: number;
  totalDiscount?: number;
  taxAmount?: number;
  grandTotal: number;
  grandTotalBase?: number; // In base currency
  reason: 'return' | 'price-adjustment' | 'damage' | 'invoice-error' | 'other';
  notes?: string;
  status: 'draft' | 'posted' | 'cancelled';
  journalEntryId?: string;
  journalEntryIdForImpactOnBalance?: string;
  postingStatus?: 'draft' | 'saved' | 'posted';
  createdBy: string;
  createdAt: string;
  cancelledAt?: string;
  cancelledBy?: string;
  cancelledReason?: string;
};

// ============================================================================
// BANK RECONCILIATION TYPES
// ============================================================================

export type BankReconciliationPeriodStatus = 'draft' | 'in-progress' | 'completed' | 'locked';

export type BankReconciliationPeriod = {
  id: string;
  bankAccountId: string;
  periodStartDate: string; // YYYY-MM-DD
  periodEndDate: string; // YYYY-MM-DD
  statementStartBalance?: number;
  statementEndBalance: number;
  ledgerStartBalance?: number;
  ledgerEndBalance?: number;
  status: BankReconciliationPeriodStatus;
  lockedAt?: string;
  lockedBy?: string;
  completedAt?: string;
  completedBy?: string;
  reconciliationDifference?: number;
  approvedBy?: string;
  approvedAt?: string;
  notes?: string;
  createdAt: string;
  createdBy: string;
  updatedAt: string;
};

export type BankTransactionDirection = 'inward' | 'outward' | 'debit' | 'credit';
export type BankTransactionType = 'check' | 'transfer' | 'fee' | 'interest' | 'charge' | 'other';

export type BankTransaction = {
  id: string;
  reconciliationPeriodId: string;
  bankAccountId: string;
  transactionDate: string; // YYYY-MM-DD
  amount: number;
  direction: BankTransactionDirection;
  description?: string;
  bankReference?: string;
  type?: BankTransactionType;
  currencyCode?: string;
  createdAt: string;
  updatedAt: string;
};

export type LedgerTransactionDirection = 'inward' | 'outward' | 'debit' | 'credit';

export type LedgerTransaction = {
  id: string;
  bankAccountId: string;
  journalEntryId: string;
  journalEntryLineIdx: number;
  transactionDate: string; // YYYY-MM-DD
  amount: number;
  direction: LedgerTransactionDirection;
  description?: string;
  referenceType?: string;
  referenceId?: string;
  postingStatus: 'draft' | 'posted';
  reconciliationStatus: 'unreconciled' | 'reconciled' | 'partial' | 'disputed';
  reconciliationPeriodId?: string;
  lastReconciliationDate?: string;
  currencyCode?: string;
  fxRate: number;
  createdAt: string;
  updatedAt: string;
};

export type ReconciliationMatchType = 'auto' | 'manual' | 'partial' | 'multi-line';
export type ReconciliationMatchStatus = 'matched' | 'unmatched' | 'disputed' | 'pending';

export type ReconciliationMatch = {
  id: string;
  reconciliationPeriodId: string;
  bankTransactionId: string;
  ledgerTransactionIds: string[];
  matchType: ReconciliationMatchType;
  matchConfidence: number; // 0-100
  matchDate: string;
  matchedBy: string;
  notes?: string;
  status: ReconciliationMatchStatus;
  createdAt: string;
  updatedAt: string;
};

export type BankDifferenceType =
  | 'unmatched_bank_transaction'
  | 'unmatched_ledger_transaction'
  | 'amount_mismatch'
  | 'date_variance'
  | 'outstanding_check'
  | 'deposit_in_transit'
  | 'bank_fee'
  | 'forex_difference'
  | 'other';

export type BankDifferenceResolutionType = 'pending' | 'identified' | 'adjusted' | 'write_off' | 'reversed';

export type BankReconciliationDifference = {
  id: string;
  reconciliationPeriodId: string;
  type: BankDifferenceType;
  amount: number;
  description?: string;
  bankTransactionId?: string;
  ledgerTransactionId?: string;
  resolutionType?: BankDifferenceResolutionType;
  resolutionDate?: string;
  resolvedBy?: string;
  adjustmentEntryId?: string;
  notes?: string;
  createdAt: string;
  updatedAt: string;
};

export type RecurringExpenseFrequency = 'monthly' | 'yearly';
export type RecurringExpenseTemplateStatus = 'active' | 'paused' | 'closed';
export type ExpenseApprovalPolicy = 'none' | 'single_step' | 'two_step';

export type RecurringExpenseTemplate = {
  id: string;
  name: string;
  expenseItemId?: string;
  expenseAccountCode: string;
  payableAccountCode: string;
  defaultAmount: number;
  currencyCode?: string;
  frequency: RecurringExpenseFrequency;
  intervalCount: number;
  startDate: string;
  nextRunDate: string;
  dayOfMonth?: number;
  monthOfYear?: number;
  endDate?: string;
  approvalPolicy: ExpenseApprovalPolicy;
  autoSubmitForApproval: boolean;
  status: RecurringExpenseTemplateStatus;
  notes?: string;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
};

export type ExpensePaymentMethod = 'cash' | 'bank' | 'credit' | 'mixed';
export type ExpenseDocumentStatus =
  | 'draft'
  | 'pending_approval'
  | 'approved'
  | 'rejected'
  | 'posted'
  | 'partially_paid'
  | 'paid'
  | 'cancelled';

export type ExpenseDocument = {
  id: string;
  templateId?: string;
  expenseItemId?: string;
  expenseAccountCode: string;
  payableAccountCode: string;
  periodYear: number;
  periodMonth: number;
  dueDate: string;
  description: string;
  amount: number;
  currencyCode?: string;
  paymentMethod: ExpensePaymentMethod;
  status: ExpenseDocumentStatus;
  paidAmount: number;
  submittedBy?: string;
  submittedAt?: string;
  approvedBy?: string;
  approvedAt?: string;
  rejectedBy?: string;
  rejectedAt?: string;
  rejectedReason?: string;
  postedBy?: string;
  postedAt?: string;
  journalEntryId?: string;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
};

export type ExpenseDocumentHistoryAction =
  | 'created'
  | 'submitted'
  | 'approved'
  | 'rejected'
  | 'posted'
  | 'payment'
  | 'status_changed';

export type ExpenseDocumentHistoryEntry = {
  id: string;
  documentId: string;
  fromStatus?: ExpenseDocumentStatus | null;
  toStatus: ExpenseDocumentStatus;
  action: ExpenseDocumentHistoryAction;
  actorId?: string;
  actorName?: string;
  note?: string;
  details?: Record<string, unknown>;
  createdAt: string;
};

export type ExpensePayment = {
  id: string;
  documentId: string;
  paymentDate: string;
  amount: number;
  paymentMethod: ExpensePaymentMethod;
  accountCode: string;
  referenceNumber?: string;
  notes?: string;
  createdBy: string;
  createdAt: string;
  journalEntryId?: string;
};

// ============================================================================
// ADVANCED RECURRING EXPENSES TYPES (PHASE 1)
// ============================================================================

// Contract Types
export type RenewalTerms = 'auto_renew' | 'manual_renew' | 'term_end';
export type EscalationPolicy = 'none' | 'fixed_percent' | 'indexed';
export type AllocationStrategy = 'none' | 'branch' | 'cost_center' | 'project' | 'department';
export type ContractStatus = 'active' | 'suspended' | 'expired' | 'terminated' | 'under_review';

export type RecurringExpenseContract = {
  id: string;
  templateId?: string;
  name: string;
  vendorId?: string;
  contractDate: string;
  startDate: string;
  endDate?: string;
  renewalTerms: RenewalTerms;
  escalationPolicy: EscalationPolicy;
  escalationValue?: number;
  allocationStrategy: AllocationStrategy;
  status: ContractStatus;
  notes?: string;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
};

// Schedule Types
export type RecurringScheduleStatus = 'active' | 'paused' | 'archived';

export type RecurringSchedule = {
  id: string;
  templateId: string;
  contractId?: string;
  currentPeriodStart?: string;
  currentPeriodEnd?: string;
  nextScheduledDate: string;
  lastGeneratedDate?: string;
  missedGenerations: number;
  lastRetryAt?: string;
  retryCount: number;
  status: RecurringScheduleStatus;
  createdAt: string;
  updatedAt: string;
};

// Obligation Types
export type ExpenseBasis = 'cash' | 'accrual' | 'prepaid';
export type ObligationStatus = 'pending' | 'recognized' | 'settled' | 'partially_settled' | 'reversed';

export type ExpenseObligation = {
  id: string;
  documentId: string;
  contractId?: string;
  templateId?: string;
  periodStart: string;
  periodEnd: string;
  grossAmount: number;
  currencyCode?: string;
  basis: ExpenseBasis;
  recognitionDate?: string;
  settlementDate?: string;
  status: ObligationStatus;
  reversalObligationId?: string;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
};

// Posting Types
export type PostingType = 'regular' | 'reversal' | 'adjustment';
export type PostingStatus = 'pending' | 'posted' | 'reversed' | 'cancelled';

export type ExpensePosting = {
  id: string;
  obligationId: string;
  documentId?: string;
  journalEntryId?: string;
  debitAccount: string;
  creditAccount: string;
  amount: number;
  postingDate: string;
  postingType: PostingType;
  status: PostingStatus;
  reversalPostingId?: string;
  reversalReason?: string;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
};

// Allocation Types
export type AllocationType = 'branch' | 'cost_center' | 'project' | 'department' | 'employee';

export type ExpenseAllocation = {
  id: string;
  obligationId: string;
  allocationType: AllocationType;
  allocationTargetId: string;
  allocationTargetName?: string;
  percentage: number;
  amount: number;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
};

// Prepaid Amortization Types
export type PrepaidAmortizationSchedule = {
  id: string;
  obligationId: string;
  periodNumber: number;
  periodStart: string;
  periodEnd: string;
  amount: number;
  status: 'pending' | 'posted' | 'reversed';
  createdAt: string;
  updatedAt: string;
};

// Escalation Rule Types
export type EscalationType = 'fixed_percent' | 'indexed' | 'tiered';
export type IndexSource = 'cpi' | 'custom' | 'manual';

export type ExpenseEscalationRule = {
  id: string;
  contractId: string;
  escalationType: EscalationType;
  escalationValue?: number;
  indexSource?: IndexSource;
  effectiveDate: string;
  endDate?: string;
  status: 'active' | 'archived';
  createdAt: string;
  updatedAt: string;
};

// Payment Schedule Types
export type PaymentScheduleStatus = 'pending' | 'partially_paid' | 'paid' | 'overdue' | 'cancelled';

export type ExpensePaymentSchedule = {
  id: string;
  obligationId: string;
  dueDate: string;
  amount: number;
  paymentMethod?: string;
  status: PaymentScheduleStatus;
  paidAmount: number;
  createdAt: string;
  updatedAt: string;
};

// Audit Log Types
export type ExpenseAuditEntityType = 'template' | 'contract' | 'document' | 'obligation' | 'posting' | 'payment';

export type ExpenseAuditLog = {
  id: string;
  entityType: ExpenseAuditEntityType;
  entityId: string;
  action: string;
  oldValues?: Record<string, unknown>;
  newValues?: Record<string, unknown>;
  actorId: string;
  actorName?: string;
  reason?: string;
  createdAt: string;
};

// ============================================
// Phase 2: Background Scheduler Types
// ============================================

export type BackgroundJobStatus = 'pending' | 'running' | 'success' | 'failed' | 'retry';
export type ScheduleJobStatus = 'active' | 'paused' | 'completed' | 'cancelled';
export type BackgroundJobType = 'generate_document' | 'apply_escalation' | 'process_prepaid_amortization' | 'reconcile_bank';

export type RecurringScheduleJob = {
  id: string;
  templateId: string;
  contractId?: string;
  
  // Schedule information
  nextRunDate: string; // ISO date string
  status: ScheduleJobStatus;
  
  // Retry logic
  retryCount: number;
  maxRetries: number;
  lastError?: string;
  
  // Execution tracking
  lastRunDate?: string;
  totalRuns: number;
  
  // Holiday and weekend handling
  skipWeekends: boolean;
  skipHolidays: boolean;
  holidayShiftDays: number;
  
  // Auto-generation options
  autoCreateObligation: boolean;
  obligationBasis: ExpenseBasis;
  autoCreatePosting: boolean;
  
  // Audit trail
  createdBy: string;
  createdAt: string;
  updatedBy?: string;
  updatedAt: string;
  
  // Raw extensible field
  raw?: Record<string, unknown>;
};

export type BackgroundJobLog = {
  id: string;
  jobId: string;
  
  // Job execution info
  jobType: BackgroundJobType;
  startedAt: string;
  completedAt?: string;
  status: BackgroundJobStatus;
  
  // Results
  generatedDocuments: number;
  failedDocuments: number;
  
  // Error handling
  errorMessage?: string;
  errorStack?: string;
  
  // Metadata
  createdBy?: string; // System or user ID if manual
  raw?: Record<string, unknown>;
};

export type RecurringGenerationDuplicate = {
  id: string;
  jobId: string;
  templateId: string;
  periodStart: string; // ISO date
  periodEnd: string;   // ISO date
  
  generatedAt: string;
  attempts: number;
  generatedDocumentId?: string;
};

export type EscalationExecution = {
  id: string;
  templateId: string;
  contractId?: string;
  
  escalationType: 'fixed_percent' | 'indexed' | 'tiered';
  escalationRuleId?: string;
  
  executionDate: string; // ISO date
  newAmount: number;
  previousAmount?: number;
  increasePercent?: number;
  
  status: 'completed' | 'pending' | 'failed';
  errorMessage?: string;
  
  createdBy: string;
  createdAt: string;
  raw?: Record<string, unknown>;
};

export type SchedulerStatus = {
  id: string;
  
  // Overall state
  isRunning: boolean;
  isHealthy: boolean;
  
  // Execution tracking
  lastRunAt?: string;
  lastCheckAt?: string;
  nextCheckAt?: string;
  
  // Statistics
  totalJobs: number;
  activeJobs: number;
  completedJobs: number;
  failedJobs: number;
  
  // Health metrics
  averageJobDurationMs?: number;
  lastErrorMessage?: string;
  errorCount: number;
  
  // Configuration
  checkIntervalSeconds: number;
  enableAutoGeneration: boolean;
  enableEscalation: boolean;
  enableAmortization: boolean;
  
  updatedAt: string;
  raw?: Record<string, unknown>;
};

export type SchedulerGenerateAllRequest = {
  asOfDate?: string; // ISO date, defaults to today
  templateIds?: string[]; // Optional filter to specific templates
  contractIds?: string[]; // Optional filter to specific contracts
  forceGenerate?: boolean; // Force even if recently generated
};

export type SchedulerGenerateAllResponse = {
  success: boolean;
  jobsCreated: number;
  jobsEnqueued: number;
  failedJobs: number;
  generatedDocuments: number;
  errors?: string[];
  processingTimeMs: number;
};