/**
 * Contact Platform Tools
 *
 * Platform tools for contact CRUD operations in the acquisition domain.
 * Used by AI agents to manage contact records with multi-tenant isolation.
 *
 * All operations require organizationId from ExecutionContext for RLS enforcement.
 */

import { getToolServices } from '../../registry'
import { serviceUnavailable } from '../../types'
import type { Tool } from '../../types'
import {
  CreateContactInputSchema,
  UpdateContactInputSchema,
  UpsertContactInputSchema,
  GetContactInputSchema,
  ListContactsInputSchema,
  DeleteContactInputSchema,
  BulkImportInputSchema,
  ContactOutputSchema,
  PaginatedContactsOutputSchema,
  BulkImportResultSchema,
  DeleteResultSchema,
  DeactivateContactsByCompanyInputSchema,
  DeactivateContactsByCompanyResultSchema
} from './types'

/**
 * Transform contact result to output format
 * Converts Date objects to ISO strings for JSON serialization
 */
function toContactOutput(result: any) {
  return {
    id: result.id,
    organizationId: result.organizationId,
    companyId: result.companyId,
    email: result.email,
    emailValid: result.emailValid,
    firstName: result.firstName,
    lastName: result.lastName,
    linkedinUrl: result.linkedinUrl,
    title: result.title,
    headline: result.headline,
    filterReason: result.filterReason,
    openingLine: result.openingLine,
    source: result.source,
    sourceId: result.sourceId,
    processingState: result.processingState,
    pipelineStatus: null,
    enrichmentData: result.enrichmentData,
    tags: result.tags,
    batchId: result.batchId ?? null,
    status: result.status ?? 'active',
    createdAt: result.createdAt instanceof Date ? result.createdAt.toISOString() : result.createdAt,
    updatedAt: result.updatedAt instanceof Date ? result.updatedAt.toISOString() : result.updatedAt
  }
}

/**
 * Create a new contact record
 *
 * @returns Tool for creating contacts
 */
export function createAcqContactCreateTool(): Tool {
  return {
    name: 'acq_contact_create',
    description: 'Create a new contact record.',
    inputSchema: CreateContactInputSchema,
    outputSchema: ContactOutputSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const validated = input as {
        email: string
        companyId?: string
        firstName?: string
        lastName?: string
        linkedinUrl?: string
        title?: string
        source?: string
        sourceId?: string
        batchId?: string
      }

      const result = await leadService.createContact({
        organizationId: executionContext.organizationId,
        ...validated
      })

      return toContactOutput(result)
    }
  }
}

/**
 * Update an existing contact with new data
 *
 * @returns Tool for updating contacts (enrichment, personalization, campaign status)
 */
export function createAcqContactUpdateTool(): Tool {
  return {
    name: 'acq_contact_update',
    description: 'Update an existing contact with new data (enrichment, personalization, campaign status).',
    inputSchema: UpdateContactInputSchema,
    outputSchema: ContactOutputSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const { id, ...params } = input as { id: string; [key: string]: unknown }
      const result = await leadService.updateContact(id, params)

      return toContactOutput(result)
    }
  }
}

/**
 * Upsert a contact by email
 *
 * @returns Tool for upserting contacts (creates new or updates existing by email)
 */
export function createAcqContactUpsertTool(): Tool {
  return {
    name: 'acq_contact_upsert',
    description: 'Upsert a contact by email. Creates new contact if email does not exist, otherwise updates existing.',
    inputSchema: UpsertContactInputSchema,
    outputSchema: ContactOutputSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const validated = input as {
        email: string
        companyId?: string
        firstName?: string
        lastName?: string
        linkedinUrl?: string
        title?: string
        source?: string
        sourceId?: string
        batchId?: string
      }

      const result = await leadService.upsertContact({
        organizationId: executionContext.organizationId,
        ...validated
      })

      return toContactOutput(result)
    }
  }
}

/**
 * Get a single contact by ID
 *
 * @returns Tool for retrieving a contact by ID
 */
export function createAcqContactGetTool(): Tool {
  return {
    name: 'acq_contact_get',
    description: 'Get a single contact by ID.',
    inputSchema: GetContactInputSchema,
    outputSchema: ContactOutputSchema.nullable(),
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const { id } = input as { id: string }
      const result = await leadService.getContact(id, executionContext.organizationId)
      return result ? toContactOutput(result) : null
    }
  }
}

/**
 * List contacts with filters and pagination
 *
 * @returns Tool for listing contacts with optional filters (list, qualification, campaign)
 */
export function createAcqContactListTool(): Tool {
  return {
    name: 'acq_contact_list',
    description: 'List contacts with optional filters (list, qualification, campaign) and pagination.',
    inputSchema: ListContactsInputSchema,
    outputSchema: PaginatedContactsOutputSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const { limit, offset, ...filters } = input as {
        limit?: number
        offset?: number
        openingLineIsNull?: boolean
        batchId?: string
        contactStatus?: 'active' | 'invalid'
      }
      const result = await leadService.listContacts(executionContext.organizationId, filters, {
        limit: limit ?? 100,
        offset: offset ?? 0
      })

      return {
        data: result.data.map(toContactOutput),
        total: result.total,
        limit: result.limit,
        offset: result.offset
      }
    }
  }
}

/**
 * Delete a contact record
 *
 * @returns Tool for deleting contacts
 */
export function createAcqContactDeleteTool(): Tool {
  return {
    name: 'acq_contact_delete',
    description: 'Delete a contact record.',
    inputSchema: DeleteContactInputSchema,
    outputSchema: DeleteResultSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const { id } = input as { id: string }
      await leadService.deleteContact(id, executionContext.organizationId)
      return { success: true }
    }
  }
}

/**
 * Batch import contacts with automatic deduplication
 *
 * @returns Tool for bulk importing contacts (creates new or updates existing by email)
 */
export function createAcqContactBulkImportTool(): Tool {
  return {
    name: 'acq_contact_bulk_import',
    description:
      'Batch import contacts with automatic deduplication. Creates new contacts or updates existing by email.',
    inputSchema: BulkImportInputSchema,
    outputSchema: BulkImportResultSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const { contacts } = input as {
        contacts: Array<{
          email: string
          companyId?: string
          firstName?: string
          lastName?: string
          linkedinUrl?: string
          title?: string
          source?: string
          sourceId?: string
          batchId?: string
        }>
      }

      const result = await leadService.bulkImportContacts({
        organizationId: executionContext.organizationId,
        contacts: contacts.map((c) => ({
          organizationId: executionContext.organizationId,
          ...c
        }))
      })

      return result
    }
  }
}

/**
 * Deactivate all active contacts belonging to a company.
 * Used by qualification workflow to cascade company disqualification.
 *
 * @returns Tool for bulk deactivating contacts by company
 */
export function createAcqContactDeactivateByCompanyTool(): Tool {
  return {
    name: 'acq_contact_deactivate_by_company',
    description: 'Deactivate all active contacts belonging to a company. Used to cascade company disqualification.',
    inputSchema: DeactivateContactsByCompanyInputSchema,
    outputSchema: DeactivateContactsByCompanyResultSchema,
    execute: async ({ input, executionContext }) => {
      const leadService = getToolServices().leadService
      if (!leadService) throw serviceUnavailable('LeadService')
      if (!executionContext?.organizationId)
        throw serviceUnavailable('ExecutionContext', { reason: 'organizationId required for multi-tenant isolation' })

      const { companyId } = input as { companyId: string }
      return leadService.deactivateContactsByCompany({
        organizationId: executionContext.organizationId,
        companyId
      })
    }
  }
}
