import {
  Accordion,
  AccordionDetails,
  AccordionSummary,
  Box,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Button,
  Typography,
  Theme,
  DialogContent,
  DialogActions,
  DialogTitle,
  useTheme,
  List,
  ListItem,
  Divider,
  Grid2 as Grid,
  Tabs,
  Tab,
  colors,
  lighten
} from "@mui/material";
import { ExpandMore } from "@mui/icons-material";
import CustomProgressBar from "common/CustomProgressBar";
import ResponsiveDialog from "common/ResponsiveDialog";
import GrainDescriber from "grain/GrainDescriber";
import GrainTransaction from "grain/GrainTransaction";
import { useMobile } from "hooks";
import { Contract } from "models/Contract";
import { pond } from "protobuf-ts/pond";
import { useContractAPI } from "providers/pond/contractAPI";
import React, { useEffect, useState } from "react";
// import { useHistory } from "react-router";
import { Label, Pie, PieChart, ResponsiveContainer, Text } from "recharts";
import { stringToMaterialColour } from "utils";
import { makeStyles } from "@mui/styles";
import { useNavigate } from "react-router-dom";
import { useGlobalState } from "providers";

interface Props {
  contracts: Contract[];
  updateList: (newContractList: Contract[]) => void;
  contractPermissions: Map<string, pond.Permission[]>;
}

const useStyles = makeStyles((theme: Theme) => ({
    contractRow: {
      cursor: "pointer",
      "&:hover": {
        backgroundColor: lighten(theme.palette.background.default, 0.25)
      }
    }
  })
);

export default function ContractsList(props: Props) {
  const { contracts, contractPermissions, updateList } = props;
  const theme = useTheme();
  const [{as}] = useGlobalState();
  //will need map for contracts that have supported grain types
  const [supportedTypes, setSupportedTypes] = useState<Map<pond.Grain, Contract[]>>(new Map());
  //will need need map for custom contracts
  const [customTypes, setCustomTypes] = useState<Map<string, Contract[]>>(new Map());
  const [openGrainTransactionDialog, setOpenGrainTransactionDialog] = useState(false);
  const [currentContract, setCurrentContract] = useState<Contract>();
  // const history = useHistory();
  const classes = useStyles();
  const [deleteWindow, setDeleteWindow] = useState(false);
  const contractAPI = useContractAPI();
  const isMobile = useMobile();
  const [contractsDisplay, setContractsDisplay] = useState("open");
  const navigate = useNavigate();

  useEffect(() => {
    //loop through contracts setting them into the appropriate map at the appropriate location
    let supportedTypes: Map<pond.Grain, Contract[]> = new Map();
    let customTypes: Map<string, Contract[]> = new Map();

    contracts.forEach(con => {
      let contract: Contract | undefined;
      if (contractsDisplay === "open" && con.settings.delivered < con.settings.size) contract = con;
      if (contractsDisplay === "closed" && con.settings.delivered >= con.settings.size)
        contract = con;

      if (contract) {
        if (!contract.isCustom()) {
          let mapItem = supportedTypes.get(contract.settings.commodity);
          if (mapItem) {
            mapItem.push(contract);
          } else {
            supportedTypes.set(contract.settings.commodity, [contract]);
          }
        } else {
          let mapItem = customTypes.get(con.settings.customCommodity);
          if (mapItem) {
            mapItem.push(contract);
          } else {
            customTypes.set(contract.settings.customCommodity, [contract]);
          }
        }
      }
    });
    setSupportedTypes(supportedTypes);
    setCustomTypes(customTypes);
  }, [contracts, contractsDisplay]);

  const goToContract = (contract: Contract) => {
    let path = "/contracts/" + contract.key();
    navigate(path, {state: { contract: contract }})
    // history.replace(path);
  };

  const deleteContract = () => {
    if (currentContract) {
      contractAPI
        .removeContract(currentContract.key(), as)
        .then(resp => {
          let c = contracts;
          contracts.splice(c.indexOf(currentContract), 1);
          updateList(c);
        })
        .catch(err => {});
    }
    setDeleteWindow(false);
  };

  const displayTable = (contracts: Contract[]) => {
    return (
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Name</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Contract Date</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Delivery Due</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Size</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Delivered</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Progress</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Remaining</Typography>
            </TableCell>
            <TableCell>
              <Typography style={{ fontSize: 15, fontWeight: 650 }}>Actions</Typography>
            </TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {contracts.map(contract => {
            const fillPercent =
              Math.round((contract.settings.delivered / contract.settings.size) * 100 * 10) / 10;
            return (
              <TableRow
                key={contract.key()}
                className={classes.contractRow}
                onClick={() => {
                  goToContract(contract);
                }}>
                <TableCell>{contract.name()}</TableCell>
                <TableCell>{contract.settings.contractDate}</TableCell>
                <TableCell>{contract.settings.deliveryWindow?.endDate}</TableCell>
                <TableCell>{contract.sizeInPreferredUnit() + " " + contract.unit}</TableCell>
                <TableCell>{contract.deliveredInPreferredUnit() + " " + contract.unit}</TableCell>
                <TableCell>
                  {/* <progress value={contract.settings.delivered} max={contract.settings.size} style={{height: 10}}/> */}
                  <CustomProgressBar colour={colors.blue[500]} completed={fillPercent} />
                  {/* {((contract.settings.delivered/contract.settings.size)*100).toFixed(1) + "%"} */}
                </TableCell>
                <TableCell>
                  {contract.sizeInPreferredUnit() -
                    contract.deliveredInPreferredUnit() +
                    " " +
                    contract.unit}
                </TableCell>
                <TableCell>
                  <Button
                    variant="contained"
                    color="primary"
                    disabled={
                      !contractPermissions
                        .get(contract.key())
                        ?.includes(pond.Permission.PERMISSION_WRITE)
                    }
                    onClick={e => {
                      e.stopPropagation();
                      setOpenGrainTransactionDialog(true);
                      setCurrentContract(contract);
                    }}>
                    Deliver
                  </Button>
                  <Button
                    variant="contained"
                    style={{
                      backgroundColor: contractPermissions
                        .get(contract.key())
                        ?.includes(pond.Permission.PERMISSION_WRITE)
                        ? "red"
                        : "",
                      marginLeft: 5
                    }}
                    disabled={
                      !contractPermissions
                        .get(contract.key())
                        ?.includes(pond.Permission.PERMISSION_WRITE)
                    }
                    onClick={e => {
                      e.stopPropagation();
                      setDeleteWindow(true);
                      setCurrentContract(contract);
                    }}>
                    Delete
                  </Button>
                </TableCell>
              </TableRow>
            );
          })}
        </TableBody>
      </Table>
    );
  };

  const circleGraph = (contract: Contract) => {
    return (
      <ResponsiveContainer>
        <PieChart>
          {/* <Legend
            verticalAlign="bottom"
            content={() => (
              <Box textAlign="center" marginY={0.5}>
                <Chip label={contract.commodityLabel()} />
              </Box>
            )}
          /> */}
          <Pie
            outerRadius={"100%"}
            innerRadius="70%"
            stroke="transparent"
            data={[
              {
                name: "",
                value: contract.settings.delivered,
                fill: contract.colour
              },
              {
                name: "",
                value: contract.settings.size - contract.settings.delivered
              }
            ]}
            dataKey="value"
            cx="50%"
            cy="50%">
            <Label
              position="center"
              fill={theme.palette.text.secondary}
              fontSize={"0.75rem"}
              fontWeight={650}
              content={props => {
                const { cx, cy } = props.viewBox as any;
                return (
                  <g>
                    <Text
                      x={cx}
                      y={cy}
                      textAnchor="middle"
                      verticalAnchor="middle"
                      fill={props.fill}
                      fontWeight={props.fontWeight}
                      fontSize={props.fontSize}>
                      {((contract.settings.delivered / contract.settings.size) * 100).toFixed(1) +
                        "%"}
                    </Text>
                  </g>
                );
              }}
            />
          </Pie>
        </PieChart>
      </ResponsiveContainer>
    );
  };

  const mobileView = (contracts: Contract[]) => {
    return (
      <List style={{ width: "100%" }}>
        {contracts.map((c, i) => {
          const remaining = c.settings.size - c.settings.delivered;
          return (
            <React.Fragment key={c.key()}>
              <ListItem
                style={{ paddingLeft: 0, paddingRight: 0 }}
                className={classes.contractRow}
                onClick={() => {
                  goToContract(c);
                }}>
                <Grid container direction="row" spacing={2}>
                  <Grid size={6}>
                    <Typography noWrap style={{ fontWeight: 650 }}>
                      {c.name()}
                    </Typography>
                    <Typography>{c.settings.contractDate}</Typography>
                    <Typography>
                      {remaining > 0 ? remaining + " " + c.unit + " remaining" : "Completed"}
                    </Typography>
                  </Grid>
                  <Grid size={6}>
                    {circleGraph(c)}
                  </Grid>
                  <Grid size={6}>
                    <Button
                      variant="contained"
                      style={{ width: "100%" }}
                      color="primary"
                      disabled={
                        !contractPermissions
                          .get(c.key())
                          ?.includes(pond.Permission.PERMISSION_WRITE)
                      }
                      onClick={e => {
                        e.stopPropagation();
                        setOpenGrainTransactionDialog(true);
                        setCurrentContract(c);
                      }}>
                      Deliver
                    </Button>
                  </Grid>
                  <Grid size={6}>
                    <Button
                      variant="contained"
                      style={{
                        backgroundColor: contractPermissions
                          .get(c.key())
                          ?.includes(pond.Permission.PERMISSION_WRITE)
                          ? "red"
                          : "",
                        width: "100%"
                      }}
                      disabled={
                        !contractPermissions
                          .get(c.key())
                          ?.includes(pond.Permission.PERMISSION_WRITE)
                      }
                      onClick={e => {
                        e.stopPropagation();
                        setDeleteWindow(true);
                        setCurrentContract(c);
                      }}>
                      Delete
                    </Button>
                  </Grid>
                </Grid>
              </ListItem>
              {i !== contracts.length - 1 && <Divider />}
            </React.Fragment>
          );
        })}
      </List>
    );
  };

  const supportedGrains = () => {
    let elements: JSX.Element[] = [];
    supportedTypes.forEach((contracts, key) => {
      elements.push(
        <Accordion key={key} style={{ borderRadius: 10, marginBottom: 10 }} defaultExpanded>
          <AccordionSummary
            expandIcon={<ExpandMore />}
            style={{
              borderTopLeftRadius: 10,
              borderTopRightRadius: 10,
              backgroundColor: GrainDescriber(key).colour
            }}>
            <Typography
              style={{
                fontSize: 20,
                fontWeight: 650,
                color: theme.palette.getContrastText(GrainDescriber(key).colour)
              }}>
              {GrainDescriber(key).name} - ({contracts.length} Contract
              {contracts.length > 1 ? "s" : ""})
            </Typography>
          </AccordionSummary>
          <AccordionDetails>
            {isMobile ? mobileView(contracts) : displayTable(contracts)}
          </AccordionDetails>
        </Accordion>
      );
    });
    return elements;
  };

  const customGrains = () => {
    let elements: JSX.Element[] = [];
    customTypes.forEach((contracts, key) => {
      elements.push(
        <Accordion key={key} style={{ borderRadius: 10, marginBottom: 10 }} defaultExpanded>
          <AccordionSummary
            expandIcon={<ExpandMore />}
            style={{
              borderTopLeftRadius: 10,
              borderTopRightRadius: 10,
              backgroundColor: stringToMaterialColour(key)
            }}>
            <Typography style={{ fontSize: 20, fontWeight: 650 }}>
              {key} - ({contracts.length} Contract{contracts.length > 1 ? "s" : ""})
            </Typography>
          </AccordionSummary>
          <AccordionDetails>
            {isMobile ? mobileView(contracts) : displayTable(contracts)}
          </AccordionDetails>
        </Accordion>
      );
    });
    return elements;
  };

  const deleteConfirmation = () => {
    return (
      <ResponsiveDialog
        open={deleteWindow}
        onClose={() => {
          setDeleteWindow(false);
        }}>
        <DialogTitle>Delete Contract</DialogTitle>
        <DialogContent>Are you sure you want to delete this contract</DialogContent>
        <DialogActions>
          <Button
            variant="contained"
            color="primary"
            onClick={() => {
              setDeleteWindow(false);
            }}
            style={{ marginRight: 10 }}>
            Cancel
          </Button>
          <Button
            variant="contained"
            color="primary"
            style={{ backgroundColor: "red" }}
            onClick={deleteContract}>
            Delete
          </Button>
        </DialogActions>
      </ResponsiveDialog>
    );
  };

  return (
    <React.Fragment>
      <Box padding={2} paddingTop={0}>
        {/* <RadioGroup
            row
            value={contractsDisplay}
            onChange={(_, value) => {
              setContractsDisplay(value)
            }}>
            <FormControlLabel
              value={"open"}
              control={<Radio />}
              label={"Open"}
            />
            <FormControlLabel
              value={"closed"}
              control={<Radio />}
              label={"Closed"}
            />
          </RadioGroup> */}
        <Tabs
          value={contractsDisplay}
          onChange={(_, value) => setContractsDisplay(value)}
          indicatorColor="primary"
          textColor="primary"
          variant={isMobile ? "fullWidth" : "standard"}
          style={{ paddingTop: 0 }}
          aria-label="statusTabs">
          <Tab label={"Open"} value={"open"} />
          <Tab label={"Closed"} value={"closed"} />
        </Tabs>
        {supportedGrains()}
        {customGrains()}
      </Box>
      {currentContract && (
        <GrainTransaction
          open={openGrainTransactionDialog}
          mainObject={currentContract}
          restrictMatching
          asDestination
          allowAttachmentUploads
          close={() => {
            setOpenGrainTransactionDialog(false);
          }}
          callback={() => {}}
        />
      )}
      {deleteConfirmation()}
    </React.Fragment>
  );
}
