import DateFnsUtils from '@date-io/date-fns';
import { Button, Checkbox, CircularProgress, FormControlLabel, Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow, TextField } from "@material-ui/core";
import { KeyboardDatePicker, KeyboardTimePicker, MuiPickersUtilsProvider } from '@material-ui/pickers';
import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { logger } from "../../../services/monitoring";
import { DTCTimelineProvider, useDTCTimelineContext } from '../../Contexts/DTCTimelineContext';
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import TableHeaderSortable from "../../Table/HeaderSortable";
import { useLocalStorage } from "../../useLocalStorage";
import useStyles from "../../useStyles";

const MainForm = ({ vin }) => {
  const classes = useStyles();

  const PAGE_SIZE = "DTC_TABLE_PAGE_SIZE";
  const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10);
  const [pageIndex, setPageIndex] = useState(0);
  const [orderBy, setOrderBy] = useState("epoch_usec");
  const [order, setOrder] = useState("desc");
  const { dtcData, getDTCData, total = 0, exportDTCTimeline } = useDTCTimelineContext();
  const [selectedStartDate, setSelectedStartDate] = useState(new Date(Date.now() - 24 * 60 * 60 * 1000));
  const [selectedEndDate, setSelectedEndDate] = useState(new Date());
  const [selectedECU, setSelectedECU] = useState("");
  const [selectedTroubleCode, setSelectedTroubleCode] = useState("");
  const [gmtTimezone, setGmtTimezone] = useState(false);
  const [loading, setLoading] = useState(false);
  const { setMessage } = useStatusContext();

  const tableColumns = [
    {
      id: "ecu",
      label: "ECU",
    },
    {
      id: "trouble_code",
      label: "Trouble Code",
    },
    {
      id: "status_byte",
      label: "Status Code",
    },
    {
      id: "ErrorText",
      label: "Error Text",
      no_sort: true,
    },
    {
      id: "speed",
      label: "Speed",
      no_sort: true,
    },
    {
      id: "milage",
      label: "Milage",
      no_sort: true,
    },
    {
      id: "voltage",
      label: "Voltage",
      no_sort: true,
    },
    {
      id: "epoch_usec",
      label: "ECU Time",
    },
    {
      id: "created_at",
      label: "Cloud Time",
    },
    {
      id: "snapshot",
      label: "DTC Snapshot",
      no_sort: true,
    },
  ];

  const handleSort = (_event, property) => {
    if (property === orderBy) {
      if (order === "asc") {
        setOrder("desc");
      } else {
        setOrder("asc");
      }
    } else {
      setOrderBy(property);
      setOrder("desc");
    }
  };

  const handleChangePageIndex = (_event, newIndex) => {
    setPageIndex(newIndex);
  };

  const handleChangePageSize = (event) => {
    setPageSize(parseInt(event.target.value, 10));
    setPageIndex(0);
  };

  const {
    token: {
      idToken: { jwtToken: token },
    },
  } = useUserContext();

  const fetchDTCData = async () => {
    setLoading(true);
    try {
      let start_date = new Date(selectedStartDate);
      start_date = start_date.toISOString();

      let end_date = new Date(selectedEndDate);
      end_date = end_date.toISOString();

      const search = {
        limit: pageSize,
        offset: pageSize * pageIndex,
        order: `${orderBy} ${order}`,
      }
      await getDTCData(vin, selectedECU, selectedTroubleCode, start_date, end_date, search, token);
      // setDTCData(data);
    } catch (e) {
      setMessage(e.message);
      logger.warn(e.stack);
    }
    setLoading(false);
  };

  const exportDTCDataFunc = async () => {
    setLoading(true);
    try {
      let start_date = new Date(selectedStartDate);
      start_date = start_date.toISOString();

      let end_date = new Date(selectedEndDate);
      end_date = end_date.toISOString();

      const search = {
        limit: pageSize,
        offset: pageSize * pageIndex,
        order: `${orderBy} ${order}`,
      }
      await exportDTCTimeline(vin, selectedECU, selectedTroubleCode, start_date, end_date, search, token);
      // setDTCData(data);
    } catch (e) {
      setMessage(e.message);
      logger.warn(e.stack);
    }
    setLoading(false);
  };

  function formatDate(date) {
    return date.replace(/[TZ]/g, ' ')
  }

  const handleDateChange = (value, dateType) => {
    const newDate = new Date(value);
    const oldDate = dateType === "start" ? selectedStartDate || new Date() : selectedEndDate || new Date();
    newDate.setHours(oldDate.getHours());
    newDate.setMinutes(oldDate.getMinutes());
    newDate.setSeconds(oldDate.getSeconds());
    if (dateType === "start") {
      setSelectedStartDate(newDate);
    } else {
      setSelectedEndDate(newDate);
    }
  };

  const handleTimeFromChange = (value) => {
    setSelectedStartDate(value);
  };

  const handleTimeToChange = (value) => {
    setSelectedEndDate(value);
  };

  const displayTimeAsGMT = (date) => {
    return gmtTimezone
      ? date.toLocaleString("en-US", { timeZone: "Etc/GMT" })
      : date;
  }

  useEffect(() => {
    fetchDTCData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [vin, selectedECU, selectedStartDate, selectedEndDate, pageIndex, pageSize, order, orderBy]);

  return (
    <div className={classes.paper}>
      <Grid container spacing={3} justifyContent="center">
        <Grid item xs={12}>
          <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <Grid container justifyContent="space-between">
              <Grid item xs={6} md={3}>
                <KeyboardDatePicker
                  required
                  disableToolbar
                  variant="inline"
                  format="MM/dd/yyyy"
                  margin="normal"
                  id="date-picker-inline"
                  label="Date From"
                  value={displayTimeAsGMT(selectedStartDate)}
                  onChange={(value) => handleDateChange(value, "start")}
                  KeyboardButtonProps={{
                    'aria-label': 'change date',
                  }}
                />
              </Grid>
              <Grid item xs={6} md={3}>
                <KeyboardTimePicker
                  required
                  margin="normal"
                  variant="inline"
                  id="time-picker"
                  label="Time From"
                  value={displayTimeAsGMT(selectedStartDate)}
                  onChange={handleTimeFromChange}
                  KeyboardButtonProps={{
                    'aria-label': 'change time',
                  }}
                />
              </Grid>
              <Grid item xs={6} md={3}>
                <KeyboardDatePicker
                  required
                  disableToolbar
                  variant="inline"
                  format="MM/dd/yyyy"
                  margin="normal"
                  id="date-picker-inline"
                  label="Date To"
                  value={displayTimeAsGMT(selectedEndDate)}
                  onChange={(value) => handleDateChange(value, "end")}
                  KeyboardButtonProps={{
                    'aria-label': 'change date',
                  }}
                />
              </Grid>
              <Grid item xs={6} md={3}>
                <KeyboardTimePicker
                  required
                  margin="normal"
                  id="time-picker"
                  variant="inline"
                  label="Time To"
                  value={displayTimeAsGMT(selectedEndDate)}
                  onChange={handleTimeToChange}
                  KeyboardButtonProps={{
                    'aria-label': 'change time',
                  }}
                />
              </Grid>
              <Grid item xs={6} md={3}>
                <FormControlLabel
                  label="GMT"
                  control={
                    <Checkbox
                      checked={gmtTimezone}
                      onChange={() => setGmtTimezone((current) => !current)}
                    />
                  }
                />
              </Grid>
            </Grid>
          </MuiPickersUtilsProvider>
        </Grid>
        <Grid item xs={12}>
          <div style={{ marginBottom: '8px' }}>
            <TextField
              id="ecu_field"
              name="ecu_field"
              label="ECU"
              InputLabelProps={{
                shrink: true
              }}
              defaultValue=""
              variant="outlined"
              margin="normal"
              fullWidth
              onChange={(e) => {
                setSelectedECU(e.target.value);
              }}
            />
            <TextField
              id="trouble_code_field"
              name="trouble_code_field"
              label="Trouble Code"
              InputLabelProps={{
                shrink: true
              }}
              defaultValue=""
              variant="outlined"
              margin="normal"
              fullWidth
              onChange={(e) => {
                setSelectedTroubleCode(e.target.value);
              }}
            />
          </div>
        </Grid>
        <Grid item xs={6}>
          <Button
            variant="contained"
            color="primary"
            onClick={fetchDTCData}
            disabled={loading}
            fullWidth
          >
            {loading ? <CircularProgress size={24} /> : "Filter"}
          </Button>
        </Grid>
        <Grid item xs={6}>
          <Button
            variant="contained"
            color="primary"
            onClick={exportDTCDataFunc}
            disabled={loading}
            fullWidth
          >
            {loading ? <CircularProgress size={24} /> : "Export"}
          </Button>
        </Grid>
        <div className={clsx(classes.paper, classes.tableSize)}>
          <Table aria-label="dtc table">
            <TableHeaderSortable
              classes={classes}
              orderBy={orderBy}
              order={order}
              columnData={tableColumns}
              onSortRequest={handleSort}
            />
            <TableBody>
              {(dtcData || []).map((dtc, index) => (
                <TableRow key={index}>
                  <TableCell>{dtc.ecu_name}</TableCell>
                  <TableCell>{dtc.trouble_code}</TableCell>
                  <TableCell>{dtc.status_byte}</TableCell>
                  <TableCell>{dtc.trouble_code_information?.ErrorText?.Text}</TableCell>
                  {(dtc.speed || dtc.speed === 0) && <TableCell>{dtc.speed + " km/h"}</TableCell>}
                  {(dtc.mileage || dtc.mileage === 0) && <TableCell>{dtc.mileage + " km"}</TableCell>}
                  {(dtc.voltage || dtc.voltage === 0) && <TableCell>{dtc.voltage + " V"}</TableCell>}
                  <TableCell>{formatDate(dtc.epoch_usec)}</TableCell>
                  <TableCell>{formatDate(dtc.created_at)}</TableCell>
                  {dtc.snapshot && <TableCell style={{ wordBreak: "break-all" }}>{dtc.snapshot}</TableCell>}
                </TableRow>
              ))}
            </TableBody>
            <TableFooter>
              <TableRow>
                <TablePagination
                  rowsPerPageOptions={[5, 10, 25, 100]}
                  colSpan={6}
                  count={total}
                  rowsPerPage={pageSize}
                  page={pageIndex}
                  SelectProps={{
                    inputProps: { "aria-label": "rows per page" },
                    native: true,
                  }}
                  onPageChange={handleChangePageIndex}
                  onRowsPerPageChange={handleChangePageSize}
                />
              </TableRow>
            </TableFooter>
          </Table>
        </div>
      </Grid>
    </div>
  );

};

const DTCTimeline = (props) => (
  <DTCTimelineProvider>
    <MainForm {...props} />
  </DTCTimelineProvider>
);

export default DTCTimeline;
