/**
 * Entity Mapper
 * Maps Autotask API responses to PostgreSQL database schema format
 */

import { EntityType } from '../types/sync';

/**
 * Map Autotask field names to PostgreSQL column names
 * Autotask uses camelCase, PostgreSQL uses snake_case
 */
export function toSnakeCase(str: string): string {
  return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
}

/**
 * Map Autotask API response to database format
 * @param entity Entity type
 * @param data Autotask API response data
 * @returns Mapped data for PostgreSQL
 */
export function mapAutotaskToDatabase(
  entity: EntityType,
  data: any
): Record<string, any> {
  // Entity-specific mappings use ORIGINAL data (not snake_cased)
  let mapped: Record<string, any>;
  
  switch (entity) {
    case EntityType.COMPANIES:
      mapped = mapCompany(data);
      break;
    case EntityType.TICKETS:
      mapped = mapTicket(data);
      break;
    case EntityType.TASKS:
      mapped = mapTask(data);
      break;
    case EntityType.PROJECTS:
      mapped = mapProject(data);
      break;
    case EntityType.PROJECT_PHASES:
      mapped = mapProjectPhase(data);
      break;
    case EntityType.RESOURCES:
      mapped = mapResource(data);
      break;
    case EntityType.CONFIGURATION_ITEMS:
      mapped = mapConfigurationItem(data);
      break;
    case EntityType.CONTACTS:
      mapped = mapContact(data);
      break;
    case EntityType.CONTRACTS:
      mapped = mapContract(data);
      break;
    case EntityType.CONTRACT_SERVICES:
      mapped = mapContractService(data);
      break;
    case EntityType.AUTOTASK_SERVICES:
      mapped = mapAutotaskService(data);
      break;
    case EntityType.BILLING_ITEMS:
      mapped = mapBillingItem(data);
      break;
    case EntityType.TIME_ENTRIES:
      mapped = mapTimeEntry(data);
      break;
    case EntityType.TICKET_NOTES:
      mapped = mapTicketNote(data);
      break;
    case EntityType.STATUSES:
    case EntityType.ISSUE_TYPES:
    case EntityType.SUB_ISSUE_TYPES:
    case EntityType.WORK_TYPES:
    case EntityType.COMPANY_CATEGORIES:
    case EntityType.COMPANY_TYPES:
      mapped = mapPicklist(data);
      break;
    case EntityType.TAG_GROUPS:
      mapped = mapTagGroup(data);
      break;
    case EntityType.TAGS:
      mapped = mapTag(data);
      break;
    case EntityType.COMPANY_TEAMS:
      mapped = mapCompanyTeam(data);
      break;
    default:
      // Fallback: auto-convert camelCase to snake_case
      mapped = {};
      for (const [key, value] of Object.entries(data)) {
        const snakeKey = toSnakeCase(key);
        mapped[snakeKey] = value;
      }
  }
  
  // Add sync timestamp
  mapped.synced_at = new Date();
  
  // Ensure is_deleted is false for new/updated records
  if (mapped.is_deleted === undefined) {
    mapped.is_deleted = false;
  }
  
  return mapped;
}

/**
 * Map Company entity
 */
function mapCompany(data: any): Record<string, any> {
  // Convert userDefinedFields array → JSONB object { name: value }
  const udfs: Record<string, string | null> = {};
  if (Array.isArray(data.userDefinedFields)) {
    for (const udf of data.userDefinedFields) {
      udfs[udf.name] = udf.value ?? null;
    }
  }

  return {
    id: data.id,
    company_name: data.companyName || data.name,
    company_number: data.companyNumber,
    phone: data.phone,
    fax: data.fax,
    web_address: data.webAddress,
    address1: data.address1,
    address2: data.address2,
    city: data.city,
    state: data.state,
    postal_code: data.postalCode,
    country_id: data.countryID,
    is_active: data.isActive !== undefined ? data.isActive : true,
    company_type: data.companyType,
    company_category_id: data.companyCategoryID,
    owner_resource_id: data.ownerResourceID,
    territory_id: data.territoryID,
    market_segment_id: data.marketSegmentID,
    competitor_id: data.competitorID,
    parent_company_id: data.parentCompanyID,
    billing_address1: data.billingAddress1,
    billing_address2: data.billingAddress2,
    billing_city: data.billToCity,
    billing_state: data.billToState,
    billing_postal_code: data.billToZipCode,
    bill_to_country_id: data.billToCountryID,
    bill_to_address_to_use: data.billToAddressToUse,
    bill_to_attention: data.billToAttention,
    additional_address_information: data.additionalAddressInformation,
    bill_to_additional_address_info: data.billToAdditionalAddressInformation,
    tax_id: data.taxID,
    tax_exempt: data.isTaxExempt || false,
    tax_region_id: data.taxRegionID,
    currency_id: data.currencyID,
    invoice_method: data.invoiceMethod,
    invoice_template_id: data.invoiceTemplateID,
    invoice_email_message_id: data.invoiceEmailMessageID,
    quote_template_id: data.quoteTemplateID,
    purchase_order_template_id: data.purchaseOrderTemplateID,
    key_account_icon: data.keyAccountIcon,
    is_client_portal_active: data.isClientPortalActive || false,
    is_task_fire_active: data.isTaskFireActive || false,
    is_comanaged: data.isEnabledForComanaged || false,
    sic_code: data.sicCode,
    stock_market: data.stockMarket,
    stock_symbol: data.stockSymbol,
    alternate_phone1: data.alternatePhone1,
    alternate_phone2: data.alternatePhone2,
    survey_company_rating: data.surveyCompanyRating,
    asset_value: data.assetValue,
    last_activity_date: data.lastActivityDate,
    last_tracked_modification_date_time: data.lastTrackedModifiedDateTime,
    api_vendor_id: data.apiVendorID,
    create_date: data.createDate,
    created_by_resource_id: data.createdByResourceID,
    classification: data.classification ?? null,
    bill_to_company_location_id: data.billToCompanyLocationID ?? null,
    impersonator_creator_resource_id: data.impersonatorCreatorResourceID ?? null,
    invoice_non_contract_items_to_parent_company: data.invoiceNonContractItemsToParentCompany ?? null,
    quote_email_message_id: data.quoteEmailMessageID ?? null,
    user_defined_fields: Object.keys(udfs).length > 0 ? JSON.stringify(udfs) : null,
    is_deleted: data.isDeleted || false,
  };
}

/**
 * Map Ticket entity
 */
function mapTicket(data: any): Record<string, any> {
  return {
    id: data.id,
    company_id: data.companyID,
    ticket_number: data.ticketNumber,
    title: data.title,
    description: data.description,
    status: data.status,
    priority: data.priority,
    queue_id: data.queueID,
    issue_type: data.issueType,
    sub_issue_type: data.subIssueType,
    source: data.source,
    assigned_resource_id: data.assignedResourceID,
    assigned_resource_role_id: data.assignedResourceRoleID,
    contact_id: data.contactID,
    account_physical_location_id: data.companyLocationID,
    due_date_time: data.dueDateTime,
    estimated_hours: data.estimatedHours,
    completed_date: data.completedDate,
    create_date: data.createDate,
    created_by_contact_id: data.createdByContactID,
    creator_resource_id: data.creatorResourceID,
    creator_type: data.creatorType,
    billing_code_id: data.billingCodeID,
    configuration_item_id: data.configurationItemID,
    last_activity_date: data.lastActivityDate,
    last_customer_notification_date_time: data.lastCustomerNotificationDateTime,
    last_customer_visible_activity_date_time: data.lastCustomerVisibleActivityDateTime,
    first_response_date_time: data.firstResponseDateTime,
    resolution_plan_date_time: data.resolutionPlanDateTime,
    resolved_date_time: data.resolvedDateTime,
    first_response_assigned_resource_id: data.firstResponseAssignedResourceID,
    first_response_initiating_resource_id: data.firstResponseInitiatingResourceID,
    project_id: data.projectID,
    opportunity_id: data.opportunityID,
    change_approval_board: data.changeApprovalBoard,
    change_approval_status: data.changeApprovalStatus,
    change_approval_type: data.changeApprovalType,
    change_info_field1: data.changeInfoField1,
    change_info_field2: data.changeInfoField2,
    change_info_field3: data.changeInfoField3,
    change_info_field4: data.changeInfoField4,
    change_info_field5: data.changeInfoField5,
    contract_id: data.contractID,
    monitor_id: data.monitorID,
    monitor_type_id: data.monitorTypeID,
    ticket_type: data.ticketType,
    ticket_category: data.ticketCategory,
    service_level_agreement_id: data.serviceLevelAgreementID,
    resolution: data.resolution,
    purchase_order_number: data.purchaseOrderNumber,
    ticket_completion_date: data.ticketCompletionDate,
    last_activity_person_type: data.lastActivityPersonType,
    last_activity_resource_id: data.lastActivityResourceID,
    current_service_thermometer_rating: data.currentServiceThermometerRating,
    previous_service_thermometer_rating: data.previousServiceThermometerRating,
    service_thermometer_temperature: data.serviceThermometerTemperature,
    api_vendor_id: data.apiVendorID,
    problem_ticket_id: data.problemTicketId,
    rma_status: data.rmaStatus,
    rma_type: data.rmaType,
    service_level_agreement_paused_next_event_hours: data.serviceLevelAgreementPausedNextEventHours,
    is_assigned_to_comanaged: data.isAssignedToComanaged || false,
    is_visible_to_comanaged: data.isVisibleToComanaged || false,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map TicketNote entity
 */
function mapTicketNote(data: any): Record<string, any> {
  return {
    id: data.id,
    ticket_id: data.ticketID,
    title: data.title,
    description: data.description,
    note_type: data.noteType,
    publish: data.publish,
    creator_resource_id: data.creatorResourceID,
    creator_type: data.creatorType,
    last_activity_date: data.lastActivityDate,
    create_date_time: data.createDateTime,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map Task entity
 */
function mapTask(data: any): Record<string, any> {
  return {
    id: data.id,
    title: data.title,
    description: data.description,
    status: data.status,
    priority: data.priority,
    assigned_resource_id: data.assignedResourceID,
    assigned_resource_role_id: data.assignedResourceRoleID,
    department_id: data.departmentID,
    estimated_hours: data.estimatedHours,
    remaining_hours: data.remainingHours,
    hours_to_be_scheduled: data.hoursToBeScheduled,
    start_date_time: data.startDateTime,
    end_date_time: data.endDateTime,
    completed_date_time: data.completedDateTime,
    create_date_time: data.createDateTime,
    creator_resource_id: data.creatorResourceID,
    completed_by_resource_id: data.completedByResourceID,
    last_activity_date_time: data.lastActivityDateTime,
    project_id: data.projectID,
    ticket_id: data.ticketID,
    phase_id: data.phaseID,
    allocation_code_id: data.allocationCodeID,
    task_type: data.taskType,
    task_is_billable: data.taskIsBillable !== undefined ? data.taskIsBillable : true,
    task_number: data.taskNumber,
    purchase_order_number: data.purchaseOrderNumber,
    can_client_portal_user_complete_task: data.canClientPortalUserCompleteTask || false,
    creator_type: data.creatorType,
    task_category_id: data.taskCategoryID,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map Project entity
 */
function mapProject(data: any): Record<string, any> {
  return {
    id: data.id,
    company_id: data.companyID,
    project_name: data.projectName,
    project_number: data.projectNumber,
    description: data.description,
    start_date_time: data.start_date_time,
    end_date_time: data.end_date_time,
    estimated_time: data.estimated_time,
    actual_hours: data.actual_hours,
    estimated_sale_cost: data.estimated_sale_cost,
    labor_estimated_costs: data.labor_estimated_costs,
    labor_estimated_revenue: data.labor_estimated_revenue,
    project_cost_estimated_margin_percentage: data.project_cost_estimated_margin_percentage,
    status: data.status,
    type: data.type,
    project_lead_resource_id: data.project_lead_resource_id,
    account_executive_resource_id: data.account_executive_resource_id,
    owner_resource_id: data.owner_resource_id,
    creator_resource_id: data.creator_resource_id,
    completed_percentage: data.completed_percentage,
    completed_date_time: data.completed_date_time,
    duration: data.duration,
    original_estimated_revenue: data.original_estimated_revenue,
    estimated_time_cost: data.estimated_time_cost,
    purchase_order_number: data.purchase_order_number,
    business_division_subdivision_id: data.business_division_subdivision_id,
    line_of_business_id: data.line_of_business_id,
    department: data.department,
    last_activity_date_time: data.last_activity_date_time,
    last_activity_person_type: data.last_activity_person_type,
    last_activity_resource_id: data.last_activity_resource_id,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map ProjectPhase entity
 */
function mapProjectPhase(data: any): Record<string, any> {
  return {
    id: data.id,
    project_id: data.projectID,
    title: data.title,
    description: data.description,
    phase_number: data.phaseNumber,
    estimated_hours: data.estimatedHours,
    start_date_time: data.startDate,
    due_date: data.dueDate,
    create_date_time: data.createDate,
    last_activity_date_time: data.lastActivityDateTime,
    parent_phase_id: data.parentPhaseID,
    is_scheduled: data.isScheduled,
    creator_resource_id: data.creatorResourceID,
    external_id: data.externalID,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map Resource entity
 */
function mapResource(data: any): Record<string, any> {
  // Helper to safely parse integer values (returns null for non-numeric strings)
  const safeInt = (value: any): number | null => {
    if (value === null || value === undefined || value === '') return null;
    const num = typeof value === 'number' ? value : parseInt(value, 10);
    return isNaN(num) ? null : num;
  };

  return {
    id: data.id,
    // Name fields
    first_name: data.firstName,
    last_name: data.lastName,
    middle_initial: data.middleInitial,
    name_prefix: data.namePrefix,
    name_suffix: data.nameSuffix,
    
    // Contact information
    email: data.email || data.emailAddress,
    email_address: data.emailAddress,
    email_address2: data.emailAddress2,
    email_address3: data.emailAddress3,
    office_phone: data.officePhone,
    mobile_phone: data.mobilePhone,
    home_phone: data.homePhone,
    office_extension: data.officeExtension,
    
    // System fields
    user_name: data.userName,
    title: data.title,
    is_active: data.isActive !== undefined ? data.isActive : true,
    
    // Employment details
    resource_type: safeInt(data.resourceType),
    payroll_identifier: data.payrollIdentifier,
    pay_roll_identifier: data.payrollIdentifier, // Keep for backward compatibility
    payroll_type: safeInt(data.payrollType),
    accounting_reference_id: data.accountingReferenceID,
    internal_cost: data.internalCost,
    hire_date: data.hireDate,
    
    // Location and availability
    location_id: safeInt(data.locationID),
    travel_availability_pct: data.travelAvailabilityPct,
    default_service_desk_role_id: safeInt(data.defaultServiceDeskRoleID),
    
    // System preferences
    email_type_code: safeInt(data.emailTypeCode),
    number_format: data.numberFormat,
    time_format: data.timeFormat,
    date_format: data.dateFormat,
    
    // Demographics and security
    gender: safeInt(data.gender),
    license_type: safeInt(data.licenseType),
    security_level: safeInt(data.securityLevel),
    
    // Ratings
    survey_resource_rating: data.surveyResourceRating,
    
    // Audit fields
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map Configuration Item entity
 */
function mapConfigurationItem(data: any): Record<string, any> {
  const mapped: Record<string, any> = {
    id: data.id,
    company_id: data.companyID,
    product_id: data.productID,
    reference_title: data.referenceTitle,
    reference_number: data.referenceNumber,
    serial_number: data.serialNumber,
    install_date: data.installDate,
    warranty_expiration_date: data.warrantyExpirationDate,
    is_active: data.isActive !== undefined ? data.isActive : true,
    daily_cost: data.dailyCost,
    hourly_cost: data.hourlyCost,
    monthly_cost: data.monthlyCost,
    per_use_cost: data.perUseCost,
    setup_fee: data.setupFee,
    contact_id: data.contactID,
    location_id: data.locationID,
    vendor_id: data.vendorID,
    installed_by_id: data.installedByID,
    installed_by_contact_id: data.installedByContactID,
    parent_configuration_item_id: data.parentConfigurationItemID,
    notes: data.notes,
    create_date: data.createDate,
    created_by_person_id: data.createdByPersonID,
    last_modified_time: data.lastModifiedTime,
    last_activity_person_type: data.lastActivityPersonType,
    impersonator_creator_resource_id: data.impersonatorCreatorResourceID,
    configuration_item_category_id: data.configurationItemCategoryID,
    configuration_item_type: data.type,
    device_type: data.deviceType,
    rmm_device_uid: data.rmmDeviceUID,
    api_vendor_id: data.apiVendorID,
    // Datto fields
    datto_availability: data.dattoAvailability,
    datto_device_memory_megabytes: data.dattoDeviceMemoryMegabytes,
    datto_drives_errors: data.dattoDrivesErrors,
    datto_hostname: data.dattoHostname,
    datto_internal_ip: data.dattoInternalIP,
    datto_kernel_version_id: data.dattoKernelVersionID,
    datto_last_check_in_date_time: data.dattoLastCheckInDateTime,
    datto_nic_speed_kilobits_per_second: data.dattoNicSpeedKilobitsPerSecond,
    datto_number_of_agents: data.dattoNumberOfAgents,
    datto_number_of_drives: data.dattoNumberOfDrives,
    datto_number_of_logical_volumes: data.dattoNumberOfLogicalVolumes,
    datto_number_of_volumes: data.dattoNumberOfVolumes,
    datto_off_site_storage_used_bytes: data.dattoOffSiteStorageUsedBytes,
    datto_os_version_id: data.dattoOsVersionID,
    datto_percentage_used: data.dattoPercentageUsed,
    datto_protected_kilobytes: data.dattoProtectedKilobytes,
    datto_remote_ip: data.dattoRemoteIP,
    datto_serial_number: data.dattoSerialNumber,
    datto_uptime_seconds: data.dattoUptimeSeconds,
    datto_used_kilobytes: data.dattoUsedKilobytes,
    datto_z_pool_percentage: data.dattoZPoolPercentage,
    device_networking_id: data.deviceNetworkingID,
    last_backup_date: data.lastBackupDateTime || data.lastBackupDate,
    last_backup_status: data.lastBackupStatus,
    os_version_id: data.osVersionID,
    service_id: data.serviceID,
    service_bundle_id: data.serviceBundleID,
    snmp_location: data.snmpLocation,
    snmp_name: data.snmpName,
    snmp_contact: data.snmpContact,
    // RMM audit fields
    rmm_device_audit_architecture_id: data.rmmDeviceAuditArchitectureID,
    rmm_device_audit_display_adaptor_id: data.rmmDeviceAuditDisplayAdaptorID,
    rmm_device_audit_domain_id: data.rmmDeviceAuditDomainID,
    rmm_device_audit_external_ip_address: data.rmmDeviceAuditExternalIPAddress,
    rmm_device_audit_hostname: data.rmmDeviceAuditHostname,
    rmm_device_audit_ip_address: data.rmmDeviceAuditIPAddress,
    rmm_device_audit_mac_address: data.rmmDeviceAuditMacAddress,
    rmm_device_audit_manufacturer_id: data.rmmDeviceAuditManufacturerID,
    rmm_device_audit_missing_patch_count: data.rmmDeviceAuditMissingPatchCount,
    rmm_device_audit_mobile_network_operator_id: data.rmmDeviceAuditMobileNetworkOperatorID,
    rmm_device_audit_mobile_number: data.rmmDeviceAuditMobileNumber,
    rmm_device_audit_model_id: data.rmmDeviceAuditModelID,
    rmm_device_audit_motherboard_id: data.rmmDeviceAuditMotherboardID,
    rmm_device_audit_operating_system_id: data.rmmDeviceAuditOperatingSystemID,
    rmm_device_audit_processor_id: data.rmmDeviceAuditProcessorID,
    rmm_device_audit_service_pack_id: data.rmmDeviceAuditServicePackID,
    rmm_device_audit_snmp_contact: data.rmmDeviceAuditSNMPContact,
    rmm_device_audit_snmp_location: data.rmmDeviceAuditSNMPLocation,
    rmm_device_audit_snmp_name: data.rmmDeviceAuditSNMPName,
    rmm_device_audit_software_status_id: data.rmmDeviceAuditSoftwareStatusID,
    rmm_device_audit_storage_bytes: data.rmmDeviceAuditStorageBytes,
    rmm_open_alert_count: data.rmmOpenAlertCount,
    rmm_device_audit_description: data.rmmDeviceAuditDescription,
    rmm_device_audit_device_type_id: data.rmmDeviceAuditDeviceTypeID,
    rmm_device_audit_last_user: data.rmmDeviceAuditLastUser,
    rmm_device_audit_memory_bytes: data.rmmDeviceAuditMemoryBytes,
    source_cost_id: data.sourceCostID,
    source_cost_type: data.sourceCostType,
  };

  // Store all UDFs as JSONB
  if (data.userDefinedFields && Array.isArray(data.userDefinedFields)) {
    const udfMap: Record<string, string> = {};
    for (const udf of data.userDefinedFields) {
      if (udf.name != null) {
        udfMap[String(udf.name)] = udf.value ?? null;
      }
    }
    mapped.udfs = Object.keys(udfMap).length > 0 ? udfMap : null;

    // Also extract the named backup_type_udf for backward compat
    const backupUdf = data.userDefinedFields.find(
      (udf: any) => udf.name === 'Backup Type' || String(udf.name) === '29693319'
    );
    if (backupUdf?.value) {
      mapped.backup_type_udf = backupUdf.value;
    }
  }

  return mapped;
}

/**
 * Map Contact entity
 */
function mapContact(data: any): Record<string, any> {
  // Convert userDefinedFields array → JSONB object { name: value }
  const udfs: Record<string, string | null> = {};
  if (Array.isArray(data.userDefinedFields)) {
    for (const udf of data.userDefinedFields) {
      udfs[udf.name] = udf.value ?? null;
    }
  }

  return {
    id: data.id,
    company_id: data.companyID,
    first_name: data.firstName,
    last_name: data.lastName,
    middle_initial: data.middleInitial,
    title: data.title,
    email_address: data.emailAddress,
    email_address2: data.emailAddress2,
    email_address3: data.emailAddress3,
    phone: data.phone,
    extension: data.extension,
    alternate_phone: data.alternatePhone,
    mobile_phone: data.mobilePhone,
    fax: data.faxNumber,
    address_line: data.addressLine,
    address_line1: data.addressLine1,
    city: data.city,
    state: data.state,
    zip_code: data.zipCode,
    country_id: data.countryID,
    company_location_id: data.companyLocationID,
    is_active: data.isActive !== undefined ? data.isActive : true,
    name_prefix: data.namePrefix,
    name_suffix: data.nameSuffix,
    facebook_url: data.facebookUrl,
    twitter_url: data.twitterUrl,
    linked_in_url: data.linkedInUrl,
    primary_contact: data.primaryContact || false,
    billing_contact: data.billingContact || false,
    solicitation_opt_out: data.solicitationOptOut || false,
    solicitation_opt_out_time: data.solicitationOptOutTime,
    survey_opt_out: data.surveyOptOut || false,
    is_opted_out_from_bulk_email: data.isOptedOutFromBulkEmail || false,
    bulk_email_opt_out_time: data.bulkEmailOptOutTime,
    receives_email_notifications: data.receivesEmailNotifications !== undefined ? data.receivesEmailNotifications : true,
    room_number: data.roomNumber,
    note: data.note,
    external_id: data.externalID,
    api_vendor_id: data.apiVendorID,
    impersonator_creator_resource_id: data.impersonatorCreatorResourceID,
    create_date: data.createDate,
    last_activity_date: data.lastActivityDate,
    last_modified_date: data.lastModifiedDate,
    user_defined_fields: Object.keys(udfs).length > 0 ? JSON.stringify(udfs) : null,
    is_deleted: data.isDeleted || false,
  };
}

/**
 * Map Contract entity
 */
function mapContract(data: any): Record<string, any> {
  return {
    id: data.id,
    company_id: data.companyID,
    contract_name: data.contractName,
    contract_number: data.contractNumber,
    description: data.description,
    start_date: data.start_date,
    end_date: data.end_date,
    time_reporting_requires_start_and_stop_times: data.time_reporting_requires_start_and_stop_times,
    service_level_agreement_id: data.service_level_agreement_id,
    contract_type: data.contract_type,
    contract_category: data.contract_category,
    status: data.status,
    business_division_subdivision_id: data.business_division_subdivision_id,
    contact_id: data.contact_id,
    contact_name: data.contact_name,
    billing_preference: data.billing_preference,
    purchase_order_number: data.purchase_order_number,
    setup_fee: data.setup_fee,
    setup_fee_allocation_code_id: data.setup_fee_allocation_code_id,
    estimated_cost: data.estimated_cost,
    estimated_hours: data.estimated_hours,
    estimated_revenue: data.estimated_revenue,
    over_budget_dollar_amount: data.over_budget_dollar_amount,
    over_budget_hours: data.over_budget_hours,
    contract_period_type: data.contract_period_type,
    opportunity_id: data.opportunity_id,
    renewed_contract_id: data.renewed_contract_id,
    is_default_contract: data.is_default_contract || false,
    internal_currency_setup_fee: data.internal_currency_setup_fee,
    internal_currency_over_budget_dollar_amount: data.internal_currency_over_budget_dollar_amount,
    internal_currency_estimated_cost: data.internal_currency_estimated_cost,
    internal_currency_estimated_revenue: data.internal_currency_estimated_revenue,
    exclusion_contract_id: data.exclusion_contract_id,
    internal_currency_monthly_revenue: data.internal_currency_monthly_revenue,
    internal_currency_quarterly_revenue: data.internal_currency_quarterly_revenue,
    internal_currency_semi_annual_revenue: data.internal_currency_semi_annual_revenue,
    internal_currency_yearly_revenue: data.internal_currency_yearly_revenue,
    internal_currency_one_time_revenue: data.internal_currency_one_time_revenue,
    compliance: data.compliance,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map Autotask Service (catalog item) entity
 */
function mapAutotaskService(data: any): Record<string, any> {
  return {
    id: data.id,
    name: data.name,
    description: data.description,
    unit_price: data.unitPrice,
    unit_cost: data.unitCost,
    period_type: data.periodType,
    is_active: data.isActive !== undefined ? data.isActive : true,
    synced_at: new Date(),
    is_deleted: false,
  };
}

/**
 * Map Contract Service entity
 */
function mapContractService(data: any): Record<string, any> {
  return {
    id: data.id,
    contract_id: data.contractID,
    service_id: data.serviceID,
    unit_price: data.unitPrice,
    unit_cost: data.unitCost,
    adjusted_price: data.internalCurrencyAdjustedPrice,
    invoice_description: data.invoiceDescription,
    internal_currency_price: data.internalCurrencyUnitPrice,
    synced_at: new Date(),
    is_deleted: false,
  };
}

/**
 * Map Billing Item entity
 */
function mapBillingItem(data: any): Record<string, any> {
  return {
    id: data.id,
    company_id: data.companyID,
    product_id: data.productID,
    description: data.description,
    quantity: data.quantity,
    rate: data.rate,
    total_amount: data.total_amount,
    line_discount_dollars: data.line_discount_dollars,
    line_discount_percent: data.line_discount_percent,
    tax_category_id: data.tax_category_id,
    internal_currency_line_discount_dollars: data.internal_currency_line_discount_dollars,
    allocation_code_id: data.allocation_code_id,
    invoice_id: data.invoice_id,
    vendor_id: data.vendor_id,
    expense_item: data.expense_item || false,
    task_id: data.task_id,
    ticket_id: data.ticket_id,
    project_id: data.project_id,
    our_cost: data.our_cost,
    list_price: data.list_price,
    unit_cost: data.unit_cost,
    unit_price: data.unit_price,
    extended_price: data.extended_price,
    tax_dollars: data.tax_dollars,
    internal_currency_unit_price: data.internal_currency_unit_price,
    internal_currency_total_amount: data.internal_currency_total_amount,
    synced_at: data.synced_at,
    is_deleted: data.is_deleted || false,
  };
}

/**
 * Map Time Entry entity
 */
function mapTimeEntry(data: any): Record<string, any> {
  // Autotask uses isNonBillable; derive billable from it
  const isNonBillable = data.isNonBillable;
  const billable = isNonBillable != null ? !isNonBillable : null;

  return {
    id: data.id,
    resource_id: data.resourceID,
    ticket_id: data.ticketID,
    task_id: data.taskID,
    contract_id: data.contractID,
    contract_service_id: data.contractServiceID,
    contract_service_bundle_id: data.contractServiceBundleID,
    entry_date: data.dateWorked,
    hours_worked: data.hoursWorked,
    hours_to_bill: data.hoursToBill,
    notes: data.summaryNotes,
    internal_notes: data.internalNotes,
    type: data.timeEntryType,
    start_date_time: data.startDateTime,
    end_date_time: data.endDateTime,
    billable,
    non_billable: isNonBillable,
    allocation_code_id: data.billingCodeID,
    approved_by_resource_id: data.billingApprovalResourceID,
    approved_date_time: data.billingApprovalDateTime,
    role_id: data.roleID,
    synced_at: new Date(),
    is_deleted: false,
  };
}

/**
 * Map TagGroup entity
 */
function mapTagGroup(data: any): Record<string, any> {
  return {
    id: data.id,
    label: data.label,
    display_color: data.displayColor,
    is_active: data.isActive !== undefined ? data.isActive : true,
    is_system: data.isSystem || false,
  };
}

/**
 * Map Tag entity
 */
function mapTag(data: any): Record<string, any> {
  return {
    id: data.id,
    label: data.label,
    tag_group_id: data.tagGroupID,
    is_active: data.isActive !== undefined ? data.isActive : true,
    is_system: data.isSystem || false,
    is_excluded_from_automatic_tagging: data.isExcludedFromAutomaticTagging || false,
    create_date_time: data.createDateTime,
    last_modified_date_time: data.lastModifiedDateTime,
  };
}

/**
 * Map Picklist entity (statuses, issue types, etc.)
 */
function mapPicklist(data: any): Record<string, any> {
  return {
    value: data.value,
    label: data.label || data.name,
    is_active: data.isActive !== undefined ? data.isActive : true,
    is_system: data.isSystem || false,
    sort_order: data.sortOrder,
    parent_value: data.parentValue,
  };
}

/**
 * Map CompanyTeam entity
 */
function mapCompanyTeam(data: any): Record<string, any> {
  return {
    id: data.id,
    company_id: data.companyID,
    resource_id: data.resourceID,
    is_associated_as_comanaged: data.isAssociatedAsComanaged || false,
    is_deleted: false,
  };
}

/**
 * Batch map multiple entities
 */
export function mapAutotaskBatch(
  entity: EntityType,
  items: any[]
): Record<string, any>[] {
  return items.map(item => mapAutotaskToDatabase(entity, item));
}
