import { Grid, TextField, InputAdornment } from '@material-ui/core';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import CustomTable from '../../../Common/CustomTable/CustomTable';
import { getShowJobsTableColumns } from './ShowJobs.columns';
import { useRouteMatch, useHistory } from 'react-router-dom';
import { TShowTypes } from '../Jobs.types';
import {
  AVAILABLE,
  BIDS_TO_CONFIRM,
  JOBS_WILDCARDS_KEYS,
} from '../Jobs.constans';
import { IShowJobsProps } from './ShowJobs.types';
import { Job } from '../../../../Api/Job/Job';
import {
  IJobFilters,
  IJobInfo,
} from '../../../../../../Application/DTOs/JobsDto/JobsDto.types';
import { toast } from 'react-toastify';
import { useDispatch, useSelector } from 'react-redux';
import { setLoader } from '../../../../Redux/Loader/actions';
import BidDialog from '../../../Dialogs/BidDialog/BidDialog';
import AdditionalStepDialog from '../../../Dialogs/AdditionalStepDialog/AdditionalStepdialog';
import MarkCompleteDialog from '../../../Dialogs/MarkCompleteDialog/MarkCompleteDialog';
import { GridRowParams } from '@material-ui/data-grid';
import ShowBiddersDialog from '../../../Dialogs/ShowBiddersDialog/ShowBiddersDialog';
import ViewEditJob from '../../../Dialogs/ViewEditJob/ViewEditJob';
import DateEntryDialog from '../../../Dialogs/DateEntryDialog/DateEntryDialog';
import {
  JOB_FILES_TYPE,
  JOB_STATUS,
  POST_TO,
  TActualDateTypes,
  USER_ROLES,
} from '../../../../Types/Constants';
import { WebStorage } from '../../../../Utilities/WebStorage';

import { AppState } from '../../../../Redux';
import { setJobList, setSelectedJob } from '../../../../Redux/Job/actions';
import SelectDriverDialog from '../../../Dialogs/SelectDriverDialog/SelectDriverDialog';
import SearchIcon from '@material-ui/icons/Search';
import fileDownload from 'js-file-download';
import EditJobDataDialog from '../../../Dialogs/EditJobDataDialog/EditJobDataDialog';


const jobApi = new Job();

const { PUBLIC } = POST_TO;

const { IN_PROGRESS, DELIVERED, PICKEDUP, ASSIGNED, FUMIGATION, VIA_YARD, STORAGE } = JOB_STATUS;

const { DRIVER_MANAGER, COMPANY_DRIVER, ADMIN_USER, COMPANY } = USER_ROLES;

const { POD } = JOB_FILES_TYPE;

function ShowJobs(props: IShowJobsProps) {
  const [t] = useTranslation(['ShowJobs', 'Columns']);
  const dispatch = useDispatch();
  const match = useRouteMatch();
  const params: any = match.params;
  const { disableJobGetting, customJobsToShow, hideSearchByReference } = props;
  const showType: TShowTypes | undefined =
    (params[JOBS_WILDCARDS_KEYS.SHOW_TYPE] as any) || AVAILABLE;

  const user = useSelector((state: AppState) => state.user);
  const { list: jobs, selectedJob } = useSelector((state: AppState) => state.job);
  const isAdminUser = user.response?.type === ADMIN_USER;
  const isCompanyUser = user.response?.type === COMPANY;

  const [isBiddingDialogOpen, setIsBiddingDialogOpen] = useState(false);
  const [isAdditionalDialogOpen, setIsAdditionalDialogOpen] = useState(false);

  const [isDateEntryDialogOpen, setIsDateEntryDialogOpen] = useState(false);
  const [isMarkCompleteDialogOpen, setIsMarkCompleteDialogOpen] =
    useState(false);
  const [isShowBiddersDialogOpen, setIsShowBiddersDialogOpen] = useState(false);
  const [isViewEditJobDialogOpen, setIsViewEditJobDialogOpen] = useState(false);
  const [
    isSelecteDriverManagerDialogOpen,
    setIsSelecteDriverManagerDialogOpen,
  ] = useState(false);
  const [isSelectDriverDialogOpen, setIsSelectDriverDialogOpen] =
    useState(false);
  const [selectedJobId, setSelectedJobId] = useState<string | number | undefined>(undefined);
  const [searchByReference, setSearchByReference] = useState('');
  const [isEditActualDatesOpen, setIsEditActualDatesOpen] = useState(false);
  const storage = new WebStorage(false)
  const history = useHistory();


  const openSelectDriversDialog = useCallback(
    (
      showSelectDriverManager: boolean,
      showSelectDriver: boolean,
      jobId: string | number
    ) => {
      if (showSelectDriverManager) {
        setIsSelecteDriverManagerDialogOpen(true);
      } else if (showSelectDriver) {
        setIsSelectDriverDialogOpen(true);
      }

      setSelectedJobId(jobId);
    },
    []
  );

  const onRowClick = useCallback(
    (rowParams: GridRowParams) => {
      const job: IJobInfo = rowParams.row as IJobInfo;
      dispatch(setSelectedJob(job));

      if (showType === BIDS_TO_CONFIRM) {
        setIsShowBiddersDialogOpen(true);
      } else {
        setIsViewEditJobDialogOpen(true);
      }
    },
    [showType, dispatch]
  );

  const getJobs = useCallback(
    (jobFilters?: IJobFilters) => {
      if (disableJobGetting) return;
      let country: string | undefined;
    
      if (isAdminUser) {
        country = user.response?.country;
      } else if (isCompanyUser) {
        country = user.response?.company?.country;
      }

      dispatch(setLoader(true));
      jobApi
        .get(props.type, showType || 'all', country, jobFilters)
        .then((response) => {
          const _jobs: IJobInfo[] = response.data;
          // dispatch(setJobList(_jobs));
          dispatch(setLoader(false));
        })
        .catch((err: any) => {
          // dispatch(setJobList([]));
          dispatch(setLoader(false));
          console.log('err', err);
          toast.error(t('error_getting_jobs'));
        });
    },
    [
      props.type,
      dispatch,
      showType,
      disableJobGetting,
      t,
      isAdminUser,
      user.response?.country,
      isCompanyUser,
      user.response?.company?.country,
    ]
  );

  const handleOnMarkCompleteDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));

    setIsMarkCompleteDialogOpen(false);
  }, [getJobs, dispatch]);

  const handleOnEditActualDatesDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsEditActualDatesOpen(false);
  }, [getJobs, dispatch]);

  const handleOnDateEntryDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsDateEntryDialogOpen(false);
  }, [getJobs, dispatch]);

  const handleOnBiddingDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsBiddingDialogOpen(false);
  }, [getJobs, dispatch]);
  const handleOnDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsAdditionalDialogOpen(false);
  }, [getJobs, dispatch]);

  const handleOnViewEditJobDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsViewEditJobDialogOpen(false);
  }, [getJobs, dispatch]);

  const handleOnShowBiddersDialogClose = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsShowBiddersDialogOpen(false);
  }, [getJobs, dispatch]);

  const onBid = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsBiddingDialogOpen(true);
    },
    [dispatch]
  );

  const onAdditionalStep = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsAdditionalDialogOpen(true);
    },
    [dispatch]
  );

  const onMarkAsComplete = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsMarkCompleteDialogOpen(true);
    },
    [dispatch]
  );

  const onSetDate = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsDateEntryDialogOpen(true);
    },
    [dispatch]
  );
  const onTrackUser = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsAdditionalDialogOpen(true);
    },
    [dispatch]
  );
  const handleBiddingSuccess = useCallback(() => {
    getJobs();
  }, [getJobs]);

  const handleAdditionalDone = useCallback(() => {
    getJobs();
  }, [getJobs]);

  const onMakePublic = useCallback(
    (job: IJobInfo) => {
      const formData = new FormData();

      formData.append('post_to', PUBLIC);

      jobApi
        .update(job.id, formData)
        .then(() => {
          toast.success(t('success_make_public'));
          getJobs();
        })
        .catch((err: any) => {
          console.log('err', err);
          toast.error(t('error_make_public'));
        });
    },
    [getJobs, t]
  );

  const onDownloadPod = useCallback(
    (job: IJobInfo) => {
      dispatch(setLoader(true));
      jobApi
        .downloadAllJobFiles(job.id)
        .then((response) => {
          fileDownload(response.data, 'job_files.zip', 'application/zip');
          dispatch(setLoader(false));
        })
        .catch((err: any) => {
          console.log('err', err);
          dispatch(setLoader(false));
          toast.error(t('error_download_proof_of_delivery'));
        });
    },
    [dispatch, t]
  );



  const onEditJob = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));

      setIsViewEditJobDialogOpen(true);
    },
    [dispatch]
  );

  const onEditActualDatesForJob = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsEditActualDatesOpen(true);
    },
    [dispatch]
  );

  const onCancelJob = useCallback(
    (job: IJobInfo) => {
      dispatch(setLoader(true));
      jobApi
        .cancelJob(job.id)
        .then(() => {
          dispatch(setLoader(false));
          toast.success(t('success_cancelling_job'));
          getJobs();
        })
        .catch((err: any) => {
          console.log('err', err);
          dispatch(setLoader(false));
          toast.error(t('error_canceling_job'));
        });
    },
    [dispatch, t, getJobs]
  );

  const columns = useMemo(
    () =>
      showType
        ? getShowJobsTableColumns(
          t,
          showType,
          {
            onCancelJob,
            onBid,
            onSetDate,
            onMarkAsComplete,
            onMakePublic,
            onSelectDriverClick: openSelectDriversDialog,
            onDownloadPod,
            onEditJob,
            onEditActualDatesForJob,
            onAdditionalStep,
            onTrackUser,
          },
          user
        )
        : [],
    [
      onEditJob,
      onDownloadPod,
      t,
      user,
      showType,
      onBid,
      onSetDate,
      onMarkAsComplete,
      onMakePublic,
      openSelectDriversDialog,
      onEditActualDatesForJob,
      onCancelJob,
      onAdditionalStep,
      onTrackUser
    ]
  );




  let dateType: TActualDateTypes | undefined = useMemo(() => {
    switch (selectedJob?.status) {
      case IN_PROGRESS:
      case ASSIGNED:

        return 'pickup';
      case PICKEDUP:
      case FUMIGATION:
      case VIA_YARD:
      case STORAGE:
        return 'delivery';
      case DELIVERED:
        return 'return';

      default:
        return undefined;
    }
  }, [selectedJob?.status]);

  const jobsToShow: IJobInfo[] = customJobsToShow || jobs;

  const handleSelectDriverManagerDialogClose = useCallback(() => {
    setIsSelecteDriverManagerDialogOpen(false);
    getJobs();
  }, [getJobs]);

  const handleSelectDriverDialogClose = useCallback(() => {
    setIsSelectDriverDialogOpen(false);
    getJobs();
  }, [getJobs]);






  useEffect(() => {

    let timeOutId = setTimeout(() => {
      getJobs({
        reference: searchByReference,
      });
    }, 500);

    return () => {
      clearTimeout(timeOutId);
    };
  }, [searchByReference, getJobs]);

  return (
    <>
      <EditJobDataDialog
        selectedJob={selectedJob}
        open={isEditActualDatesOpen}
        handleClose={handleOnEditActualDatesDialogClose}
      />
      <SelectDriverDialog
        selectedJobId={selectedJobId}
        userTypeToGet={DRIVER_MANAGER}
        title={t('select_driver_manager')}
        open={isSelecteDriverManagerDialogOpen}
        handleClose={handleSelectDriverManagerDialogClose}
      />
      <SelectDriverDialog
        selectedJobId={selectedJobId}
        userTypeToGet={COMPANY_DRIVER}
        title={t('select_driver')}
        open={isSelectDriverDialogOpen}
        handleClose={handleSelectDriverDialogClose}
      />
      <MarkCompleteDialog
        selectedJob={selectedJob}
        open={isMarkCompleteDialogOpen}
        handleClose={handleOnMarkCompleteDialogClose}
      />
      <DateEntryDialog
        type={dateType}
        selectedJob={selectedJob}
        open={isDateEntryDialogOpen}
        handleClose={handleOnDateEntryDialogClose}
      />
      <ViewEditJob
        key={(selectedJob?.id || 0) + 1}
        selectedJob={selectedJob}
        type={props.type}
        open={isViewEditJobDialogOpen}
        handleClose={handleOnViewEditJobDialogClose}
        isInProgress={selectedJob?.status === IN_PROGRESS}
        mode={props.type === 'assigned-transport' ? 'edit-allocated' : 'edit'}
      />
      <ShowBiddersDialog
        selectedJob={selectedJob}
        open={isShowBiddersDialogOpen}
        handleClose={handleOnShowBiddersDialogClose}
      />
      <BidDialog
        selectedJob={selectedJob}
        open={isBiddingDialogOpen}
        handleClose={handleOnBiddingDialogClose}
        onDone={handleBiddingSuccess}
      />

      <AdditionalStepDialog
        selectedJob={selectedJob}
        open={isAdditionalDialogOpen}
        handleClose={handleOnDialogClose}
      />
      <Grid container spacing={2} justifyContent="flex-end">
        {!hideSearchByReference ? (
          <Grid item md={4}>
            <TextField
              value={searchByReference}
              onChange={(e) => setSearchByReference(e.target.value)}
              variant="outlined"
              fullWidth
              label={t('search_by_reference')}
              InputProps={{
                endAdornment: (
                  <InputAdornment position="end">
                    <SearchIcon />
                  </InputAdornment>
                ),
              }}
              InputLabelProps={{
                style: {
                  fontWeight: 'bold',
                },
              }}
            />
          </Grid>
        ) : null}
        <Grid item md={12}>
          <CustomTable
            onRowClick={onRowClick}
            rows={jobsToShow}
            columns={columns}
          />
        </Grid>
      </Grid>
    </>
  );
}

export default ShowJobs;
