import { ToolingError } from '../../../../../../types'
import type { ExecutionContext } from '../../../../../../../base/types'
import { withRetry, createHttpError, DEFAULT_RETRY_POLICY } from '../../../../../../../../../platform/resilience'
import type { AttioCredentials, CreateNoteParams, CreateNoteResult, AttioNoteResponse } from '../utils/types'

/**
 * Create a new note on an Attio record using native fetch API
 *
 * @param credentials - Attio API credentials (apiKey)
 * @param params - Note creation parameters
 * @param context - Execution context for logging
 * @returns Created note ID and success status
 * @throws ToolingError if note creation fails
 *
 * @example
 * // Create a discovery call note on a person
 * const note = await createNote(
 *   { apiKey: 'xxx' },
 *   {
 *     parentObject: 'people',
 *     parentRecordId: '891dcbfc-9141-415d-9b2a-2238a6cc012d',
 *     title: 'Discovery Call Notes - 2026-01-25',
 *     format: 'markdown',
 *     content: '## Summary\n\n- Key point 1\n- Key point 2'
 *   },
 *   context
 * )
 */
export async function createNote(
  credentials: AttioCredentials,
  params: CreateNoteParams,
  context?: ExecutionContext
): Promise<CreateNoteResult> {
  const { apiKey } = credentials
  const { parentObject, parentRecordId, title, format, content, createdAt } = params

  // Validate required parameters
  if (!apiKey) {
    throw new ToolingError('credentials_invalid', 'Attio API credentials must include apiKey', {
      integration: 'attio',
      method: 'createNote'
    })
  }

  if (!parentObject || !parentRecordId || !title || !format || !content) {
    throw new ToolingError(
      'validation_error',
      'parentObject, parentRecordId, title, format, and content are required',
      {
        integration: 'attio',
        method: 'createNote',
        params: { parentObject, parentRecordId, title, format }
      }
    )
  }

  // Validate format
  if (format !== 'plaintext' && format !== 'markdown') {
    throw new ToolingError('validation_error', 'format must be "plaintext" or "markdown"', {
      integration: 'attio',
      method: 'createNote',
      params: { format }
    })
  }

  // Build URL
  const url = 'https://api.attio.com/v2/notes'

  // Build request body
  const requestBody: {
    data: {
      parent_object: string
      parent_record_id: string
      title: string
      format: string
      content: string
      created_at?: string
    }
  } = {
    data: {
      parent_object: parentObject,
      parent_record_id: parentRecordId,
      title,
      format,
      content
    }
  }

  // Add optional createdAt
  if (createdAt) {
    requestBody.data.created_at = createdAt
  }

  try {
    // Execute with retry logic
    const response = await withRetry(async () => {
      const res = await fetch(url, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
          Accept: 'application/json'
        },
        body: JSON.stringify(requestBody)
      })

      // Handle HTTP errors
      if (!res.ok) {
        throw await createHttpError(res, {
          integration: 'attio',
          method: 'createNote',
          organizationId: context?.organizationId
        })
      }

      return res
    }, DEFAULT_RETRY_POLICY)

    // Parse response
    const result = (await response.json()) as AttioNoteResponse

    // Extract note ID from nested structure
    const noteId = result.data.id.note_id

    // Log success
    if (context?.logger) {
      context.logger.info(
        `[AttioAdapter] Note created: noteId=${noteId} parentObject=${parentObject} parentRecordId=${parentRecordId} executionId=${context.executionId}`
      )
    }

    // Return standardized result
    return {
      noteId,
      success: true
    }
  } catch (error) {
    // Re-throw ToolingError as-is
    if (error instanceof ToolingError) {
      throw error
    }

    // Wrap unknown errors
    throw new ToolingError('api_error', `Failed to create Attio note: ${(error as Error).message}`, {
      integration: 'attio',
      method: 'createNote',
      organizationId: context?.organizationId,
      params: { parentObject, parentRecordId, title },
      originalError: error
    })
  }
}
