import { getToolServices } from '../../registry'
import { serviceUnavailable } from '../../types'
import type { Tool } from '../../types'
import {
  CreateCompanyInputSchema,
  UpdateCompanyInputSchema,
  UpsertCompanyInputSchema,
  GetCompanyInputSchema,
  ListCompaniesInputSchema,
  DeleteCompanyInputSchema,
  CompanyOutputSchema,
  CompanyArrayOutputSchema,
  DeleteResultSchema,
  type CreateCompanyInput,
  type UpdateCompanyInput,
  type UpsertCompanyInput,
  type GetCompanyInput,
  type ListCompaniesInput,
  type DeleteCompanyInput
} from './types'

/**
 * Helper to transform company result to output format
 * Converts Date objects to ISO strings for consistent API responses
 */
function toCompanyOutput(result: any) {
  return {
    id: result.id,
    organizationId: result.organizationId,
    name: result.name,
    domain: result.domain,
    linkedinUrl: result.linkedinUrl,
    website: result.website,
    numEmployees: result.numEmployees,
    foundedYear: result.foundedYear,
    locationCity: result.locationCity,
    locationState: result.locationState,
    category: result.category,
    categoryPain: result.categoryPain ?? null,
    segment: result.segment,
    processingState: result.processingState,
    pipelineStatus: null,
    enrichmentData: result.enrichmentData,
    tags: result.tags,
    source: result.source,
    batchId: result.batchId ?? null,
    status: result.status,
    createdAt: result.createdAt instanceof Date ? result.createdAt.toISOString() : result.createdAt,
    updatedAt: result.updatedAt instanceof Date ? result.updatedAt.toISOString() : result.updatedAt
  }
}

/**
 * Create a tool for creating new company records
 *
 * @returns Tool that creates a company
 *
 * @example
 * const tool = createAcqCompanyCreateTool()
 * const result = await tool.execute({
 *   input: { name: 'Acme Corp', domain: 'acme.com' },
 *   executionContext: { organizationId: 'org-123', ... }
 * })
 */
export function createAcqCompanyCreateTool(): Tool {
  return {
    name: 'acq_company_create',
    description: 'Create a new company record for lead tracking.',
    inputSchema: CreateCompanyInputSchema,
    outputSchema: CompanyOutputSchema,
    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 typedInput = input as CreateCompanyInput
      const result = await leadService.createCompany({
        organizationId: executionContext.organizationId,
        ...typedInput
      })

      return toCompanyOutput(result)
    }
  }
}

/**
 * Create a tool for updating existing company records
 *
 * @returns Tool that updates a company
 *
 * @example
 * const tool = createAcqCompanyUpdateTool()
 * const result = await tool.execute({
 *   input: { id: 'company-123', numEmployees: 500 },
 *   executionContext: { organizationId: 'org-123', ... }
 * })
 */
export function createAcqCompanyUpdateTool(): Tool {
  return {
    name: 'acq_company_update',
    description: 'Update an existing company record with new data (e.g., enrichment data, firmographics).',
    inputSchema: UpdateCompanyInputSchema,
    outputSchema: CompanyOutputSchema,
    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 typedInput = input as UpdateCompanyInput
      const { id, ...params } = typedInput
      const result = await leadService.updateCompany(id, params)

      return toCompanyOutput(result)
    }
  }
}

/**
 * Create a tool for upserting companies by domain
 * Creates new record if domain does not exist, otherwise updates existing
 *
 * @returns Tool that upserts a company
 *
 * @example
 * const tool = createAcqCompanyUpsertTool()
 * const result = await tool.execute({
 *   input: { name: 'Acme Corp', domain: 'acme.com' },
 *   executionContext: { organizationId: 'org-123', ... }
 * })
 */
export function createAcqCompanyUpsertTool(): Tool {
  return {
    name: 'acq_company_upsert',
    description: 'Upsert a company by domain. Creates new record if domain does not exist, otherwise updates existing.',
    inputSchema: UpsertCompanyInputSchema,
    outputSchema: CompanyOutputSchema,
    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 typedInput = input as UpsertCompanyInput
      const result = await leadService.upsertCompany({
        organizationId: executionContext.organizationId,
        ...typedInput
      })

      return toCompanyOutput(result)
    }
  }
}

/**
 * Create a tool for getting a single company by ID
 *
 * @returns Tool that retrieves a company
 *
 * @example
 * const tool = createAcqCompanyGetTool()
 * const result = await tool.execute({
 *   input: { id: 'company-123' },
 *   executionContext: { organizationId: 'org-123', ... }
 * })
 */
export function createAcqCompanyGetTool(): Tool {
  return {
    name: 'acq_company_get',
    description: 'Get a single company by ID.',
    inputSchema: GetCompanyInputSchema,
    outputSchema: CompanyOutputSchema.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 typedInput = input as GetCompanyInput
      const result = await leadService.getCompany(typedInput.id, executionContext.organizationId)
      return result ? toCompanyOutput(result) : null
    }
  }
}

/**
 * Create a tool for listing companies with optional filters
 *
 * @returns Tool that lists companies
 *
 * @example
 * const tool = createAcqCompanyListTool()
 * const result = await tool.execute({
 *   input: { segment: 'smb', category: 'saas' },
 *   executionContext: { organizationId: 'org-123', ... }
 * })
 */
export function createAcqCompanyListTool(): Tool {
  return {
    name: 'acq_company_list',
    description: 'List companies with optional filters for category, segment, or processing state.',
    inputSchema: ListCompaniesInputSchema,
    outputSchema: CompanyArrayOutputSchema,
    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 typedInput = input as ListCompaniesInput
      const results = await leadService.listCompanies(executionContext.organizationId, typedInput)
      return results.map(toCompanyOutput)
    }
  }
}

/**
 * Create a tool for deleting company records
 * Associated contacts will have their company_id set to null
 *
 * @returns Tool that deletes a company
 *
 * @example
 * const tool = createAcqCompanyDeleteTool()
 * const result = await tool.execute({
 *   input: { id: 'company-123' },
 *   executionContext: { organizationId: 'org-123', ... }
 * })
 */
export function createAcqCompanyDeleteTool(): Tool {
  return {
    name: 'acq_company_delete',
    description: 'Delete a company record. Associated contacts will have their company_id set to null.',
    inputSchema: DeleteCompanyInputSchema,
    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 typedInput = input as DeleteCompanyInput
      await leadService.deleteCompany(typedInput.id, executionContext.organizationId)
      return { success: true }
    }
  }
}
