// Branded types for IDs
export type CustomerId = string & { readonly __brand: 'CustomerId' };
export type VendorId = string & { readonly __brand: 'VendorId' };
export type EmployeeId = string & { readonly __brand: 'EmployeeId' };
export type InvoiceId = string & { readonly __brand: 'InvoiceId' };
export type PaymentId = string & { readonly __brand: 'PaymentId' };
export type BillId = string & { readonly __brand: 'BillId' };
export type EstimateId = string & { readonly __brand: 'EstimateId' };
export type ItemId = string & { readonly __brand: 'ItemId' };
export type AccountId = string & { readonly __brand: 'AccountId' };
export type TaxCodeId = string & { readonly __brand: 'TaxCodeId' };
export type ClassId = string & { readonly __brand: 'ClassId' };
export type DepartmentId = string & { readonly __brand: 'DepartmentId' };
export type TimeActivityId = string & { readonly __brand: 'TimeActivityId' };

// Base entity with SyncToken for optimistic locking
export interface QBOEntity {
  Id: string;
  SyncToken: string;
  MetaData: {
    CreateTime: string;
    LastUpdatedTime: string;
  };
}

// Reference types
export interface Ref {
  value: string;
  name?: string;
}

export interface CustomerRef extends Ref {
  value: CustomerId;
}

export interface VendorRef extends Ref {
  value: VendorId;
}

export interface EmployeeRef extends Ref {
  value: EmployeeId;
}

export interface ItemRef extends Ref {
  value: ItemId;
}

export interface AccountRef extends Ref {
  value: AccountId;
}

export interface ClassRef extends Ref {
  value: ClassId;
}

export interface DepartmentRef extends Ref {
  value: DepartmentId;
}

export interface TaxCodeRef extends Ref {
  value: TaxCodeId;
}

// Address
export interface PhysicalAddress {
  Line1?: string;
  Line2?: string;
  Line3?: string;
  Line4?: string;
  Line5?: string;
  City?: string;
  Country?: string;
  CountrySubDivisionCode?: string;
  PostalCode?: string;
  Lat?: string;
  Long?: string;
}

// Customer
export interface Customer extends QBOEntity {
  Id: CustomerId;
  DisplayName: string;
  Title?: string;
  GivenName?: string;
  MiddleName?: string;
  FamilyName?: string;
  Suffix?: string;
  FullyQualifiedName?: string;
  CompanyName?: string;
  PrintOnCheckName?: string;
  Active?: boolean;
  PrimaryPhone?: { FreeFormNumber: string };
  AlternatePhone?: { FreeFormNumber: string };
  Mobile?: { FreeFormNumber: string };
  Fax?: { FreeFormNumber: string };
  PrimaryEmailAddr?: { Address: string };
  WebAddr?: { URI: string };
  BillAddr?: PhysicalAddress;
  ShipAddr?: PhysicalAddress;
  Notes?: string;
  Taxable?: boolean;
  Balance?: number;
  BalanceWithJobs?: number;
  CurrencyRef?: Ref;
  PreferredDeliveryMethod?: string;
  ResaleNum?: string;
}

// Vendor
export interface Vendor extends QBOEntity {
  Id: VendorId;
  DisplayName: string;
  Title?: string;
  GivenName?: string;
  MiddleName?: string;
  FamilyName?: string;
  Suffix?: string;
  CompanyName?: string;
  PrintOnCheckName?: string;
  Active?: boolean;
  PrimaryPhone?: { FreeFormNumber: string };
  AlternatePhone?: { FreeFormNumber: string };
  Mobile?: { FreeFormNumber: string };
  Fax?: { FreeFormNumber: string };
  PrimaryEmailAddr?: { Address: string };
  WebAddr?: { URI: string };
  BillAddr?: PhysicalAddress;
  Balance?: number;
  AcctNum?: string;
  Vendor1099?: boolean;
  CurrencyRef?: Ref;
}

// Employee
export interface Employee extends QBOEntity {
  Id: EmployeeId;
  DisplayName: string;
  Title?: string;
  GivenName?: string;
  MiddleName?: string;
  FamilyName?: string;
  Suffix?: string;
  PrintOnCheckName?: string;
  Active?: boolean;
  PrimaryPhone?: { FreeFormNumber: string };
  Mobile?: { FreeFormNumber: string };
  PrimaryEmailAddr?: { Address: string };
  PrimaryAddr?: PhysicalAddress;
  EmployeeNumber?: string;
  SSN?: string;
  HiredDate?: string;
  ReleasedDate?: string;
  BillableTime?: boolean;
}

// Item types
export type ItemType = 'Inventory' | 'NonInventory' | 'Service' | 'Category' | 'Group';

export interface Item extends QBOEntity {
  Id: ItemId;
  Name: string;
  Type: ItemType;
  Active?: boolean;
  FullyQualifiedName?: string;
  Taxable?: boolean;
  UnitPrice?: number;
  Description?: string;
  PurchaseDesc?: string;
  PurchaseCost?: number;
  QtyOnHand?: number;
  IncomeAccountRef?: AccountRef;
  ExpenseAccountRef?: AccountRef;
  AssetAccountRef?: AccountRef;
  InvStartDate?: string;
  TrackQtyOnHand?: boolean;
}

// Invoice Line
export interface InvoiceLine {
  Id?: string;
  LineNum?: number;
  Description?: string;
  Amount: number;
  DetailType: 'SalesItemLineDetail' | 'SubTotalLineDetail' | 'DiscountLineDetail' | 'DescriptionOnly';
  SalesItemLineDetail?: {
    ItemRef?: ItemRef;
    Qty?: number;
    UnitPrice?: number;
    TaxCodeRef?: TaxCodeRef;
    ClassRef?: ClassRef;
    ServiceDate?: string;
  };
  DiscountLineDetail?: {
    PercentBased?: boolean;
    DiscountPercent?: number;
    DiscountAccountRef?: AccountRef;
  };
}

// Invoice
export type InvoiceStatus = 'Draft' | 'Pending' | 'Sent' | 'Paid' | 'Overdue' | 'Void';

export interface Invoice extends QBOEntity {
  Id: InvoiceId;
  DocNumber?: string;
  TxnDate: string;
  DueDate?: string;
  CustomerRef: CustomerRef;
  Line: InvoiceLine[];
  TotalAmt: number;
  Balance: number;
  BillAddr?: PhysicalAddress;
  ShipAddr?: PhysicalAddress;
  EmailStatus?: 'NotSet' | 'NeedToSend' | 'EmailSent';
  PrintStatus?: 'NotSet' | 'NeedToPrint' | 'PrintComplete';
  TxnStatus?: InvoiceStatus;
  PrivateNote?: string;
  CustomerMemo?: { value: string };
  BillEmail?: { Address: string };
  AllowOnlineCreditCardPayment?: boolean;
  AllowOnlineACHPayment?: boolean;
  CurrencyRef?: Ref;
  ExchangeRate?: number;
  Deposit?: number;
  DepositToAccountRef?: AccountRef;
  ClassRef?: ClassRef;
  DepartmentRef?: DepartmentRef;
  SalesTermRef?: Ref;
  ShipMethodRef?: Ref;
  ShipDate?: string;
  TrackingNum?: string;
}

// Payment
export interface PaymentLine {
  Amount: number;
  LinkedTxn?: Array<{
    TxnId: string;
    TxnType: string;
  }>;
}

export interface Payment extends QBOEntity {
  Id: PaymentId;
  TxnDate: string;
  CustomerRef: CustomerRef;
  TotalAmt: number;
  UnappliedAmt?: number;
  DepositToAccountRef?: AccountRef;
  Line?: PaymentLine[];
  PaymentMethodRef?: Ref;
  PaymentRefNum?: string;
  PrivateNote?: string;
  CurrencyRef?: Ref;
  ExchangeRate?: number;
}

// Credit Memo
export interface CreditMemo extends QBOEntity {
  Id: string;
  DocNumber?: string;
  TxnDate: string;
  CustomerRef: CustomerRef;
  Line: InvoiceLine[];
  TotalAmt: number;
  Balance: number;
  BillAddr?: PhysicalAddress;
  PrivateNote?: string;
  CustomerMemo?: { value: string };
  EmailStatus?: 'NotSet' | 'NeedToSend' | 'EmailSent';
  PrintStatus?: 'NotSet' | 'NeedToPrint' | 'PrintComplete';
}

// Bill
export interface BillLine {
  Id?: string;
  LineNum?: number;
  Description?: string;
  Amount: number;
  DetailType: 'AccountBasedExpenseLineDetail' | 'ItemBasedExpenseLineDetail';
  AccountBasedExpenseLineDetail?: {
    AccountRef: AccountRef;
    TaxCodeRef?: TaxCodeRef;
    ClassRef?: ClassRef;
    BillableStatus?: 'Billable' | 'NotBillable' | 'HasBeenBilled';
    CustomerRef?: CustomerRef;
  };
  ItemBasedExpenseLineDetail?: {
    ItemRef: ItemRef;
    Qty?: number;
    UnitPrice?: number;
    TaxCodeRef?: TaxCodeRef;
    ClassRef?: ClassRef;
    BillableStatus?: 'Billable' | 'NotBillable' | 'HasBeenBilled';
    CustomerRef?: CustomerRef;
  };
}

export interface Bill extends QBOEntity {
  Id: BillId;
  DocNumber?: string;
  TxnDate: string;
  DueDate?: string;
  VendorRef: VendorRef;
  Line: BillLine[];
  TotalAmt: number;
  Balance: number;
  APAccountRef?: AccountRef;
  PrivateNote?: string;
  CurrencyRef?: Ref;
  ExchangeRate?: number;
  SalesTermRef?: Ref;
}

// Bill Payment
export interface BillPayment extends QBOEntity {
  Id: string;
  TxnDate: string;
  VendorRef: VendorRef;
  TotalAmt: number;
  APAccountRef?: AccountRef;
  PayType: 'Check' | 'CreditCard';
  CheckPayment?: {
    BankAccountRef: AccountRef;
    PrintStatus?: 'NotSet' | 'NeedToPrint' | 'PrintComplete';
  };
  CreditCardPayment?: {
    CCAccountRef: AccountRef;
  };
  Line?: Array<{
    Amount: number;
    LinkedTxn?: Array<{
      TxnId: string;
      TxnType: string;
    }>;
  }>;
  PrivateNote?: string;
}

// Purchase
export interface Purchase extends QBOEntity {
  Id: string;
  DocNumber?: string;
  TxnDate: string;
  AccountRef?: AccountRef;
  PaymentType: 'Cash' | 'Check' | 'CreditCard';
  EntityRef?: VendorRef | CustomerRef | EmployeeRef;
  Line: BillLine[];
  TotalAmt: number;
  PrivateNote?: string;
  CurrencyRef?: Ref;
}

// Purchase Order
export interface PurchaseOrder extends QBOEntity {
  Id: string;
  DocNumber?: string;
  TxnDate: string;
  VendorRef: VendorRef;
  Line: Array<{
    Id?: string;
    LineNum?: number;
    Description?: string;
    Amount: number;
    DetailType: 'ItemBasedExpenseLineDetail';
    ItemBasedExpenseLineDetail: {
      ItemRef: ItemRef;
      Qty?: number;
      UnitPrice?: number;
      ClassRef?: ClassRef;
      CustomerRef?: CustomerRef;
    };
  }>;
  TotalAmt: number;
  POStatus?: 'Open' | 'Closed';
  POEmail?: { Address: string };
  ShipAddr?: PhysicalAddress;
  ShipMethodRef?: Ref;
  PrivateNote?: string;
  Memo?: string;
}

// Estimate
export interface Estimate extends QBOEntity {
  Id: EstimateId;
  DocNumber?: string;
  TxnDate: string;
  CustomerRef: CustomerRef;
  Line: InvoiceLine[];
  TotalAmt: number;
  BillAddr?: PhysicalAddress;
  ShipAddr?: PhysicalAddress;
  EmailStatus?: 'NotSet' | 'NeedToSend' | 'EmailSent';
  PrintStatus?: 'NotSet' | 'NeedToPrint' | 'PrintComplete';
  TxnStatus?: 'Accepted' | 'Closed' | 'Pending' | 'Rejected';
  ExpirationDate?: string;
  AcceptedBy?: string;
  AcceptedDate?: string;
  PrivateNote?: string;
  CustomerMemo?: { value: string };
}

// Sales Receipt
export interface SalesReceipt extends QBOEntity {
  Id: string;
  DocNumber?: string;
  TxnDate: string;
  CustomerRef: CustomerRef;
  Line: InvoiceLine[];
  TotalAmt: number;
  Balance: number;
  DepositToAccountRef?: AccountRef;
  PaymentMethodRef?: Ref;
  PaymentRefNum?: string;
  BillAddr?: PhysicalAddress;
  ShipAddr?: PhysicalAddress;
  EmailStatus?: 'NotSet' | 'NeedToSend' | 'EmailSent';
  PrintStatus?: 'NotSet' | 'NeedToPrint' | 'PrintComplete';
  PrivateNote?: string;
  CustomerMemo?: { value: string };
}

// Account
export type AccountType = 
  | 'Bank' | 'Other Current Asset' | 'Fixed Asset' | 'Other Asset'
  | 'Accounts Receivable' | 'Equity' | 'Expense' | 'Other Expense'
  | 'Cost of Goods Sold' | 'Accounts Payable' | 'Credit Card'
  | 'Long Term Liability' | 'Other Current Liability' | 'Income'
  | 'Other Income';

export type AccountSubType = string;

export interface Account extends QBOEntity {
  Id: AccountId;
  Name: string;
  FullyQualifiedName?: string;
  Active?: boolean;
  AccountType: AccountType;
  AccountSubType?: AccountSubType;
  AcctNum?: string;
  CurrentBalance?: number;
  CurrentBalanceWithSubAccounts?: number;
  CurrencyRef?: Ref;
  ParentRef?: AccountRef;
  Description?: string;
  SubAccount?: boolean;
}

// Journal Entry
export interface JournalEntryLine {
  Id?: string;
  LineNum?: number;
  Description?: string;
  Amount: number;
  DetailType: 'JournalEntryLineDetail';
  JournalEntryLineDetail: {
    PostingType: 'Debit' | 'Credit';
    AccountRef: AccountRef;
    Entity?: CustomerRef | VendorRef | EmployeeRef;
    ClassRef?: ClassRef;
    DepartmentRef?: DepartmentRef;
    TaxCodeRef?: TaxCodeRef;
    BillableStatus?: 'Billable' | 'NotBillable' | 'HasBeenBilled';
  };
}

export interface JournalEntry extends QBOEntity {
  Id: string;
  DocNumber?: string;
  TxnDate: string;
  Line: JournalEntryLine[];
  TotalAmt: number;
  Adjustment?: boolean;
  PrivateNote?: string;
  CurrencyRef?: Ref;
  ExchangeRate?: number;
}

// Deposit
export interface Deposit extends QBOEntity {
  Id: string;
  TxnDate: string;
  DepositToAccountRef: AccountRef;
  Line: Array<{
    Id?: string;
    LineNum?: number;
    Description?: string;
    Amount: number;
    DetailType: 'DepositLineDetail';
    DepositLineDetail: {
      Entity?: CustomerRef | VendorRef | EmployeeRef;
      AccountRef: AccountRef;
      ClassRef?: ClassRef;
      PaymentMethodRef?: Ref;
      CheckNum?: string;
    };
  }>;
  TotalAmt: number;
  PrivateNote?: string;
  CurrencyRef?: Ref;
}

// Transfer
export interface Transfer extends QBOEntity {
  Id: string;
  TxnDate: string;
  FromAccountRef: AccountRef;
  ToAccountRef: AccountRef;
  Amount: number;
  PrivateNote?: string;
}

// Tax Code
export interface TaxCode extends QBOEntity {
  Id: TaxCodeId;
  Name: string;
  Description?: string;
  Active?: boolean;
  Taxable?: boolean;
  TaxGroup?: boolean;
  SalesTaxRateList?: {
    TaxRateDetail: Array<{
      TaxRateRef: Ref;
      TaxTypeApplicable?: string;
      TaxOrder?: number;
    }>;
  };
  PurchaseTaxRateList?: {
    TaxRateDetail: Array<{
      TaxRateRef: Ref;
      TaxTypeApplicable?: string;
      TaxOrder?: number;
    }>;
  };
}

// Tax Rate
export interface TaxRate extends QBOEntity {
  Id: string;
  Name: string;
  Description?: string;
  Active?: boolean;
  RateValue?: number;
  AgencyRef?: Ref;
  SpecialTaxType?: string;
  DisplayType?: string;
}

// Tax Agency
export interface TaxAgency extends QBOEntity {
  Id: string;
  DisplayName: string;
  TaxTrackedOnPurchases?: boolean;
  TaxTrackedOnSales?: boolean;
  TaxTrackedOnSalesReceipts?: boolean;
}

// Time Activity
export interface TimeActivity extends QBOEntity {
  Id: TimeActivityId;
  TxnDate: string;
  EmployeeRef?: EmployeeRef;
  VendorRef?: VendorRef;
  CustomerRef?: CustomerRef;
  ItemRef?: ItemRef;
  ClassRef?: ClassRef;
  NameOf: 'Employee' | 'Vendor';
  Hours?: number;
  Minutes?: number;
  StartTime?: string;
  EndTime?: string;
  Description?: string;
  HourlyRate?: number;
  BillableStatus?: 'Billable' | 'NotBillable' | 'HasBeenBilled';
  Taxable?: boolean;
  BreakHours?: number;
  BreakMinutes?: number;
}

// Class
export interface Class extends QBOEntity {
  Id: ClassId;
  Name: string;
  FullyQualifiedName?: string;
  Active?: boolean;
  SubClass?: boolean;
  ParentRef?: ClassRef;
}

// Department
export interface Department extends QBOEntity {
  Id: DepartmentId;
  Name: string;
  FullyQualifiedName?: string;
  Active?: boolean;
  SubDepartment?: boolean;
  ParentRef?: DepartmentRef;
}

// Company Info
export interface CompanyInfo extends QBOEntity {
  Id: string;
  CompanyName: string;
  LegalName?: string;
  CompanyAddr?: PhysicalAddress;
  CustomerCommunicationAddr?: PhysicalAddress;
  LegalAddr?: PhysicalAddress;
  PrimaryPhone?: { FreeFormNumber: string };
  CompanyStartDate?: string;
  FiscalYearStartMonth?: string;
  Country?: string;
  Email?: { Address: string };
  WebAddr?: { URI: string };
  SupportedLanguages?: string;
  NameValue?: Array<{
    Name: string;
    Value: string;
  }>;
}

// Preferences
export interface Preferences extends QBOEntity {
  Id: string;
  AccountingInfoPrefs?: {
    FirstMonthOfFiscalYear?: string;
    UseAccountNumbers?: boolean;
    TaxYearMonth?: string;
    ClassTrackingPerTxn?: boolean;
    TrackDepartments?: boolean;
    DepartmentTerminology?: string;
    ClassTrackingPerTxnLine?: boolean;
  };
  ProductAndServicesPrefs?: {
    ForSales?: boolean;
    ForPurchase?: boolean;
    QuantityWithPriceAndRate?: boolean;
    QuantityOnHand?: boolean;
  };
  SalesFormsPrefs?: {
    CustomField?: Array<{
      CustomField: Array<{
        Name: string;
        Type: string;
        StringValue?: string;
      }>;
    }>;
    AllowDeposit?: boolean;
    AllowDiscount?: boolean;
    DefaultDiscountAccount?: string;
    AllowEstimates?: boolean;
    AllowShipping?: boolean;
    DefaultShippingAccount?: string;
    IPNSupportEnabled?: boolean;
    UsingPriceLevels?: boolean;
    UsingProgressInvoicing?: boolean;
    ETransactionEnabledStatus?: string;
    ETransactionPaymentEnabled?: boolean;
    ETransactionAttachPDF?: boolean;
  };
  EmailMessagesPrefs?: {
    InvoiceMessage?: { Subject?: string; Message?: string };
    EstimateMessage?: { Subject?: string; Message?: string };
    SalesReceiptMessage?: { Subject?: string; Message?: string };
  };
  VendorAndPurchasesPrefs?: {
    TrackingByCustomer?: boolean;
    BillableExpenseTracking?: boolean;
    POCustomField?: Array<{
      CustomField: Array<{
        Name: string;
        Type: string;
        StringValue?: string;
      }>;
    }>;
  };
  TimeTrackingPrefs?: {
    UseServices?: boolean;
    BillCustomers?: boolean;
    ShowBillRateToAll?: boolean;
    WorkWeekStartDate?: string;
    MarkTimeEntriesBillable?: boolean;
  };
  TaxPrefs?: {
    UsingSalesTax?: boolean;
    TaxGroupCodeRef?: Ref;
  };
  CurrencyPrefs?: {
    MultiCurrencyEnabled?: boolean;
    HomeCurrency?: Ref;
  };
  ReportPrefs?: {
    ReportBasis?: 'Accrual' | 'Cash';
    CalcAgingReportFromTxnDate?: boolean;
  };
}

// Report types
export interface ReportColumn {
  ColTitle?: string;
  ColType?: string;
  MetaData?: Array<{
    Name: string;
    Value: string;
  }>;
}

export interface ReportRow {
  type: string;
  Summary?: {
    ColData: Array<{
      value: string;
      id?: string;
    }>;
  };
  ColData?: Array<{
    value: string;
    id?: string;
  }>;
  Rows?: {
    Row: ReportRow[];
  };
  group?: string;
  Header?: {
    ColData: Array<{
      value: string;
    }>;
  };
}

export interface Report {
  Header: {
    Time: string;
    ReportName: string;
    DateMacro?: string;
    StartPeriod?: string;
    EndPeriod?: string;
    Currency?: string;
    Option?: Array<{
      Name: string;
      Value: string;
    }>;
  };
  Columns: {
    Column: ReportColumn[];
  };
  Rows: {
    Row: ReportRow[];
  };
}

export interface ProfitAndLoss extends Report {
  Header: Report['Header'] & {
    ReportName: 'ProfitAndLoss';
  };
}

export interface BalanceSheet extends Report {
  Header: Report['Header'] & {
    ReportName: 'BalanceSheet';
  };
}

export interface CashFlow extends Report {
  Header: Report['Header'] & {
    ReportName: 'CashFlow';
  };
}

// Query Response wrapper
export interface QueryResponse<T> {
  QueryResponse: {
    [key: string]: T[] | number | undefined;
    startPosition: number;
    maxResults: number;
    totalCount?: number;
  };
}

// Error response
export interface QBOError {
  Fault: {
    Error: Array<{
      Message: string;
      Detail: string;
      code: string;
      element?: string;
    }>;
    type: string;
  };
  time: string;
}
