import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { createAction, Property, DynamicPropsValue } from '@activepieces/pieces-framework';
import { getApiEndpoint } from '../common';
import { returningAiAuth } from '../auth';

/**
 * This action allows you to send messages to any accessible channel as a specific user.
 * The message will appear as if the selected user posted it directly.
 * 
 * When using this action, you need to provide:
 * 1. The username or email of the sender (who will appear to have sent the message)
 * 2. The channel where the message will be posted
 * 3. The content of the message
 * 
 * The API will handle posting the message to the specified channel with the appropriate sender.
 * 
 * @example
 * ```
 * // Example response
 * {
 *   "status": "success",
 *   "message": "Message sent successfully"
 * }
 * ```
 * 
 * @link https://dev.returning.ai/api-15023884
 */
export const sendMessage = createAction({
  auth:returningAiAuth,
  name: 'sendMessage',
  displayName: 'Send Channel Message',
  description: 'Posts a message to a specified channel as a chosen user',
  audience: 'both',
  aiMetadata: { description: 'Posts a new message to a Returning.ai channel on behalf of a given user (identified by username or email), so the message appears as if that user sent it. Use to broadcast or announce content in a channel; supply message text, image URLs, or both (at least one is required), and for forum-type channels a topic ID is also required. Not idempotent: each call posts a new message.', idempotent: false },
  props: {
    description: Property.MarkDown({
      value:
        'This action allows you to send messages to any accessible channel as a specific user. The message will appear as if the selected user posted it directly.',
    }),
    user: Property.ShortText({
      displayName: 'Sender (Username or email)',
      description: 'The user account that will send the message',
      required: true,
    }),
    channel: Property.Dropdown({
      auth: returningAiAuth,
      displayName: 'Channel',
      description: 'The channel where the message will be posted',
      required: true,
      refreshers: ['auth'],
      options: async ({ auth }) => {
        const authToken = auth?.secret_text;

        if (!authToken) {
          return {
            disabled: true,
            options: [],
            placeholder: 'Please authenticate first',
          };
        }

        /**
         * Fetches the list of available channels from the Returning.ai API
         * @link https://dev.returning.ai/api-15023851
         */
        const response = await httpClient.sendRequest({
          method: HttpMethod.GET,
          url: `${getApiEndpoint(authToken)}/apis/v1/channels`,
          headers: {
            Authorization: `Bearer ${authToken.includes(':') ? authToken.split(':')[1] : authToken}`,
          },
        });

        if (response.body.status === 'success') {
          return {
            options: response.body.data.map(
              (channel: {
                _id: string;
                topic: string;
                channelType: string;
              }) => ({
                label: channel.topic,
                value: JSON.stringify({
                  id: channel._id,
                  type: channel.channelType,
                }),
              })
            ),
          };
        } else {
          return {
            disabled: true,
            options: [],
            placeholder: response.body.message,
          };
        }
      },
    }),
    dynamicFields: Property.DynamicProperties({
      auth: returningAiAuth,
      displayName: 'Channel Fields',
      description: 'Additional fields based on channel type',
      required: true,
      refreshers: ['channel'],
      props: async ({ channel }) => {
        const properties: Record<string, any> = {};

        if (channel) {
          const channelData = JSON.parse(channel as unknown as string);
          if (channelData.type === 'forum') {
            properties['topicId'] = Property.ShortText({
              displayName: 'Topic ID',
              description:
                'The topic ID of the forum channel where the message will be posted',
              required: true,
            });
          }
        }

        return properties;
      },
    }),
    message: Property.LongText({
      displayName: 'Message',
      description: 'The message to be posted (optional if images are provided)',
      required: false,
    }),
    images: Property.Array({
      displayName: 'Images',
      description: 'Add one image URL per entry (e.g., https://example.com/image1.png)',
      required: false,
    }),
  },
  async run({ propsValue, auth }) {
    const authToken = auth.secret_text;
    const channelData = JSON.parse(propsValue.channel as string);
    const imagesInput = propsValue.images as unknown as string[];
    const dynamicFields = propsValue.dynamicFields as DynamicPropsValue;

    // Parse comma-separated image URLs
    const imageUrls = imagesInput
      ? imagesInput
          .map((url:string) => url.trim())
          .filter((url:string) => url.length > 0)
      : [];

    // Validate that at least message or images is provided
    const hasMessage = propsValue.message && propsValue.message.trim().length > 0;
    const hasImages = imageUrls.length > 0;

    if (!hasMessage && !hasImages) {
      return {
        status: 'error',
        message: 'Either "message" (text content) or "images" (comma-separated URLs) must be provided.',
        detail: 'Both fields are empty or missing.',
      };
    }

    const response = await httpClient.sendRequest({
      method: HttpMethod.POST,
      url: `${getApiEndpoint(authToken)}/apis/v1/messages/send`,
      headers: {
        Authorization: `Bearer ${authToken.includes(':') ? authToken.split(':')[1] : authToken}`,
      },
      body: {
        channelId: channelData.id,
        message: propsValue.message,
        sender: propsValue.user,
        ...(channelData.type === 'forum' && {
          forumTopicId: dynamicFields['topicId'],
        }),
        ...(hasImages && {
          images: imageUrls,
        }),
      },
    });

    return response.body;
  },
});
