import type { SlackGetThreadParams, SlackGetThreadResponse } from '@/tools/slack/types'
import { MESSAGE_OUTPUT_PROPERTIES } from '@/tools/slack/types'
import type { ToolConfig } from '@/tools/types'

export const slackGetThreadTool: ToolConfig<SlackGetThreadParams, SlackGetThreadResponse> = {
  id: 'slack_get_thread',
  name: 'Slack Get Thread',
  description:
    'Retrieve an entire thread including the parent message and all replies. Useful for getting full conversation context.',
  version: '1.0.0',

  oauth: {
    required: true,
    provider: 'slack',
  },

  params: {
    authMethod: {
      type: 'string',
      required: false,
      visibility: 'user-only',
      description: 'Authentication method: oauth or bot_token',
    },
    botToken: {
      type: 'string',
      required: false,
      visibility: 'user-only',
      description: 'Bot token for Custom Bot',
    },
    accessToken: {
      type: 'string',
      required: false,
      visibility: 'hidden',
      description: 'OAuth access token or bot token for Slack API',
    },
    channel: {
      type: 'string',
      required: true,
      visibility: 'user-or-llm',
      description: 'Slack channel ID (e.g., C1234567890)',
    },
    threadTs: {
      type: 'string',
      required: true,
      visibility: 'user-or-llm',
      description: 'Thread timestamp (thread_ts) to retrieve (e.g., 1405894322.002768)',
    },
    limit: {
      type: 'number',
      required: false,
      visibility: 'user-or-llm',
      description: 'Maximum number of messages to return (default: 100, max: 200)',
    },
  },

  request: {
    url: (params: SlackGetThreadParams) => {
      const url = new URL('https://slack.com/api/conversations.replies')
      url.searchParams.append('channel', params.channel?.trim() ?? '')
      url.searchParams.append('ts', params.threadTs?.trim() ?? '')
      url.searchParams.append('inclusive', 'true')
      const limit = params.limit ? Math.min(Number(params.limit), 200) : 100
      url.searchParams.append('limit', String(limit))
      return url.toString()
    },
    method: 'GET',
    headers: (params: SlackGetThreadParams) => ({
      'Content-Type': 'application/json',
      Authorization: `Bearer ${params.accessToken || params.botToken}`,
    }),
  },

  transformResponse: async (response: Response) => {
    const data = await response.json()

    if (!data.ok) {
      if (data.error === 'missing_scope') {
        throw new Error(
          'Missing required permissions. Please reconnect your Slack account with the necessary scopes (channels:history, groups:history, im:history, mpim:history).'
        )
      }
      if (data.error === 'invalid_auth') {
        throw new Error('Invalid authentication. Please check your Slack credentials.')
      }
      if (data.error === 'channel_not_found') {
        throw new Error('Channel not found. Please check the channel ID.')
      }
      if (data.error === 'thread_not_found') {
        throw new Error('Thread not found. Please check the thread timestamp.')
      }
      throw new Error(data.error || 'Failed to get thread from Slack')
    }

    const rawMessages = data.messages || []
    if (rawMessages.length === 0) {
      throw new Error('Thread not found')
    }

    const messages = rawMessages.map((msg: any) => ({
      type: msg.type ?? 'message',
      ts: msg.ts,
      text: msg.text ?? '',
      user: msg.user ?? null,
      bot_id: msg.bot_id ?? null,
      username: msg.username ?? null,
      channel: msg.channel ?? null,
      team: msg.team ?? null,
      thread_ts: msg.thread_ts ?? null,
      parent_user_id: msg.parent_user_id ?? null,
      reply_count: msg.reply_count ?? null,
      reply_users_count: msg.reply_users_count ?? null,
      latest_reply: msg.latest_reply ?? null,
      subscribed: msg.subscribed ?? null,
      last_read: msg.last_read ?? null,
      unread_count: msg.unread_count ?? null,
      subtype: msg.subtype ?? null,
      reactions: msg.reactions ?? [],
      is_starred: msg.is_starred ?? false,
      pinned_to: msg.pinned_to ?? [],
      files: (msg.files ?? []).map((f: any) => ({
        id: f.id,
        name: f.name,
        mimetype: f.mimetype,
        size: f.size,
        url_private: f.url_private ?? null,
        permalink: f.permalink ?? null,
        mode: f.mode ?? null,
      })),
      attachments: msg.attachments ?? [],
      blocks: msg.blocks ?? [],
      edited: msg.edited ?? null,
      permalink: msg.permalink ?? null,
    }))

    // First message is always the parent
    const parentMessage = messages[0]
    // Remaining messages are replies
    const replies = messages.slice(1)

    return {
      success: true,
      output: {
        parentMessage,
        replies,
        messages,
        replyCount: replies.length,
        hasMore: data.has_more ?? false,
      },
    }
  },

  outputs: {
    parentMessage: {
      type: 'object',
      description: 'The thread parent message',
      properties: MESSAGE_OUTPUT_PROPERTIES,
    },
    replies: {
      type: 'array',
      description: 'Array of reply messages in the thread (excluding the parent)',
      items: {
        type: 'object',
        properties: MESSAGE_OUTPUT_PROPERTIES,
      },
    },
    messages: {
      type: 'array',
      description: 'All messages in the thread (parent + replies) in chronological order',
      items: {
        type: 'object',
        properties: MESSAGE_OUTPUT_PROPERTIES,
      },
    },
    replyCount: {
      type: 'number',
      description: 'Number of replies returned in this response',
    },
    hasMore: {
      type: 'boolean',
      description: 'Whether there are more messages in the thread (pagination needed)',
    },
  },
}
