import { View, Text, StyleSheet, FlatList, Image } from "react-native";
import React, { useState, useEffect, useReducer } from "react";
import { ProgressBar, ActivityIndicator } from "react-native-paper";
import style from "react-native-digitcamera/src/common/CommonStyle";
import ActivityView from "./ActivityView";
import Database from "../../../../../../Components/common/DAsyncStorage";
import store from "../../../redux/store";
import { findFailureAndReset } from "react-native-digitcamera/src/Screens/SilentUploadV2/DatabaseHelpers";
const actionTypes = {
  PUSH_INPROGRESS_ACTIVITY: "PUSH_INPROGRESS_ACTIVITY",
  REPLACE_INPROGRESS_ACTIVITY: "REPLACE_INPROGRESS_ACTIVITY",
  UPDATE_INPROGRESS_ACTIVITIES: "UPDATE_INPROGRESS_ACTIVITIES",
  RESET_INPROGRESS_ACTIVITIES: "UPDATE_INPROGRESS_ACTIVITIES",
  ADD_SERVICE_FAILURE_INPROGRESS_ACTIVITY:
    "ADD_SERVICE_FAILURE_INPROGRESS_ACTIVITY",
};

const actions = {
  update: (payload) => {
    return {
      type: actionTypes.UPDATE_INPROGRESS_ACTIVITIES,
      payload: payload,
    };
  },
  push: (payload) => {
    return {
      type: actionTypes.PUSH_INPROGRESS_ACTIVITY,
      payload: payload,
    };
  },
  replace: (payload) => {
    return {
      type: actionTypes.REPLACE_INPROGRESS_ACTIVITY,
      payload: payload,
    };
  },
  reset: () => {
    return {
      type: actionTypes.RESET_INPROGRESS_ACTIVITIES,
    };
  },
  addServiceFailure: (payload) => {
    return {
      type: actionTypes.ADD_SERVICE_FAILURE_INPROGRESS_ACTIVITY,
      payload: payload,
    };
  },
};

const intialState = {
  mInProgressActivities: [],
  serviceFailure: {},
  loading: true,
};

const resetState = {
  mInProgressActivities: [],
};

const getProgress = (sumOfProgress, totalDocuments) => {
  if (sumOfProgress && totalDocuments) {
    const result = (sumOfProgress / totalDocuments) * 0.01;
    return parseFloat(result.toFixed(2));
  }
  return 0;
};

const createProgressObjects = (dUploadProgress, dispatcher) => {
  const dProgressMap = {};
  const dLengthMap = {};
  const dTimeMap = {};
  const dSpeedMap = {};

  for (let itx in dUploadProgress) {
    const activityId = itx.split("_")[0];
    dProgressMap[activityId] = 0;
    dLengthMap[activityId] = 0;
    dTimeMap[activityId] = 0;
    dSpeedMap[activityId] = 0;
  }

  for (let itx in dUploadProgress) {
    const activityId = itx.split("_")[0];
    if (itx.includes(activityId)) {
      dLengthMap[activityId] += 1;
      dProgressMap[activityId] += dUploadProgress[itx].progress;
      dTimeMap[activityId] += dUploadProgress[itx].secondsRemaining;
      dSpeedMap[activityId] += dUploadProgress[itx].uploadSpeed;
    }
  }

  for (let dProgress in dProgressMap) {
    dispatcher(
      actions.replace({
        activityId: dProgress,
        progress: getProgress(dProgressMap[dProgress], dLengthMap[dProgress]),
        uploadSpeed: dSpeedMap[dProgress],
        secondsRemaining: dTimeMap[dProgress],
      })
    );
  }
};

const mInProgressActivityReducer = (state = intialState, action) => {
  switch (action.type) {
    case actionTypes.UPDATE_INPROGRESS_ACTIVITIES: {
      const mInProgressActivities = action.payload;

      const activities = mInProgressActivities ?? [];
      const uniqueActivities = new Map();
      if (mInProgressActivities) {
        for (let idx = 0; idx < activities.length; idx++) {
          if (!uniqueActivities.has(activities[idx].id)) {
            uniqueActivities.set(activities[idx].id, activities[idx]);
          }
        }
      }

      if (state.loading) {
        return {
          ...state,
          mInProgressActivities:
            uniqueActivities.size > 0
              ? Array.from(uniqueActivities.values())
              : [],
          loading: false, // make it false only one time
        };
      }
      return {
        ...state,
        mInProgressActivities: mInProgressActivities,
      };
    }
    case actionTypes.PUSH_INPROGRESS_ACTIVITY: {
      const mInProgressActivity = action.payload;
      console.log("EREREER", mInProgressActivity);
      return {
        ...state,
        mInProgressActivities: [
          ...state.mInProgressActivities,
          mInProgressActivity,
        ],
      };
    }
    case actionTypes.REPLACE_INPROGRESS_ACTIVITY: {
      const { activityId, progress, secondsRemaining, uploadSpeed } =
        action.payload;
      const newMappedArray = state.mInProgressActivities.map((item) => {
        if (item.activityId.toString() === activityId.toString()) {
          return {
            ...item,
            progress: progress,
            secondsRemaining: secondsRemaining,
            uploadSpeed: uploadSpeed,
          };
        }
        return item;
      });
      return {
        ...state,
        mInProgressActivities: newMappedArray,
      };
    }
    case actionTypes.ADD_SERVICE_FAILURE_INPROGRESS_ACTIVITY: {
      const { activityId } = action.payload;
      const newObj = { ...state.serviceFailure, activityId };
      return { ...state, serviceFailure: newObj };
    }
    case actionTypes.RESET_INPROGRESS_ACTIVITIES:
      return resetState;
  }
};

const MediaStatusSchema = [];

const _emptyItem = () => {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text style={[style.muliRegLG, { fontSize: 14 }]}>
        No in progress data available
      </Text>
    </View>
  );
};

const _renderItem = ({ item, index }) => {
  const serviceFailed = item?.serviceFailure;
  const type = serviceFailed ? "SERVICE_FAILURE" : "IN-PROGRESS";
  const newProps = {
    item,
    type: type,
  };
  return <ActivityView {...newProps} />;
};

const getMultiActivityData = async (oldState, dispatcher) => {
  const piMediaStatus = await Database.get("PIMediaStatus");
  const inProgressActivities = piMediaStatus.filter(
    (item) => item.activityStatus === "IN-PROGRESS"
  );

  // this should only update when there is new in progress activity

  if (oldState.mInProgressActivities.length < inProgressActivities.length) {
    dispatcher(actions.update(inProgressActivities));
  }

  //if there is nothing in progress, empty the redux
  if (inProgressActivities.length === 0) {
    dispatcher(actions.reset());
  }

  // this will update progress for each in progress item

  if (inProgressActivities.length > 0) {
    const dProgressMap = store.getState().uploadProgress.dProgressMap;
    createProgressObjects(dProgressMap, dispatcher);
  }
};

const getTimeInMinAndSec = (sec) => {
  if (!sec || sec === "calculating") {
    return `0 sec`;
  }
  const min = sec / 60;
  const remSec = sec % 60;
  return `${Math.floor(min)} min ${Math.floor(remSec)} sec`;
};

const _RETRY_TIMEOUT = 300000;

const TimeoutView = () => {
  const [timer, setTimer] = useState(_RETRY_TIMEOUT);
  useEffect(() => {
    let localTimer = _RETRY_TIMEOUT;
    const timeoutItr = setInterval(() => {
      localTimer -= 1000;
      setTimer(localTimer);
      console.log("localTimer - ", localTimer);
      if (localTimer === 0) {
        clearInterval(timeoutItr);
        findFailureAndReset();
      }
    }, 1000);

    return () => {
      clearInterval(timeoutItr);
    };
  }, []);

  return (
    <Text style={[style.muliboldBB, { fontSize: 12 }]}>
      Retring upload after {getTimeInMinAndSec(timer / 1000)}
    </Text>
  );
};

const InProgressSceneView = () => {
  const [mInProgressState, mInProgressDispatcher] = useReducer(
    mInProgressActivityReducer,
    intialState
  );

  const { mInProgressActivities, loading, serviceFailure } = mInProgressState;

  useEffect(() => {
    const itr = setInterval(() => {
      getMultiActivityData(mInProgressState, mInProgressDispatcher);
    }, 1000);
    return () => {
      clearInterval(itr);
    };
  }, []);

  return (
    <View style={styles.main}>
      {loading ? (
        <View
          style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
        >
          <ActivityIndicator
            style={{ alignSelf: "center" }}
            animating={true}
            color={"#D3D3D3"}
            size={"large"}
          />
        </View>
      ) : (
        [
          mInProgressActivities?.filter((item) => item.serviceFailure === true)
            .length > 0 && (
            <View
              style={{
                flex: 0.1,
                backgroundColor: "#FFFAEB",
                justifyContent: "space-evenly",
                paddingHorizontal: 16,
              }}
            >
              <TimeoutView />
            </View>
          ),
          <FlatList
            data={mInProgressActivities}
            keyExtractor={(item, index) => index.toString()}
            ListEmptyComponent={_emptyItem}
            renderItem={_renderItem}
            contentContainerStyle={{ flexGrow: 0.8 }}
          />,
        ]
      )}
    </View>
  );
};

export default InProgressSceneView;

const styles = StyleSheet.create({
  main: {
    flex: 1,
    backgroundColor: "#FFFFFF",
  },
});
