/**
 * Salesforce REST API TypeScript Definitions
 */

// Branded type for Salesforce IDs (15 or 18 characters)
export type SalesforceId = string & { readonly __brand: 'SalesforceId' };

// Helper to create branded IDs
export const salesforceId = (id: string): SalesforceId => id as SalesforceId;

// Base SObject interface - all Salesforce objects extend this
export interface SObject {
  Id?: SalesforceId;
  IsDeleted?: boolean;
  CreatedDate?: string;
  CreatedById?: SalesforceId;
  LastModifiedDate?: string;
  LastModifiedById?: SalesforceId;
  SystemModstamp?: string;
  attributes?: {
    type: string;
    url?: string;
  };
}

// Standard Objects
export interface Account extends SObject {
  Name: string;
  Type?: string;
  Industry?: string;
  BillingStreet?: string;
  BillingCity?: string;
  BillingState?: string;
  BillingPostalCode?: string;
  BillingCountry?: string;
  ShippingStreet?: string;
  ShippingCity?: string;
  ShippingState?: string;
  ShippingPostalCode?: string;
  ShippingCountry?: string;
  Phone?: string;
  Fax?: string;
  Website?: string;
  Description?: string;
  NumberOfEmployees?: number;
  AnnualRevenue?: number;
  OwnerId?: SalesforceId;
  ParentId?: SalesforceId;
}

export interface Contact extends SObject {
  FirstName?: string;
  LastName: string;
  AccountId?: SalesforceId;
  Email?: string;
  Phone?: string;
  MobilePhone?: string;
  Title?: string;
  Department?: string;
  MailingStreet?: string;
  MailingCity?: string;
  MailingState?: string;
  MailingPostalCode?: string;
  MailingCountry?: string;
  Description?: string;
  OwnerId?: SalesforceId;
  ReportsToId?: SalesforceId;
}

export interface Lead extends SObject {
  FirstName?: string;
  LastName: string;
  Company: string;
  Status: string;
  Email?: string;
  Phone?: string;
  MobilePhone?: string;
  Title?: string;
  Industry?: string;
  Street?: string;
  City?: string;
  State?: string;
  PostalCode?: string;
  Country?: string;
  Description?: string;
  OwnerId?: SalesforceId;
  Rating?: string;
  LeadSource?: string;
  ConvertedAccountId?: SalesforceId;
  ConvertedContactId?: SalesforceId;
  ConvertedOpportunityId?: SalesforceId;
  ConvertedDate?: string;
  IsConverted?: boolean;
}

export interface Opportunity extends SObject {
  Name: string;
  AccountId?: SalesforceId;
  StageName: string;
  CloseDate: string;
  Amount?: number;
  Probability?: number;
  Type?: string;
  LeadSource?: string;
  Description?: string;
  OwnerId?: SalesforceId;
  IsClosed?: boolean;
  IsWon?: boolean;
  ForecastCategoryName?: string;
  CampaignId?: SalesforceId;
}

export interface Case extends SObject {
  AccountId?: SalesforceId;
  ContactId?: SalesforceId;
  Status: string;
  Priority?: string;
  Origin?: string;
  Subject?: string;
  Description?: string;
  Type?: string;
  Reason?: string;
  OwnerId?: SalesforceId;
  IsClosed?: boolean;
  ClosedDate?: string;
  ParentId?: SalesforceId;
}

export interface Task extends SObject {
  Subject: string;
  Status: string;
  Priority?: string;
  ActivityDate?: string;
  Description?: string;
  OwnerId?: SalesforceId;
  WhoId?: SalesforceId; // Lead or Contact
  WhatId?: SalesforceId; // Account, Opportunity, etc.
  IsClosed?: boolean;
  IsHighPriority?: boolean;
}

export interface Event extends SObject {
  Subject: string;
  StartDateTime: string;
  EndDateTime: string;
  Location?: string;
  Description?: string;
  OwnerId?: SalesforceId;
  WhoId?: SalesforceId; // Lead or Contact
  WhatId?: SalesforceId; // Account, Opportunity, etc.
  IsAllDayEvent?: boolean;
  IsPrivate?: boolean;
}

export interface Campaign extends SObject {
  Name: string;
  Type?: string;
  Status?: string;
  StartDate?: string;
  EndDate?: string;
  Description?: string;
  IsActive?: boolean;
  BudgetedCost?: number;
  ActualCost?: number;
  ExpectedRevenue?: number;
  NumberOfLeads?: number;
  NumberOfConvertedLeads?: number;
  NumberOfContacts?: number;
  NumberOfOpportunities?: number;
  OwnerId?: SalesforceId;
  ParentId?: SalesforceId;
}

export interface CampaignMember extends SObject {
  CampaignId: SalesforceId;
  LeadId?: SalesforceId;
  ContactId?: SalesforceId;
  Status?: string;
  HasResponded?: boolean;
  FirstRespondedDate?: string;
}

export interface User extends SObject {
  Username: string;
  Email: string;
  FirstName?: string;
  LastName: string;
  Name?: string;
  IsActive?: boolean;
  UserRoleId?: SalesforceId;
  ProfileId?: SalesforceId;
  Title?: string;
  Department?: string;
  Phone?: string;
  MobilePhone?: string;
  TimeZoneSidKey?: string;
  LocaleSidKey?: string;
  EmailEncodingKey?: string;
  LanguageLocaleKey?: string;
}

export interface UserRole extends SObject {
  Name: string;
  ParentRoleId?: SalesforceId;
  DeveloperName?: string;
  PortalType?: string;
}

export interface Profile extends SObject {
  Name: string;
  Description?: string;
  UserType?: string;
  UserLicenseId?: SalesforceId;
}

export interface PermissionSet extends SObject {
  Name: string;
  Label: string;
  Description?: string;
  IsOwnedByProfile?: boolean;
  ProfileId?: SalesforceId;
}

export interface Report extends SObject {
  Name: string;
  DeveloperName: string;
  FolderName?: string;
  Description?: string;
  Format?: string;
  LastRunDate?: string;
  OwnerId?: SalesforceId;
}

export interface Dashboard extends SObject {
  Title: string;
  DeveloperName: string;
  FolderName?: string;
  Description?: string;
  LeftSize?: string;
  MiddleSize?: string;
  RightSize?: string;
  RunningUserId?: SalesforceId;
}

export interface ReportMetadata {
  name: string;
  id?: string;
  developerName?: string;
  reportType?: string;
  reportFormat?: 'TABULAR' | 'SUMMARY' | 'MATRIX';
  aggregates?: Array<{
    acrossGroupingContext?: string;
    calculatedFormula?: string;
    datatype?: string;
    description?: string;
    developerName?: string;
    downGroupingContext?: string;
    isActive?: boolean;
    isCrossBlock?: boolean;
    masterLabel?: string;
    reportType?: string;
    scale?: number;
  }>;
}

export interface ContentDocument extends SObject {
  Title: string;
  FileType?: string;
  FileExtension?: string;
  ContentSize?: number;
  OwnerId?: SalesforceId;
  ParentId?: SalesforceId;
  PublishStatus?: string;
  LatestPublishedVersionId?: SalesforceId;
}

export interface ContentVersion extends SObject {
  Title: string;
  PathOnClient?: string;
  VersionData?: string; // Base64 encoded
  ContentDocumentId?: SalesforceId;
  ReasonForChange?: string;
  ContentSize?: number;
  FileType?: string;
  FileExtension?: string;
  OwnerId?: SalesforceId;
}

export interface Attachment extends SObject {
  Name: string;
  Body: string; // Base64 encoded
  ContentType?: string;
  ParentId?: SalesforceId;
  OwnerId?: SalesforceId;
  IsPrivate?: boolean;
  Description?: string;
  BodyLength?: number;
}

// SOQL Query Result
export interface QueryResult<T = SObject> {
  totalSize: number;
  done: boolean;
  records: T[];
  nextRecordsUrl?: string;
}

// Describe results
export interface FieldDescribe {
  name: string;
  label: string;
  type: string;
  length?: number;
  byteLength?: number;
  precision?: number;
  scale?: number;
  digits?: number;
  picklistValues?: Array<{
    active: boolean;
    defaultValue: boolean;
    label: string;
    value: string;
  }>;
  referenceTo?: string[];
  relationshipName?: string;
  calculatedFormula?: string;
  defaultValue?: unknown;
  defaultValueFormula?: string;
  defaultedOnCreate?: boolean;
  dependentPicklist?: boolean;
  externalId?: boolean;
  htmlFormatted?: boolean;
  idLookup?: boolean;
  inlineHelpText?: string;
  autoNumber?: boolean;
  calculated?: boolean;
  cascadeDelete?: boolean;
  caseSensitive?: boolean;
  createable?: boolean;
  custom?: boolean;
  updateable?: boolean;
  nillable?: boolean;
  nameField?: boolean;
  unique?: boolean;
  sortable?: boolean;
  filterable?: boolean;
  groupable?: boolean;
}

export interface SObjectDescribe {
  name: string;
  label: string;
  labelPlural: string;
  keyPrefix?: string;
  custom: boolean;
  fields: FieldDescribe[];
  childRelationships?: Array<{
    field: string;
    childSObject: string;
    relationshipName?: string;
    cascadeDelete: boolean;
  }>;
  recordTypeInfos?: Array<{
    name: string;
    recordTypeId: string;
    developerName: string;
    active: boolean;
    defaultRecordTypeMapping: boolean;
    master: boolean;
  }>;
  createable?: boolean;
  updateable?: boolean;
  deletable?: boolean;
  queryable?: boolean;
  searchable?: boolean;
  undeletable?: boolean;
  mergeable?: boolean;
  triggerable?: boolean;
  feedEnabled?: boolean;
  activateable?: boolean;
  urls?: Record<string, string>;
}

// Bulk API 2.0 types
export interface BulkJob {
  id?: string;
  object: string;
  operation: 'insert' | 'update' | 'upsert' | 'delete' | 'hardDelete';
  externalIdFieldName?: string;
  contentType?: 'CSV';
  lineEnding?: 'LF' | 'CRLF';
  state?: 'Open' | 'UploadComplete' | 'InProgress' | 'Aborted' | 'JobComplete' | 'Failed';
  createdDate?: string;
  systemModstamp?: string;
  createdById?: string;
  numberRecordsProcessed?: number;
  numberRecordsFailed?: number;
  retries?: number;
  totalProcessingTime?: number;
  apiVersion?: string;
  jobType?: string;
}

export interface BulkJobInfo extends BulkJob {
  state: 'Open' | 'UploadComplete' | 'InProgress' | 'Aborted' | 'JobComplete' | 'Failed';
  numberRecordsProcessed: number;
  numberRecordsFailed: number;
}

export interface BulkResult {
  id?: string;
  success: boolean;
  created: boolean;
  errors?: Array<{
    statusCode: string;
    message: string;
    fields: string[];
  }>;
}

// Composite request/response types
export interface CompositeSubrequest {
  method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
  url: string;
  referenceId: string;
  body?: Record<string, unknown>;
  httpHeaders?: Record<string, string>;
}

export interface CompositeRequest {
  allOrNone?: boolean;
  collateSubrequests?: boolean;
  compositeRequest: CompositeSubrequest[];
}

export interface CompositeSubresponse {
  body: unknown;
  httpHeaders: Record<string, string>;
  httpStatusCode: number;
  referenceId: string;
}

export interface CompositeResponse {
  compositeResponse: CompositeSubresponse[];
}

// Error response
export interface SalesforceError {
  message: string;
  errorCode: string;
  fields?: string[];
}

export interface SalesforceErrorResponse {
  errors?: SalesforceError[];
  message?: string;
  errorCode?: string;
}

// API limits
export interface ApiLimits {
  used: number;
  remaining: number;
}

// Generic custom object support
export type CustomSObject<T extends Record<string, unknown> = Record<string, unknown>> = SObject & T;
