/**
 * Platform Storage Tools
 *
 * Factory functions for creating storage tools that interact with
 * Supabase Storage for org-scoped file management.
 *
 * Usage:
 * ```typescript
 * const uploadTool = createStorageUploadTool({
 *   name: 'save_proposal',
 *   description: 'Save generated proposal PDF to storage'
 * })
 *
 * const signedUrlTool = createStorageSignedUrlTool({
 *   name: 'get_proposal_url',
 *   description: 'Get signed URL for proposal download'
 * })
 * ```
 */

import type { Tool, ToolExecutionOptions } from '../../types'
import { serviceUnavailable } from '../../types'
import { getToolServices } from '../../registry'
import {
  StorageUploadInputSchema,
  StorageUploadOutputSchema,
  StorageSignedUrlInputSchema,
  StorageSignedUrlOutputSchema,
  StorageDownloadInputSchema,
  StorageDownloadOutputSchema,
  StorageDeleteInputSchema,
  StorageDeleteOutputSchema,
  StorageListInputSchema,
  StorageListOutputSchema,
  type StorageUploadInput,
  type StorageUploadOutput,
  type StorageSignedUrlInput,
  type StorageSignedUrlOutput,
  type StorageDownloadInput,
  type StorageDownloadOutput,
  type StorageDeleteInput,
  type StorageDeleteOutput,
  type StorageListInput,
  type StorageListOutput,
  type StorageToolConfig
} from './types'

/**
 * Create storage upload tool for workflows/agents
 *
 * @param config - Tool configuration (name, description)
 * @returns Tool that uploads files to org-scoped storage
 *
 * @example
 * const uploadTool = createStorageUploadTool({
 *   name: 'save_proposal',
 *   description: 'Save generated proposal PDF to storage'
 * })
 *
 * // In agent execution:
 * await uploadTool.execute({
 *   input: {
 *     bucket: 'acquisition',
 *     path: 'proposals/deal-123/proposal.pdf',
 *     content: base64EncodedPdf,
 *     contentType: 'application/pdf'
 *   },
 *   executionContext: context
 * })
 */
export function createStorageUploadTool(config: StorageToolConfig): Tool {
  return {
    name: config.name,
    description: config.description,
    inputSchema: StorageUploadInputSchema,
    outputSchema: StorageUploadOutputSchema,

    async execute(options: ToolExecutionOptions): Promise<StorageUploadOutput> {
      if (!options.executionContext) {
        throw serviceUnavailable('ExecutionContext', { tool: config.name, reason: 'organizationId required for multi-tenant isolation' })
      }

      const { storageService } = getToolServices()
      if (!storageService) {
        throw serviceUnavailable('StorageService', {
          message: 'Ensure toolServicesRegistry.initialize() was called in apps/api/src/main.ts',
          tool: config.name
        })
      }

      const input = options.input as StorageUploadInput
      const buffer = Buffer.from(input.content, 'base64')

      const result = await storageService.upload({
        organizationId: options.executionContext.organizationId,
        bucket: input.bucket,
        path: input.path,
        file: buffer,
        contentType: input.contentType,
        upsert: input.upsert
      })

      return {
        success: true,
        path: result.path,
        fullPath: result.fullPath
      }
    }
  }
}

/**
 * Create storage signed URL tool for workflows/agents
 *
 * @param config - Tool configuration (name, description)
 * @returns Tool that creates signed URLs for temporary file access
 *
 * @example
 * const signedUrlTool = createStorageSignedUrlTool({
 *   name: 'get_proposal_url',
 *   description: 'Get signed URL for proposal download'
 * })
 *
 * // In agent execution:
 * await signedUrlTool.execute({
 *   input: {
 *     bucket: 'acquisition',
 *     path: 'proposals/deal-123/proposal.pdf',
 *     expiresIn: 604800  // 7 days
 *   },
 *   executionContext: context
 * })
 */
export function createStorageSignedUrlTool(config: StorageToolConfig): Tool {
  return {
    name: config.name,
    description: config.description,
    inputSchema: StorageSignedUrlInputSchema,
    outputSchema: StorageSignedUrlOutputSchema,

    async execute(options: ToolExecutionOptions): Promise<StorageSignedUrlOutput> {
      if (!options.executionContext) {
        throw serviceUnavailable('ExecutionContext', { tool: config.name, reason: 'organizationId required for multi-tenant isolation' })
      }

      const { storageService } = getToolServices()
      if (!storageService) {
        throw serviceUnavailable('StorageService', {
          message: 'Ensure toolServicesRegistry.initialize() was called in apps/api/src/main.ts',
          tool: config.name
        })
      }

      const input = options.input as StorageSignedUrlInput

      const result = await storageService.createSignedUrl({
        organizationId: options.executionContext.organizationId,
        bucket: input.bucket,
        path: input.path,
        expiresIn: input.expiresIn
      })

      return {
        success: true,
        signedUrl: result.signedUrl,
        expiresAt: result.expiresAt.toISOString()
      }
    }
  }
}

/**
 * Create storage download tool for workflows/agents
 *
 * @param config - Tool configuration (name, description)
 * @returns Tool that downloads files from org-scoped storage
 *
 * @example
 * const downloadTool = createStorageDownloadTool({
 *   name: 'get_proposal_content',
 *   description: 'Download proposal PDF content'
 * })
 *
 * // In agent execution:
 * await downloadTool.execute({
 *   input: {
 *     bucket: 'acquisition',
 *     path: 'proposals/deal-123/proposal.pdf'
 *   },
 *   executionContext: context
 * })
 */
export function createStorageDownloadTool(config: StorageToolConfig): Tool {
  return {
    name: config.name,
    description: config.description,
    inputSchema: StorageDownloadInputSchema,
    outputSchema: StorageDownloadOutputSchema,

    async execute(options: ToolExecutionOptions): Promise<StorageDownloadOutput> {
      if (!options.executionContext) {
        throw serviceUnavailable('ExecutionContext', { tool: config.name, reason: 'organizationId required for multi-tenant isolation' })
      }

      const { storageService } = getToolServices()
      if (!storageService) {
        throw serviceUnavailable('StorageService', {
          message: 'Ensure toolServicesRegistry.initialize() was called in apps/api/src/main.ts',
          tool: config.name
        })
      }

      const input = options.input as StorageDownloadInput

      const blob = await storageService.download({
        organizationId: options.executionContext.organizationId,
        bucket: input.bucket,
        path: input.path
      })

      // Convert blob to base64
      const arrayBuffer = await blob.arrayBuffer()
      const content = Buffer.from(arrayBuffer).toString('base64')

      return {
        success: true,
        content,
        contentType: blob.type || undefined
      }
    }
  }
}

/**
 * Create storage delete tool for workflows/agents
 *
 * @param config - Tool configuration (name, description)
 * @returns Tool that deletes files from org-scoped storage
 *
 * @example
 * const deleteTool = createStorageDeleteTool({
 *   name: 'remove_draft',
 *   description: 'Delete draft proposal file'
 * })
 *
 * // In agent execution:
 * await deleteTool.execute({
 *   input: {
 *     bucket: 'acquisition',
 *     path: 'proposals/deal-123/draft.pdf'
 *   },
 *   executionContext: context
 * })
 */
export function createStorageDeleteTool(config: StorageToolConfig): Tool {
  return {
    name: config.name,
    description: config.description,
    inputSchema: StorageDeleteInputSchema,
    outputSchema: StorageDeleteOutputSchema,

    async execute(options: ToolExecutionOptions): Promise<StorageDeleteOutput> {
      if (!options.executionContext) {
        throw serviceUnavailable('ExecutionContext', { tool: config.name, reason: 'organizationId required for multi-tenant isolation' })
      }

      const { storageService } = getToolServices()
      if (!storageService) {
        throw serviceUnavailable('StorageService', {
          message: 'Ensure toolServicesRegistry.initialize() was called in apps/api/src/main.ts',
          tool: config.name
        })
      }

      const input = options.input as StorageDeleteInput

      await storageService.delete({
        organizationId: options.executionContext.organizationId,
        bucket: input.bucket,
        path: input.path
      })

      return {
        success: true
      }
    }
  }
}

/**
 * Create storage list tool for workflows/agents
 *
 * @param config - Tool configuration (name, description)
 * @returns Tool that lists files in org-scoped storage
 *
 * @example
 * const listTool = createStorageListTool({
 *   name: 'list_proposals',
 *   description: 'List all proposals for a deal'
 * })
 *
 * // In agent execution:
 * await listTool.execute({
 *   input: {
 *     bucket: 'acquisition',
 *     prefix: 'proposals/deal-123/'
 *   },
 *   executionContext: context
 * })
 */
export function createStorageListTool(config: StorageToolConfig): Tool {
  return {
    name: config.name,
    description: config.description,
    inputSchema: StorageListInputSchema,
    outputSchema: StorageListOutputSchema,

    async execute(options: ToolExecutionOptions): Promise<StorageListOutput> {
      if (!options.executionContext) {
        throw serviceUnavailable('ExecutionContext', { tool: config.name, reason: 'organizationId required for multi-tenant isolation' })
      }

      const { storageService } = getToolServices()
      if (!storageService) {
        throw serviceUnavailable('StorageService', {
          message: 'Ensure toolServicesRegistry.initialize() was called in apps/api/src/main.ts',
          tool: config.name
        })
      }

      const input = options.input as StorageListInput

      const files = await storageService.list({
        organizationId: options.executionContext.organizationId,
        bucket: input.bucket,
        prefix: input.prefix
      })

      return {
        success: true,
        files
      }
    }
  }
}

// Re-export types for consumers
export {
  StorageUploadInputSchema,
  StorageUploadOutputSchema,
  StorageSignedUrlInputSchema,
  StorageSignedUrlOutputSchema,
  StorageDownloadInputSchema,
  StorageDownloadOutputSchema,
  StorageDeleteInputSchema,
  StorageDeleteOutputSchema,
  StorageListInputSchema,
  StorageListOutputSchema,
  type StorageUploadInput,
  type StorageUploadOutput,
  type StorageSignedUrlInput,
  type StorageSignedUrlOutput,
  type StorageDownloadInput,
  type StorageDownloadOutput,
  type StorageDeleteInput,
  type StorageDeleteOutput,
  type StorageListInput,
  type StorageListOutput,
  type StorageToolConfig
} from './types'
