import {
  DedupeStrategy,
  Polling,
  pollingHelper,
} from '@activepieces/pieces-common';
import {
  createTrigger,
  TriggerStrategy,
  AppConnectionValueForAuthProperty,
} from '@activepieces/pieces-framework';
import dayjs from 'dayjs';
import { getNotionToken, NotionAuthValue, notionCommon } from '../common';
import { Client } from '@notionhq/client';
import { notionAuth } from '../auth';

export const newComment = createTrigger({
  auth: notionAuth,
  name: 'new_comment',
  displayName: 'New Comment',
  description:
    'Triggers whenever someone adds a new comment to a specific Notion page. Perfect for notifications, review workflows, or automated responses to team feedback.',
  aiMetadata: {
    description:
      'Fires when a new comment is posted on the selected Notion page, emitting the comment. Use to react to feedback or discussion activity on a specific page; requires read-comments capability on the integration.',
  },
  props: {
    page_id: notionCommon.page,
  },
  sampleData: {
    object: 'comment',
    id: '223805e9-774b-80b1-9194-001d0c8f56dd',
    parent: {
      type: 'page_id',
      page_id: '1d5805e9-774b-8071-80c0-ffcea9b13b94',
    },
    discussion_id: 'f1c805e9-774b-824f-8511-83edf6abbdda',
    created_time: '2025-07-01T07:19:00.000Z',
    last_edited_time: '2025-07-01T07:19:00.000Z',
    created_by: {
      object: 'user',
      id: '0f46d5cf-06ee-4350-8051-79ad10c898a6',
    },
    rich_text: [
      {
        type: 'text',
        text: {
          content: 'Good DX',
          link: null,
        },
        annotations: {
          bold: false,
          italic: false,
          strikethrough: false,
          underline: false,
          code: false,
          color: 'default',
        },
        plain_text: 'Good DX',
        href: null,
      },
    ],
    display_name: {
      type: 'integration',
      resolved_name: 'Activepieces',
    },
  },
  type: TriggerStrategy.POLLING,
  async test(ctx) {
    return await pollingHelper.test(polling, {
      auth: ctx.auth,
      store: ctx.store,
      propsValue: ctx.propsValue,
      files: ctx.files,
    });
  },
  async onEnable(ctx) {
    await pollingHelper.onEnable(polling, {
      auth: ctx.auth,
      store: ctx.store,
      propsValue: ctx.propsValue,
    });
  },
  async onDisable(ctx) {
    await pollingHelper.onDisable(polling, {
      auth: ctx.auth,
      store: ctx.store,
      propsValue: ctx.propsValue,
    });
  },
  async run(ctx) {
    return await pollingHelper.poll(polling, {
      auth: ctx.auth,
      store: ctx.store,
      propsValue: ctx.propsValue,
      files: ctx.files,
    });
  },
});

const polling: Polling<
  AppConnectionValueForAuthProperty<typeof notionAuth>,
  { page_id: string | undefined }
> = {
  strategy: DedupeStrategy.LAST_ITEM,
  items: async ({ auth, propsValue, lastItemId }) => {
    const lastItem = lastItemId as string;
    let lastCreatedDate: string | null;

    if (lastItem) {
      const lastUpdatedEpochMS = Number(lastItem.split('|')[1]);
      lastCreatedDate = dayjs(lastUpdatedEpochMS).toISOString();
    } else {
      lastCreatedDate = lastItem;
    }

    const items = await getComments(
      auth,
      propsValue.page_id || '',
      lastCreatedDate
    );
    return items.map((item) => {
      const comment = item as { created_time: string; id: string };
      return {
        id: comment.id + '|' + dayjs(comment.created_time).valueOf(),
        data: item,
      };
    });
  },
};

const getComments = async (
  authentication: NotionAuthValue,
  page_id: string,
  startDate: string | null
) => {
  const notion = new Client({
    auth: getNotionToken(authentication),
    notionVersion: '2022-02-22',
  });

  let cursor;
  let hasMore = true;
  let shouldContinue = true;

  const results = [];

  do {
    try {
      const response = await notion.comments.list({
        start_cursor: cursor,
        block_id: page_id,
      });

      hasMore = response.has_more;
      cursor = response.next_cursor ?? undefined;

      for (const comment of response.results) {
        if (
          startDate &&
          !dayjs(comment.created_time).isAfter(dayjs(startDate))
        ) {
          shouldContinue = false;
          break;
        }
        results.push(comment);
      }
    } catch (error) {
      if ((error as Error).message?.includes('permissions')) {
        throw new Error(
          'Integration lacks required "read comments" capability.'
        );
      }
      throw error;
    }
  } while (hasMore && shouldContinue);

  return results.sort(
    (a: { created_time: string }, b: { created_time: string }) =>
      dayjs(b.created_time).valueOf() - dayjs(a.created_time).valueOf()
  );
};
