import { useApolloClient } from "@apollo/client";
import * as FileSystem from "expo-file-system";
import * as MediaLibrary from "expo-media-library";
import _ from "lodash";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  ActivityIndicator,
  Alert,
  Modal,
  ScrollView,
  StyleSheet,
  Text,
  View,
} from "react-native";
import { ProgressBar } from "react-native-paper";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.analytics";
import { GET_DOC_SIZE_TOTALS } from "../../graphql/documents.queries";
import {
  selectCurrentCameraJobId,
  selectDeleteAfterUpload,
} from "../../redux/app/app.selectors";
import {
  selectBodyshop,
  selectCurrentUser,
} from "../../redux/user/user.selectors";
import { formatBytes, handleUpload } from "../../util/document-upload.utility";

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  bodyshop: selectBodyshop,
  selectedCameraJobId: selectCurrentCameraJobId,
  deleteAfterUpload: selectDeleteAfterUpload,
});

export default connect(mapStateToProps, null)(UploadProgress);

export function UploadProgress({
  currentUser,
  bodyshop,
  selectedCameraJobId,
  deleteAfterUpload,
  uploads,
  forceRerender,
}) {
  const [progress, setProgress] = useState({
    loading: false,
    uploadInProgress: false,
    speed: 0,
    files: {}, //uri is the key, value is progress
  });

  const client = useApolloClient();

  const { t } = useTranslation();

  useEffect(() => {
    //Set the state of uploads to do.

    if (uploads) onDone(uploads);
  }, [uploads]);

  //if (!uploads) return null;

  function handleOnSuccess(id) {
    logImEXEvent("imexmobile_successful_upload");

    setProgress((progress) => ({
      ...progress,
      action: t("mediabrowser.labels.converting"),
      files: {
        ...progress.files,
        [id]: {
          ...progress.files[id],
          action: t("mediabrowser.labels.converting"),
        },
      },
      // });
    }));
  }

  function handleOnProgress(uri, percent, loaded) {
    setProgress((progress) => ({
      ...progress,
      speed: loaded - progress.files[uri].loaded,
      action:
        percent === 1
          ? t("mediabrowser.labels.converting")
          : t("mediabrowser.labels.uploading"),
      files: {
        ...progress.files,
        [uri]: {
          ...progress.files[uri],
          percent,
          action:
            percent === 1
              ? t("mediabrowser.labels.converting")
              : t("mediabrowser.labels.uploading"),
          loaded: loaded,
        },
      },
    }));
  }
  function handleOnError(...props) {
    logImEXEvent("imexmobile_upload_documents_error", { props });
  }

  const onDone = async (data) => {
    //Validate to make sure the totals for the file sizes do not exceed the total on the job.
    setProgress({
      files: _.keyBy(data, "id"),
      loading: true,
      uploadInProgress: true,
    });

    if (selectedCameraJobId !== "temp") {
      const queryData = await client.query({
        query: GET_DOC_SIZE_TOTALS,
        fetchPolicy: "network-only",
        variables: {
          jobId: selectedCameraJobId,
        },
      });
      const totalOfUploads = await data.reduce(async (acc, val) => {
        //Get the size of the file based on URI.
        const info = await FileSystem.getInfoAsync(val.uri, { size: true });
        return (await acc) + info.size;
      }, 0);

      if (
        bodyshop.jobsizelimit -
          queryData.data.documents_aggregate.aggregate.sum.size <=
        totalOfUploads
      ) {
        //No more room... abandon ship.
        setProgress((progress) => ({
          ...progress,
          speed: 0,
          action: null,
          loading: false,
          uploadInProgress: false,
        }));
        Alert.alert(
          t("mediabrowser.labels.storageexceeded_title"),
          t("mediabrowser.labels.storageexceeded")
        );
        return;
      }
    }

    //Sequentially await the proms.
    for (const p of data) {
      let filename;
      filename = p.filename || p.uri.split("/").pop();

      await handleUpload(
        {
          filename,
          mediaId: p.id,
          onError: handleOnError,
          onProgress: ({ percent, loaded }) =>
            handleOnProgress(p.id, percent, loaded),
          onSuccess: () => handleOnSuccess(p.id),
        },
        {
          bodyshop: bodyshop,
          jobId: selectedCameraJobId !== "temp" ? selectedCameraJobId : null,
          uploaded_by: currentUser.email,
          photo: p,
        }
      );

      //Set the state to mark that it's done.
      setProgress((progress) => ({
        ...progress,
        action: null,
        speed: 0,
        files: {
          ...progress.files,
          [p.id]: {
            ...progress.files[p.id],
            action: null,
          },
        },
      }));
    }

    if (deleteAfterUpload) {
      try {
        await MediaLibrary.deleteAssetsAsync(Object.keys(progress.files));
      } catch (error) {
        console.log("Unable to delete picture.", error);
      }
    }
    setProgress({
      loading: false,
      speed: 0,
      action: null,
      uploadInProgress: false,
      files: {}, //uri is the key, value is progress
    });

    forceRerender();
  };

  return (
    <Modal
      visible={progress.uploadInProgress}
      animationType="slide"
      transparent={true}
      onRequestClose={() => {
        Alert.alert("Modal has been closed.");
      }}
    >
      <View style={styles.modal}>
        {progress.loading && <ActivityIndicator />}
        {progress.action && (
          <Text>{`${progress.action} ${
            (progress.speed !== 0 || !progress.speed) &&
            `- ${formatBytes(progress.speed)}/sec`
          }`}</Text>
        )}
        <ScrollView contentContainerStyle={styles.centeredView}>
          {Object.keys(progress.files).map((key) => (
            <View key={progress.files[key].id} style={styles.progressItem}>
              <Text style={styles.progressText}>
                {progress.files[key].filename}
              </Text>
              <View style={styles.progressBarContainer}>
                <ProgressBar
                  progress={progress.files[key].percent}
                  style={styles.progress}
                  color={progress.files[key].percent === 1 ? "green" : "blue"}
                />
              </View>
            </View>
          ))}
        </ScrollView>
      </View>
    </Modal>
  );
}
const styles = StyleSheet.create({
  modal: {
    flex: 1,
    marginTop: 50,
    marginBottom: 60,
    marginLeft: 20,
    marginRight: 20,
    backgroundColor: "white",
    borderRadius: 20,
    padding: 18,
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    elevation: 5,
  },
  centeredView: {
    flex: 1,
    // justifyContent: "center",
    // alignItems: "center",
    marginTop: 22,
  },
  progressItem: {
    display: "flex",
    flexDirection: "row",
    alignItems: "center",
    marginBottom: 12,
    marginLeft: 12,
    marginRight: 12,
  },
  progressText: {
    flex: 1,
  },
  progressBarContainer: {
    flex: 3,
    marginLeft: 12,
    marginRight: 12,
  },
});
