import { Grid, TextField, InputAdornment } from '@material-ui/core';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import CustomTable from '../../../Common/CustomTable/CustomTable';
import { getShowJobsTableColumns } from './ShowJobs.columns';
import { useRouteMatch } from 'react-router-dom';
import { TShowTypes } from '../Jobs.types';
import Swal from 'sweetalert2'
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 LocationTrackingDialog from '../../../Dialogs/LocationTrackingDialog/LocationTrackingDialog'

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 { 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';
import LazyTable from '../../../Common/LazyTable/LazyTable';
import { WebStorage } from '../../../../Utilities/WebStorage';
import { AxiosError } from 'axios';
import { useLocation } from 'react-router-dom';
import useDebouncedValue from '../../../../hooks/useDebouncedValue';
import SectionHeader from '../../../Common/SectionHeader/SectionHeader';

const _ = require('lodash');

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 [retainCurrent, setRetainCurrent] = useState(false);

  const location = useLocation();

  const [refreshTable, setRefreshTable] = useState(false);

  const [
    isSelecteDriverManagerDialogOpen,
    setIsSelecteDriverManagerDialogOpen,
  ] = useState(false);
  const [isSelectDriverDialogOpen, setIsSelectDriverDialogOpen] =
    useState(false);
  const [selectedJobId, setSelectedJobId] = useState<
    string | number | undefined
  >(undefined);
  const storage = new WebStorage(false)
  const queryParams = new URLSearchParams(location.search);
  const referenceParam = queryParams.get('reference') || '';

  const [isEditActualDatesOpen, setIsEditActualDatesOpen] = useState(false);
  const [isTracking, setIsTracking] = useState(false);
  const [files, setFiles] = useState<any>([]);

  const [filterState, setFilterState] = useState<IJobFilters>({
    reference: referenceParam
  });

  const debouncedFilters = useDebouncedValue(filterState, 500); // Debounce filters

  useEffect(() => {
    setFilterState((prevFilters) => ({
      ...prevFilters,
      reference: referenceParam,
    }));
  }, [referenceParam, showType, isDateEntryDialogOpen]);

  const handleFilterChange = (e) => {
    const { name, value } = e.target;
    setFilterState((prevFilters) => ({
      ...prevFilters,
      [name]: value,
    }));
  };

  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 isNotNullOrEmpty = str => !_.isNil(str) && !_.isEmpty(_.toString(str));
  const onConnoteClick = useCallback(
    (job: IJobInfo) => {

      Swal.fire({
        title: 'Select a file',
        input: 'file',
        inputAttributes: {
          accept: '.pdf', // specify accepted file types, e.g., 'image/*,.pdf,.doc'
          'aria-label': 'Upload Connote files',
          multiple: 'multiple' // allow multiple file selection
        },
        showCancelButton: true,
        confirmButtonText: 'Upload',
        cancelButtonText: 'Cancel',
        showLoaderOnConfirm: true,
        preConfirm: (files) => {
          // You can process the selected file here

          return files;
        }
      }).then((result) => {


        if (result.isConfirmed) {
          const files = result.value;
          if (!files) {
            toast.error("File not found");
            return
          }
          if (!isNotNullOrEmpty(job.pick_up_address.email)) {
            toast.error("Email recipient not found");
            return
          }
          if (result.isConfirmed) {
            jobApi.uploadFiles(12, files, job.id, true, 12).then(() => {
              toast.success('The file has been uploaded, and the email has been sent.');

              jobApi.sendConnotationEmail(job.id, files).then((response) => {
                dispatch(setLoader(false));
              }).catch((err: any) => {
                dispatch(setLoader(false));
                console.log('err', err);
                toast.error(t(err.response?.data || 'error_uploading_file'));
              })
            })
              .catch((err: any) => {
                dispatch(setLoader(false));
                console.log('err', err);
                toast.error(t(err.response?.data || 'error_uploading_file'));
              });
          }
        }
      });
      // dispatch(setSelectedJob(job));

    },
    [showType, dispatch]
  );

  const getJobs = useCallback(
    (jobFilters?: IJobFilters) => {
      setRefreshTable(prev => !prev);
    },
    [
      props.type,
      dispatch,
      showType,
      disableJobGetting,
      t,
      isAdminUser,
      user.response?.country,
      isCompanyUser,
      user.response?.company?.country,
    ]
  );




  const lazyGet = async (offset: number, pageNumber: number, limit: number, jobFilters: any, order_by: any) => {
    if (disableJobGetting) return;
    let country: string | undefined;

    if (isAdminUser) {
      country = user.response?.country;
    } else if (isCompanyUser) {
      country = user.response?.company?.country;
    }
    // dispatch(setLoader(true));
    const leShow = showType == 'all' ? showType : showType
    return jobApi
      .lazyGet(props.type, leShow, country, jobFilters, undefined, undefined, offset, pageNumber, limit, order_by)
      .then((response) => {
        const jobs: IJobInfo[] = response.data.jobList;
        const count = response.data.jobsCount;
        return { jobs, count }
      })
      .catch((err: AxiosError) => {
        const jobs: IJobInfo[] = [];
        const count = 0;
        if (err.response.status != 502) {
          toast.error(t('error_getting_jobs'));
        }
        return { jobs, count }

      });

  }

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

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

  const hasEditDialogClosedOnce = useRef(false);

  const handleOnEditActualDatesDialogClose = useCallback(() => {
    dispatch(setSelectedJob(null));
    setIsEditActualDatesOpen(false);
    hasEditDialogClosedOnce.current = true;
  }, [dispatch]);

  useEffect(() => {
    if (!isEditActualDatesOpen && hasEditDialogClosedOnce.current) {
      getJobs();
      hasEditDialogClosedOnce.current = false;
    }
  }, [isEditActualDatesOpen, getJobs]);


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

  const hasDialogClosedOnce = useRef(false);

  const handleOnDateEntryDialogClose = useCallback(() => {
    dispatch(setSelectedJob(null));
    setIsDateEntryDialogOpen(false);
    hasDialogClosedOnce.current = true;
  }, [dispatch]);

  useEffect(() => {
    if (!isDateEntryDialogOpen && hasDialogClosedOnce.current) {
      getJobs();
      hasDialogClosedOnce.current = false;
    }
  }, [isDateEntryDialogOpen, getJobs]);



  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(() => {

    setTimeout(() => {
      getJobs();
    }, 500);
    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 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 onTrackUser = useCallback(
    (job: IJobInfo) => {
      dispatch(setSelectedJob(job));
      setIsTracking(true);
    },
    [dispatch]
  );
  const handleTrackingOff = useCallback(() => {
    getJobs();
    dispatch(setSelectedJob(null));
    setIsTracking(false);
  }, [getJobs, dispatch]);



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

          },
          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(() => {
  //   if (selectedJob != null) {
  //     setRetainCurrent(true)
  //   } else {
  //     setRetainCurrent(false)
  //   }
  //   let timeOutId = setTimeout(() => {
  //     setFilterState({
  //       ...filterState,
  //       reference: searchByReference,
  //     });
  //   }, 500);
  //   return () => {
  //     clearTimeout(timeOutId);
  //   };
  // }, [searchByReference, showType, selectedJob]);



  return (
    <>
      <EditJobDataDialog
        selectedJob={selectedJob}
        open={isEditActualDatesOpen}
        handleClose={handleOnEditActualDatesDialogClose}
      />
      <LocationTrackingDialog
        selectedJob={selectedJob}
        open={isTracking}
        handleClose={handleTrackingOff}

      />
      <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}
      />
      <SectionHeader subtitle={t('transport_management')} title=
        {['bids'].includes(t(showType).toLowerCase())
          ? t(showType)
          : (t(showType).match(/\bjobs?\b/i) ? t(showType) : `${t(showType)} Jobs`)
        }

      />

      <Grid container spacing={2} justifyContent="flex-end">
        {!hideSearchByReference ? (
          <Grid item md={4}>
            <TextField
              value={filterState.reference}
              onChange={handleFilterChange}
              name='reference'
              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}>
          <LazyTable
            onRowClick={onRowClick}
            lazyFunction={lazyGet}
            columns={columns}
            lazyFilter={debouncedFilters}
            refresh={refreshTable}
            retainCurrent={retainCurrent}
            pageType={showType}
          />
        </Grid>
      </Grid>
    </>
  );
}

export default ShowJobs;
