// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import { v4 as generateUuid } from 'uuid';

import type { AttachmentType } from '../types/Attachment';
import type { MessageAttributesType } from '../model-types.d';
import type { MessageModel } from '../models/messages';
import * as log from '../logging/log';
import { IMAGE_JPEG } from '../types/MIME';
import { ReadStatus } from '../messages/MessageReadStatus';
import { SeenStatus } from '../MessageSeenStatus';
import { findAndDeleteOnboardingStoryIfExists } from './findAndDeleteOnboardingStoryIfExists';
import { saveNewMessageBatcher } from './messageBatcher';
import { strictAssert } from './assert';
import { incrementMessageCounter } from './incrementMessageCounter';

// First, this function is meant to be run after a storage service sync

// * If onboarding story has been viewed and it's downloaded on this device,
//   delete & return.
// * Check if we've already downloaded the onboarding story.
// * Download onboarding story, create db entry, mark as downloaded.
// * If story has been viewed mark as viewed on AccountRecord.
// * If we viewed it >24 hours ago, delete.
export async function downloadOnboardingStory(): Promise<void> {
  const { server } = window.textsecure;

  strictAssert(server, 'server not initialized');

  const hasViewedOnboardingStory = window.storage.get(
    'hasViewedOnboardingStory'
  );

  if (hasViewedOnboardingStory) {
    await findAndDeleteOnboardingStoryIfExists();
    return;
  }

  const existingOnboardingStoryMessageIds = window.storage.get(
    'existingOnboardingStoryMessageIds'
  );

  if (existingOnboardingStoryMessageIds) {
    log.info('downloadOnboardingStory: has existingOnboardingStoryMessageIds');
    return;
  }

  const userLocale = window.i18n.getLocale();

  const manifest = await server.getOnboardingStoryManifest();

  log.info('downloadOnboardingStory: got manifest version:', manifest.version);

  const imageFilenames =
    userLocale in manifest.languages
      ? manifest.languages[userLocale]
      : manifest.languages.en;

  const imageBuffers = await server.downloadOnboardingStories(
    manifest.version,
    imageFilenames
  );

  log.info('downloadOnboardingStory: downloaded stories:', imageBuffers.length);

  const attachments: Array<AttachmentType> = await Promise.all(
    imageBuffers.map(data => {
      const attachment: AttachmentType = {
        contentType: IMAGE_JPEG,
        data,
        size: data.byteLength,
      };

      return window.Signal.Migrations.processNewAttachment(attachment);
    })
  );

  log.info('downloadOnboardingStory: getting signal conversation');
  const signalConversation =
    await window.ConversationController.getOrCreateSignalConversation();

  const storyMessages: Array<MessageModel> = attachments.map(
    (attachment, index) => {
      const timestamp = Date.now() + index;

      const partialMessage: MessageAttributesType = {
        attachments: [attachment],
        canReplyToStory: false,
        conversationId: signalConversation.id,
        id: generateUuid(),
        readStatus: ReadStatus.Unread,
        received_at: incrementMessageCounter(),
        received_at_ms: timestamp,
        seenStatus: SeenStatus.Unseen,
        sent_at: timestamp,
        serverTimestamp: timestamp,
        sourceDevice: 1,
        sourceServiceId: signalConversation.getServiceId(),
        timestamp,
        type: 'story',
      };
      return new window.Whisper.Message(partialMessage);
    }
  );

  await Promise.all(
    storyMessages.map(message => saveNewMessageBatcher.add(message.attributes))
  );

  // Sync to redux
  storyMessages.forEach(message => {
    message.trigger('change');
  });

  await window.storage.put(
    'existingOnboardingStoryMessageIds',
    storyMessages.map(message => message.id)
  );

  log.info('downloadOnboardingStory: done');
}