/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */

import {DownloadablePluginDetails} from 'flipper-common';
import {State, Store} from '../reducers/index';
import {
  PluginDownloadStatus,
  pluginDownloadStarted,
  pluginDownloadFinished,
} from '../reducers/pluginDownloads';
import {sideEffect} from '../utils/sideEffect';
import {reportPlatformFailures, reportUsage} from 'flipper-common';
import {loadPlugin} from '../reducers/pluginManager';
import {showErrorNotification} from '../utils/notifications';
import {pluginInstalled} from '../reducers/plugins';
import {getAllClients} from '../reducers/connections';
import {getRenderHostInstance} from 'flipper-frontend-core';

export default (store: Store) => {
  sideEffect(
    store,
    {name: 'handlePluginDownloads', throttleMs: 1000, fireImmediately: true},
    (state) => state.pluginDownloads,
    (state, store) => {
      for (const download of Object.values(state)) {
        if (download.status === PluginDownloadStatus.QUEUED) {
          reportUsage(
            'plugin-auto-update:download',
            {
              version: download.plugin.version,
              startedByUser: download.startedByUser ? '1' : '0',
            },
            download.plugin.id,
          );
          reportPlatformFailures(
            handlePluginDownload(
              download.plugin,
              download.startedByUser,
              store,
            ),
            'plugin-auto-update:download',
          ).catch(() => {});
        }
      }
    },
  );
  return async () => {};
};

async function handlePluginDownload(
  plugin: DownloadablePluginDetails,
  startedByUser: boolean,
  store: Store,
) {
  const {title, version, downloadUrl} = plugin;
  const dispatch = store.dispatch;
  console.log(
    `Downloading plugin "${title}" v${version} from "${downloadUrl}".`,
  );
  try {
    dispatch(pluginDownloadStarted({plugin}));
    const installedPlugin = await getRenderHostInstance().flipperServer!.exec(
      'plugin-start-download',
      plugin,
    );
    dispatch(pluginInstalled(installedPlugin));
    if (pluginIsDisabledForAllConnectedClients(store.getState(), plugin)) {
      dispatch(
        loadPlugin({
          plugin: installedPlugin,
          enable: startedByUser,
          notifyIfFailed: startedByUser,
        }),
      );
    }
    console.log(
      `Successfully downloaded and installed plugin "${title}" v${version} from "${downloadUrl}".`,
    );
  } catch (error) {
    console.error(
      `Failed to download plugin "${title}" v${version} from "${downloadUrl}".`,
      error,
    );
    if (startedByUser) {
      showErrorNotification(
        `Failed to download plugin "${title}" v${version}.`,
        'Please check that you are on VPN/Lighthouse.',
      );
    }
    throw error;
  } finally {
    dispatch(pluginDownloadFinished({plugin}));
  }
}

function pluginIsDisabledForAllConnectedClients(
  state: State,
  plugin: DownloadablePluginDetails,
) {
  return (
    !state.plugins.clientPlugins.has(plugin.id) ||
    !getAllClients(state.connections).some((c) =>
      state.connections.enabledPlugins[c.query.app]?.includes(plugin.id),
    )
  );
}
