import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useNavigate, useSearchParams } from "react-router-dom";
import { selectAllRoutes, selectTomorrowAllRoutes, selectHistoryRoutes, selectTomorrowInboundRoutes, selectTomorrowOutboundRoutes, selectAllActiveDrivers, selectAllActiveVehicles } from "./../../store";
import RoutesSection from "./RoutesSection";
import { PERSONAL_ROUTE_STATUS } from "../../shared";
import { transRoutesSlice } from "../../store";
import { AuthService, TransRoutesService } from "../../services";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { Modal, Button, Spinner } from "react-bootstrap";
import RouteCustomerTable from "./RouteCustomerTable";
import moment from "moment";

const RoutesSchedule = () => {
  const navigate = useNavigate();
  const dispatch = useDispatch();
  const inboundRoutes = useSelector(selectTomorrowInboundRoutes);
  const outboundRoutes = useSelector(selectTomorrowOutboundRoutes);
  const allRoutes = useSelector(selectAllRoutes);
  const tomorrowRoutes = useSelector(selectTomorrowAllRoutes);
  const drivers = useSelector(selectAllActiveDrivers);
  const [datePicked, setDatePicked] = useState(undefined);
  const [dateTargetPicked, setDateTargetPicked] = useState(undefined);
  const [dateSchedule, setDateSchedule] = useState(undefined);
  const vehicles = useSelector(selectAllActiveVehicles);
  const { createRoute, fetchAllTomorrowRoutes } = transRoutesSlice.actions;
  const [errorMessage, setErrorMessage] = useState(undefined);
  const [successMessage, setSuccessMessage] = useState(undefined);
  const [showCopyTodayLoading, setShowCopyTodayLoading] = useState(false);
  const [showCopyDateLoading, setShowCopyDateLoading] = useState(false);
  const [showCopyDateTargetLoading, setShowCopyDateTargetLoading] = useState(false);
  const [copyDisabled, setCopyDisabled] = useState(false);
  const [copyDateDisabled, setCopyDateDisabled] = useState(false);
  const [showDeleteModal, setShowDeleteModal] = useState(false);
  const [searchParams, setSearchParams] = useSearchParams();
  const [isLoading, setIsLoading] = useState(false);
  const now = new Date();
  const params = new URLSearchParams(window.location.search);
  const scheduleDate = params.get('dateSchedule');
 
  now.setDate(now.getDate() + 1);
  const directToDashboad = () => {
    navigate('/trans-routes/dashboard');
  }

  const createVehicle = () => {
    navigate('/vehicles?redirect=schedule');
  }

  const createDriver = () => {
    navigate('/employees?redirect=schedule&type=driver');
  }

  const goToCreateRoute = (type) => {
    navigate(`/trans-routes/create?type=${type}&date=${scheduleDate? scheduleDate: 'tomorrow'}`);
  }

  const getDateString = (date) => {
    return ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear()
  }

  const cleanupSchedule = () => {
    tomorrowRoutes.forEach((route) => {
      TransRoutesService.deleteRoute(route.id);
    });
    setTimeout(() => {
      closeDeleteModal();
      window.location.reload();
    }, 1000)
  }

  const closeDeleteModal = () => {
    setShowDeleteModal(false);
  }


  const triggerShowDeleteModal = () => {
    setShowDeleteModal(true);
  }

  const startToScheduleDate = (v) => {
    setDateSchedule(v);
    setSearchParams({dateSchedule: moment(v).format('YYYY-MM-DD')});
    dispatch(fetchAllTomorrowRoutes({dateText: moment(v).format('MM/DD/YYYY')}));
  } 

  const validateSchedule = () => {
    const inboundCustomersRouteMap = {};
    let success = true;
    for (const inboundRoute of inboundRoutes) {
      for (const inboundCustomer of inboundRoute.route_customer_list) {
        if (Object.keys(inboundCustomersRouteMap).includes(inboundCustomer.customer_id) && inboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
          setSuccessMessage(undefined);
          success = false;
          setErrorMessage(`Error: Customer ${inboundCustomer.customer_name} was scheduled in both inbound ${inboundRoute.name} and ${inboundCustomersRouteMap[inboundCustomer.customer_id].name}.`)
          break;
        } else {
          if (inboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
            inboundCustomersRouteMap[inboundCustomer.customer_id] = inboundRoute;
          }
          
        }
      }
    }
    const outboundCustomersRouteMap = {};
    for (const outboundRoute of outboundRoutes) {
      for (const outboundCustomer of outboundRoute.route_customer_list) {
        if (Object.keys(outboundCustomersRouteMap).includes(outboundCustomer.customer_id) && outboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
          setSuccessMessage(undefined);
          success = false;
          setErrorMessage(`Error: Customer ${outboundCustomer.customer_name} was scheduled in both outbound ${outboundRoute.name} and ${outboundCustomersRouteMap[outboundCustomer.customer_id].name}.`)
          break;
        } else {
          if (outboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
            outboundCustomersRouteMap[outboundCustomer.customer_id] = outboundRoute;
          }
          
        }
      }
    }
    if (success) {
      setErrorMessage(undefined);
      setSuccessMessage(`Routes Schedule Validate Successfully`);
    }
  }

  const copyTodayRoutesOver = () => {
    setShowCopyTodayLoading(true);
    setIsLoading(true);
    let count = 0;
    TransRoutesService.getAll(((now.getMonth() > 8) ? (now.getMonth() + 1) : ('0' + (now.getMonth() + 1))) + '/' + ((now.getDate() > 9) ? now.getDate() : ('0' + now.getDate())) + '/' + now.getFullYear()).then(existingRoutes => {
      for (const draftRoute of allRoutes) {
        const existed = existingRoutes?.data?.find(r => r.name === draftRoute.name);
        if (draftRoute && !existed) {
          const data = Object.assign({}, {
            name: draftRoute.name,
            schedule_date: ((now.getMonth() > 8) ? (now.getMonth() + 1) : ('0' + (now.getMonth() + 1))) + '/' + ((now.getDate() > 9) ? now.getDate() : ('0' + now.getDate())) + '/' + now.getFullYear(),
            vehicle: draftRoute.vehicle,
            driver: draftRoute.driver,
            type: draftRoute.type,
            start_mileage: vehicles.find((vehicle) => vehicle.id === draftRoute.vehicle)?.mileage,
            route_customer_list: draftRoute.route_customer_list?.map((customer) => {
              return Object.assign({}, customer, {
                customer_enter_center_time: null,
                customer_leave_center_time: null,
                customer_pickup_time: null,
                customer_dropoff_time: null,
                customer_estimated_pickup_time: null,
                customer_estimated_dropoff_time: null,
                customer_route_status: PERSONAL_ROUTE_STATUS.NO_STATUS,
                customer_address_override: null
              })
            })
          });
          dispatch(createRoute({ data }));
        } else {
          if (existed) {
            count++;
          }
        }
      }
      setTimeout(() => {
        dispatch(fetchAllTomorrowRoutes({}));
        setShowCopyTodayLoading(false);
        setCopyDisabled(true);
        setIsLoading(false);
        setSuccessMessage('Routes Copied Successfully, please do not click the button again!');
        if (count > 0) {
          window.alert(`${count} routes has existed in selected date and is not copied again!`)
        }
      }, 2000);
    })
    
  }

  const copyDateRoutesOver = (withTargetDate) => {
    const dateSelected = new Date(datePicked);
    const scheduleDate = withTargetDate ? new Date(dateTargetPicked) : now;
    if (withTargetDate) {
      setShowCopyDateTargetLoading(true);
    } else {
      setShowCopyDateLoading(true);
    }

    setIsLoading(true);
    let count = 0;
    TransRoutesService.getAll(getDateString(dateSelected)).then(({data: allHistoryRoutes}) => {
      TransRoutesService.getAll(((scheduleDate.getMonth() > 8) ? (scheduleDate.getMonth() + 1) : ('0' + (scheduleDate.getMonth() + 1))) + '/' + ((scheduleDate.getDate() > 9) ? scheduleDate.getDate() : ('0' + scheduleDate.getDate())) + '/' + scheduleDate.getFullYear()).then(existingRoutes => {
        for (const draftRoute of allHistoryRoutes) {
          const existed = existingRoutes?.data?.find((r) => r. name === draftRoute.name);
          if (draftRoute && !existed) {
            const data = Object.assign({}, {
              name: draftRoute.name,
              schedule_date: ((scheduleDate.getMonth() > 8) ? (scheduleDate.getMonth() + 1) : ('0' + (scheduleDate.getMonth() + 1))) + '/' + ((scheduleDate.getDate() > 9) ? scheduleDate.getDate() : ('0' + scheduleDate.getDate())) + '/' + scheduleDate.getFullYear(),
              vehicle: draftRoute.vehicle,
              driver: draftRoute.driver,
              type: draftRoute.type,
              start_mileage: vehicles.find((vehicle) => vehicle.id === draftRoute.vehicle)?.mileage,
              route_customer_list: draftRoute.route_customer_list?.map((customer) => {
                return Object.assign({}, customer, {
                  customer_enter_center_time: null,
                  customer_leave_center_time: null,
                  customer_pickup_time: null,
                  customer_dropoff_time: null,
                  customer_estimated_pickup_time: null,
                  customer_estimated_dropoff_time: null,
                  customer_route_status: PERSONAL_ROUTE_STATUS.NO_STATUS,
                  customer_address_override: null
                })
              })
            });
            dispatch(createRoute({ data }));
          } else {
            if (existed) {
              count++;
            }
          }
        }
        setTimeout(() => {
          // dispatch(fetchAllTomorrowRoutes({}));
          startToScheduleDate(withTargetDate ? dateTargetPicked : now);
          if (withTargetDate) {
            setShowCopyDateTargetLoading(false);
          } else {
            setShowCopyDateLoading(false);
          }
          setIsLoading(false);
          setCopyDateDisabled(true);
          setSuccessMessage('Routes Copied Successfully, please do not click the button again!');
          if (count > 0) {
            window.alert(`${count} routes has existed on selected date and are not copied again.`)
          }
        }, 2000);
      });
    });
  }

  useEffect(() => {
    if (!AuthService.canAddOrEditRoutes()) {
      window.alert('You haven\'t login yet OR this user does not have access to this page. Please change an admin account to login.')
      AuthService.logout();
      navigate(`/login`);
    }
  }, []);

  return (
    <>
      {errorMessage && <div className="alert alert-danger alert-dismissible fade show" role="alert">
        {errorMessage}
        <button onClick={() => setErrorMessage(undefined)} type="button" className="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>}
      {successMessage && <div className="alert alert-success alert-dismissible fade show" role="alert">
        {successMessage}
        <button onClick={() => setSuccessMessage(undefined)} type="button" className="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>}
      <div className="list row">
        <div className="col-md-12 text-primary mb-2">
          Schedule Date: { scheduleDate ? scheduleDate : moment().format('YYYY-MM-DD')} <button type="button" onClick={() => directToDashboad()} className="btn btn-link btn-sm">Back</button>
        </div>
      </div>
      <div className="list row">
        <div className="col-lg-3 col-md-6 col-sm-6 col-xs-12 mb-4">
          <button type="button" className="btn btn-primary btn-sm me-2 mb-4" disabled={copyDisabled || showCopyTodayLoading} onClick={() => copyTodayRoutesOver()}>{showCopyTodayLoading? 'Loading...' : `Copy Today's Routes Over`}</button>
        </div>
        {/* <div className="col-lg-4 col-md-6col-sm-12 col-xs-12 mb-4">
          <button type="button" className="btn btn-primary btn-sm" onClick={()=> validateSchedule()}>Validate and Finish Planning</button>
        </div> */}
        <div className="col-lg-4 col-md-6 col-sm-12 col-xs-12 mb-4">
          <button type="button" className="btn btn-primary btn-sm" onClick={()=> triggerShowDeleteModal()}>Clean All Routes</button>
        </div>
        <div className="col-lg-4 col-md-6 col-sm-8 col-xs-12 mb-4">
          <DatePicker placeholderText={'Please Select A Date to Copy Routes From'}  selected={datePicked} onChange={(v) => setDatePicked(v)} />
        </div> 
        <div className="col-lg-8 col-md-6 col-sm-4 col-xs-12 mb-4">
          <button type="button" className="btn btn-primary btn-sm me-2" disabled={showCopyDateLoading} onClick={() => copyDateRoutesOver()}>{showCopyDateLoading? 'Loading...' : `Copy Routes To The Schedule Day!`}</button> 
        </div>
        <div className="col-md-12 mb-4">
          -- OR --
        </div>
        <div className="col-lg-4 col-md-6 col-sm-8 col-xs-12 mb-4">
          <DatePicker placeholderText={'Please Select A Date to Copy Routes To'}  selected={dateTargetPicked} onChange={(v) => setDateTargetPicked(v)} />
        </div> 
        <div className="col-lg-8 col-md-6 col-sm-4 col-xs-12 mb-4">
        <button type="button" className="btn btn-primary btn-sm me-2" disabled={showCopyDateTargetLoading} onClick={() => copyDateRoutesOver(true)}>{showCopyDateTargetLoading? 'Loading...' : `Copy Routes to Dates Selected!`}</button> 
        </div> 

        <div className="col-lg-4 col-md-6 col-sm-8 col-xs-12 mb-4">
          <DatePicker placeholderText={'Select the Day you want to Schedule'} minDate={new Date(new Date().getTime() + (24 * 60 * 60 * 1000))}  selected={dateSchedule} onChange={(v) => {startToScheduleDate(v)}} />
        </div> 

        {isLoading && <div className="col-md-12"><Spinner animation="border" role="status">
          <span className="visually-hidden">Loading...</span>
        </Spinner></div>}
        {!isLoading && <>
          <div className="col-md-12 mb-4">
            <RoutesSection transRoutes={inboundRoutes} copyList={outboundRoutes} addText="+Add Route" copyText="+Copy Route from Outbound" canAddNew={true} drivers={drivers} vehicles={vehicles} redirect={goToCreateRoute} routeType="inbound" sectionName="Inbound Routes"/>
          </div>
          <hr />
          <div className="col-md-12 mb-4">
            <RoutesSection transRoutes={outboundRoutes} copyList={inboundRoutes} addText="+Add Route" copyText="+Copy Route from Inbound" canAddNew={true} drivers={drivers} vehicles={vehicles} redirect={goToCreateRoute} routeType="outbound" sectionName="Outbound Routes"/>
          </div>
          <hr />
          {(AuthService.canCreateOrEditDrivers() || AuthService.canAddOrEditEmployees()) && <div className="col-md-12 mb-4">
            <RoutesSection canAddNew={true} drivers={drivers} addText="+Add Driver"  redirect={createDriver} sectionName="Drivers"/>
          </div>}
          <hr />
          {AuthService.canAddOrEditVechiles() && <div className="col-md-12 mb-4">
            <RoutesSection canAddNew={true} vehicles={vehicles} addText="+Add Vehicle" redirect={createVehicle} sectionName="Vehicles"/>
          </div>}
          <hr />
          <div className="col-md-12 mb-4">
            {allRoutes && vehicles && <RouteCustomerTable transRoutes={allRoutes} sectionName={'Customer Seating'} vehicles={vehicles}/>}
          </div>
        </>}
        
      </div>
      <Modal show={showDeleteModal} onHide={() => closeDeleteModal()}>
        <Modal.Header closeButton>
          <Modal.Title>Delete Schedule</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <div>Are you sure you want to delete all the schedule?</div>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="link" onClick={() => closeDeleteModal()}>
            No
          </Button>
          <Button variant="primary" onClick={() => cleanupSchedule()}>
            Yes
          </Button>
        </Modal.Footer>
      </Modal>
    </>
    
  );
};

export default RoutesSchedule;