export interface QboTokenRecord {
  id: number;
  realm_id: string;
  access_token: string;
  refresh_token: string;
  access_token_expires_at: Date;
  refresh_token_expires_at: Date;
  created_at: Date;
  updated_at: Date;
}

export interface QboTokenResponse {
  access_token: string;
  refresh_token: string;
  expires_in: number;
  x_refresh_token_expires_in: number;
  token_type: string;
}

export interface QboRef {
  value: string;
  name?: string;
}

export interface QboMetaData {
  CreateTime: string;
  LastUpdatedTime: string;
}

export interface QboLineItem {
  Id?: string;
  LineNum?: number;
  Description?: string;
  Amount: number;
  DetailType: string;
  [key: string]: any;
}

export interface QboLinkedTxn {
  TxnId: string;
  TxnType: string;
  TxnLineId?: string;
}

// Invoice
export interface QboInvoice {
  Id: string;
  SyncToken: string;
  DocNumber?: string;
  TxnDate?: string;
  DueDate?: string;
  CustomerRef?: QboRef;
  BillEmail?: { Address?: string };
  TotalAmt?: number;
  Balance?: number;
  EmailStatus?: string;
  PrintStatus?: string;
  CurrencyRef?: QboRef;
  Line?: QboLineItem[];
  LinkedTxn?: QboLinkedTxn[];
  MetaData?: QboMetaData;
}

// Payment
export interface QboPayment {
  Id: string;
  SyncToken: string;
  TxnDate?: string;
  CustomerRef?: QboRef;
  TotalAmt?: number;
  UnappliedAmt?: number;
  CurrencyRef?: QboRef;
  PaymentMethodRef?: QboRef;
  DepositToAccountRef?: QboRef;
  Line?: Array<{ Amount: number; LinkedTxn?: QboLinkedTxn[] }>;
  MetaData?: QboMetaData;
}

// Deposit
export interface QboDeposit {
  Id: string;
  SyncToken: string;
  TxnDate?: string;
  DepositToAccountRef?: QboRef;
  TotalAmt?: number;
  Line?: QboLineItem[];
  MetaData?: QboMetaData;
}

// Payload for creating a Payment via POST /v3/company/{realmId}/payment
// Only the fields we actually send — QBO accepts many more but we keep the
// surface area small and explicit.
export interface QboPaymentCreatePayload {
  CustomerRef: QboRef;                // { value: customer_ref_id }
  TotalAmt: number;
  TxnDate?: string;                   // YYYY-MM-DD
  DepositToAccountRef?: QboRef;       // { value: account id }
  PaymentRefNum?: string;             // check number (max 21 chars per QBO)
  PrivateNote?: string;
  Line?: Array<{
    Amount: number;
    LinkedTxn?: QboLinkedTxn[];       // one entry per invoice being paid
  }>;
}

// Payload for creating a Deposit via POST /v3/company/{realmId}/deposit
// Each Line links to a previously-created Payment so QBO groups them as a
// single bank deposit (matches the bank slip).
export interface QboDepositCreatePayload {
  TxnDate?: string;
  DepositToAccountRef: QboRef;        // required for deposit
  PrivateNote?: string;
  Line: Array<{
    Amount: number;
    DetailType: 'DepositLineDetail';
    LinkedTxn?: QboLinkedTxn[];       // [{ TxnId: payment_id, TxnType: 'Payment' }]
    DepositLineDetail?: Record<string, unknown>;
  }>;
}

// Purchase (expense/credit card)
export interface QboPurchase {
  Id: string;
  SyncToken: string;
  TxnDate?: string;
  DocNumber?: string;
  EntityRef?: QboRef & { type?: string };
  AccountRef?: QboRef;
  TotalAmt?: number;
  CurrencyRef?: QboRef;
  PrivateNote?: string;
  Line?: QboLineItem[];
  MetaData?: QboMetaData;
}

// Journal Entry
export interface QboJournalEntry {
  Id: string;
  SyncToken: string;
  TxnDate?: string;
  DocNumber?: string;
  TotalAmt?: number;
  CurrencyRef?: QboRef;
  PrivateNote?: string;
  Line?: QboLineItem[];
  MetaData?: QboMetaData;
}

// Report (P&L, Balance Sheet)
export interface QboReport {
  Header?: {
    ReportName?: string;
    StartPeriod?: string;
    EndPeriod?: string;
    Time?: string;
    Currency?: string;
    ReportBasis?: string;
    NoReportData?: string;
    [key: string]: any;
  };
  Columns?: any;
  Rows?: any;
}

export interface QboQueryResponse<T> {
  QueryResponse: {
    [key: string]: T[] | number | undefined;
    startPosition?: number;
    maxResults?: number;
    totalCount?: number;
  };
  time: string;
}

export interface QboSyncResult {
  syncId: string;
  realmId: string;
  status: 'completed' | 'failed';
  startedAt: Date;
  completedAt: Date;
  duration: number;
  entities: QboEntitySyncResult[];
  errors: string[];
}

export interface QboEntitySyncResult {
  entity: string;
  success: boolean;
  recordsUpserted: number;
  recordsDeleted?: number;
  duration: number;
  error?: string;
}
