import {
  Box,
  Button,
  DialogActions,
  DialogContent,
  DialogTitle,
  FormControlLabel,
  Grid2 as Grid,
  InputAdornment,
  Step,
  StepLabel,
  Stepper,
  Switch,
  Tab,
  Tabs,
  TextField,
  Typography
} from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog";
import SearchSelect from "common/SearchSelect";
import GrainDescriber from "grain/GrainDescriber";
import { Contract } from "models/Contract";
import moment from "moment";
import { pond } from "protobuf-ts/pond";
import { useGlobalState, useTaskAPI, useContractAPI, useSnackbar } from "providers";
import React, { useEffect, useState } from "react";
import { getGrainUnit } from "utils";

interface Props {
  open: boolean;
  close: () => void;
  contract?: Contract;
  //if we do other types of contracts (not grain) the default type should be an input prop
}

interface InputLabels {
  commodityLabel: string;
  sizeLabel: string;
  deliveryLabel: string;
  conversionLabel: string;
  adornment: string;
}

export default function ContractSettings(props: Props) {
  const { open, close, contract } = props;
  const contractAPI = useContractAPI();
  const [name, setName] = useState("");
  const [{as}] = useGlobalState();
  const [contractID, setContractID] = useState(""); //id
  const [holder, setHolder] = useState(""); //holder
  const [deliveryStart, setDeliveryStart] = useState(moment().format("YYYY-MM-DD")); //deliverystart
  const [deliveryEnd, setDeliveryEnd] = useState(moment().format("YYYY-MM-DD")); //deliveryend
  const [contractType, setContractType] = useState<pond.ContractType>(1); //contracttype -- defaults to grain
  //const [selectedContractType, setSelectedContractType] = useState<Option | null>(null);
  const [customCommodity, setCustomCommodity] = useState(""); //customcommodity
  const [contractSize, setContractSize] = useState("0"); //contractsize
  const [deliveredAmount, setDeliveredAmount] = useState("0"); //deliveredamount
  const [contractValue, setContractValue] = useState("0"); //contractvalue
  const [commodity, setCommodity] = useState(0); //commodity
  const [useCustom, setUseCustom] = useState(false);
  const [currentTab, setCurrentTab] = useState(0);
  const [contractDate, setContractDate] = useState(moment().format("YYYY-MM-DD"));
  const [deleteWindow, setDeleteWindow] = useState(false);
  const [createDeliveryTask, setCreateDeliveryTask] = useState(false);
  const [conversionValue, setConversionValue] = useState("1");
  const { openSnack } = useSnackbar()
  const [labels, setLabels] = useState<InputLabels>({
    sizeLabel: "Size",
    commodityLabel: "Commodity",
    conversionLabel: "Primary units per Secondary Unit",
    deliveryLabel: "Delivered",
    adornment: ""
  });
  const taskAPI = useTaskAPI();
  const [{ user }] = useGlobalState();

  const closeSettings = () => {
    close();
  };

  useEffect(() => {
    if (contract) {
      setName(contract.name());
      setContractID(contract.settings.contractId);
      setHolder(contract.settings.contractHolder);
      setDeliveryStart(contract.settings.deliveryWindow?.startDate ?? "");
      setDeliveryEnd(contract.settings.deliveryWindow?.endDate ?? "");
      setContractType(contract.settings.type);
      setCustomCommodity(contract.settings.customCommodity);
      setContractSize(contract.sizeInPreferredUnit().toFixed(2));
      setDeliveredAmount(contract.deliveredInPreferredUnit().toFixed(2));
      setContractValue(contract.settings.totalValue.toString());
      setCommodity(contract.settings.commodity);
      setContractDate(contract.settings.contractDate);
      setConversionValue(
        contract.settings.conversionValue > 0 ? contract.settings.conversionValue.toString() : "1"
      );
      setUseCustom(contract.isCustom());
    }
  }, [contract]);

  useEffect(() => {
    switch (contractType) {
      case pond.ContractType.CONTRACT_TYPE_GRAIN:
        setLabels({
          sizeLabel: "Total Grain on Contract",
          commodityLabel: "Select Grain Type",
          conversionLabel: "Bushels Per Tonne",
          deliveryLabel: "Grain Delivered",
          adornment: getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? "mT" : "bu"
        });
        break;
      default:
        setLabels({
          sizeLabel: "Size",
          commodityLabel: "Commodity",
          conversionLabel: "Primary units per Secondary Unit",
          deliveryLabel: "Delivered",
          adornment: ""
        });
        break;
    }
  }, [contractType]);

  const createTask = (contractKey: string) => {
    let task: pond.TaskSettings = pond.TaskSettings.create({
      userId: user.id(),
      title: name + " Delivery Window",
      start: deliveryStart,
      startTime: "00:00",
      end: deliveryEnd,
      endTime: "00:00",
      objectKey: contractKey,
      description: "The window for delivering grain for the " + name + " contract",
      worker: user.id(),
      complete: false,
      colour: "22194D"
    });

    taskAPI
      .addTask(task, as)
      .then(resp => {
        console.log("Task Created");
      })
      .catch(err => {
        console.log("error creating task");
      });
  };

  const submit = () => {
    const conVal = isNaN(parseFloat(conversionValue)) ? 1 : parseFloat(conversionValue);
    const deliveredVal = isNaN(parseFloat(deliveredAmount))
      ? 0
      : Math.round(Contract.toStoredUnit(parseFloat(deliveredAmount), contractType, conVal));
    const sizeVal = isNaN(parseFloat(contractSize))
      ? 0
      : Math.round(Contract.toStoredUnit(parseFloat(contractSize), contractType, conVal));
    if (contract) {
      let settings: pond.ContractSettings = contract.settings;
      settings.commodity = commodity;
      settings.contractHolder = holder;
      settings.contractId = contractID;
      settings.customCommodity = customCommodity;
      settings.delivered = deliveredVal;
      settings.deliveryWindow = pond.ContractDelivery.create({
        startDate: deliveryStart,
        endDate: deliveryEnd
      });
      settings.conversionValue = conVal;
      settings.size = sizeVal;
      settings.totalValue = isNaN(parseFloat(contractValue)) ? 0 : parseFloat(contractValue);
      settings.type = contractType;
      settings.contractDate = contractDate;

      contractAPI
        .updateContract(contract.key(), name, settings, as)
        .then(resp => {
          //console.log("Updated Contract");
          openSnack("Contract Updated")
          close();
        })
        .catch(err => {
          //console.log("Error updating contract");
          openSnack("Error Updating Contract")

        });
    } else {
      let settings: pond.ContractSettings = pond.ContractSettings.create();
      settings.commodity = commodity;
      settings.contractHolder = holder;
      settings.contractId = contractID;
      settings.customCommodity = customCommodity;
      //settings.commoditySubtype = variant;
      settings.delivered = deliveredVal;
      settings.deliveryWindow = pond.ContractDelivery.create({
        startDate: deliveryStart,
        endDate: deliveryEnd
      });
      settings.size = sizeVal;
      settings.totalValue = isNaN(parseFloat(contractValue)) ? 0 : parseFloat(contractValue);
      settings.type = contractType;
      settings.conversionValue = conVal;
      settings.contractDate = contractDate;

      contractAPI
        .addContract(name, settings, as)
        .then(resp => {
          if (createDeliveryTask) {
            createTask(resp.data.key);
          }
          close();
        })
        .catch(err => {
          console.log("Error adding contract");
        });
    }
  };

  const deleteContract = () => {
    if (contract) {
      contractAPI
        .removeContract(contract.key(), as)
        .then(resp => {
          console.log("contract deleted");
          close();
        })
        .catch(err => {
          console.log("failed to delete contract");
        });
    }
  };

  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>
    );
  };

  const stepValid = () => {
    let valid = true;
    if (currentTab === 0) {
      if (name === "" || holder === "" || contractID === "") {
        valid = false;
      }
    } else if (currentTab === 1) {
      if (contractType === pond.ContractType.CONTRACT_TYPE_UNKNOWN) {
        valid = false;
      } else if (
        commodity === 0 ||
        (commodity === Contract.customValue(contractType) &&
          (customCommodity === "" || conversionValue === ""))
      ) {
        valid = false;
      }
    }
    return valid;
  };

  const general = () => {
    return (
      <React.Fragment>
        <Typography style={{ fontSize: 13, margin: 20 }}>
          General information about your contract such as: name, reference number, contract holder
          and delivery window will help organize your contracts for easy reference and deliveries.
          All fields marked with “*” are required but all fields are recommended
        </Typography>
        <TextField
          fullWidth
          margin="dense"
          value={name}
          InputLabelProps={{ shrink: true }}
          onChange={e => {
            setName(e.target.value);
          }}
          label={"*Contract Name"}
        />
        <TextField
          fullWidth
          margin="dense"
          type="date"
          label="Contract Signing Date"
          value={contractDate}
          InputLabelProps={{ shrink: true }}
          onChange={e => setContractDate(e.target.value)}
        />
        <TextField
          fullWidth
          margin="dense"
          value={contractID}
          InputLabelProps={{ shrink: true }}
          onChange={e => {
            setContractID(e.target.value);
          }}
          label={"*Reference #"}
        />
        <TextField
          fullWidth
          margin="dense"
          value={holder}
          InputLabelProps={{ shrink: true }}
          onChange={e => {
            setHolder(e.target.value);
          }}
          label={"*Contract Holder"}
        />
        <Box border={"2px solid grey"} borderRadius={5} padding={2} marginTop={2} marginBottom={2}>
          <Typography>Delivery Window</Typography>
          <TextField
            style={{ width: "45%" }}
            margin="dense"
            type="date"
            label="Start"
            value={deliveryStart}
            InputLabelProps={{ shrink: true }}
            onChange={e => setDeliveryStart(e.target.value)}
          />
          <TextField
            style={{ width: "45%", marginLeft: "10%" }}
            margin="dense"
            type="date"
            label="End"
            value={deliveryEnd}
            InputLabelProps={{ shrink: true }}
            onChange={e => setDeliveryEnd(e.target.value)}
          />
        </Box>
        {!contract && (
          <FormControlLabel
            control={
              <Switch
                checked={createDeliveryTask}
                onChange={(_, checked) => {
                  setCreateDeliveryTask(checked);
                }}
                name="Create Task For Delivery Window"
              />
            }
            //disabled={!canEdit}
            label="Create Task For Delivery Window"
            labelPlacement="end"
          />
        )}
        <TextField
          fullWidth
          margin="dense"
          type="number"
          value={contractValue}
          InputProps={{
            startAdornment: <InputAdornment position="start">$</InputAdornment>
          }}
          error={isNaN(parseFloat(contractValue))}
          helperText={isNaN(parseFloat(contractValue)) ? "Must be a valid number" : ""}
          InputLabelProps={{ shrink: true }}
          onChange={e => {
            setContractValue(e.target.value);
          }}
          label={"Contract Value"}
        />
      </React.Fragment>
    );
  };

  const details = () => {
    return (
      <React.Fragment>
        <Box>
          <Typography
            style={{ fontSize: 13, paddingLeft: 5, paddingRight: 5, margin: 20, marginBottom: 0 }}>
            Select Grain Type, Total Grain on Contract (bu), and Grain Delivered. These settings can
            be changed at anytime. If your grain type is not listed use the “Custom” toggle.
          </Typography>
          <Typography
            style={{
              fontSize: 13,
              padding: 5,
              border: "1px solid grey",
              borderRadius: 5,
              margin: 20
            }}>
            Note: When delivering grain on contract from a field or a bin the Grain Types must match
          </Typography>
        </Box>
        <Grid
          container
          direction="row"
          alignContent="center"
          alignItems="center"
          style={{ marginTop: 10 }}>
          <Grid size={8}>
            <SearchSelect
              label="Contract Type*"
              selected={Contract.toTypeOption(contractType)}
              changeSelection={option => {
                if (option) {
                  setContractType(option.value);
                }
              }}
              options={Contract.typeOptions()}
            />
          </Grid>
          <Grid size={4}>
            <FormControlLabel
              control={
                <Switch
                  checked={useCustom}
                  onChange={(_, checked) => {
                    setUseCustom(checked);
                    setCustomCommodity("");
                    if (checked) {
                      setCommodity(Contract.customValue(contractType));
                    } else {
                      setCommodity(0);
                    }
                  }}
                  name="Custom"
                />
              }
              //disabled={!canEdit}
              label="Custom"
              labelPlacement="start"
            />
          </Grid>
        </Grid>
        {!useCustom ? (
          <SearchSelect
            style={{ marginTop: 10 }}
            label={labels.commodityLabel + "*"}
            selected={Contract.toCommodityOption(contractType, commodity)}
            changeSelection={option => {
              if (option) {
                let c = 0;
                let conversion = 1;
                if (contractType) {
                  switch (contractType) {
                    case pond.ContractType.CONTRACT_TYPE_GRAIN:
                      c = pond.Grain[option.value as keyof typeof pond.Grain];
                      conversion = GrainDescriber(c).bushelsPerTonne;
                      break;
                    default:
                      c = option.value;
                  }
                }
                setCommodity(c);
                setConversionValue(conversion.toFixed(2));
              }
            }}
            options={Contract.commodityOptionsForType(contractType)}
          />
        ) : (
          <React.Fragment>
            <TextField
              fullWidth
              margin="dense"
              label="Custom*"
              value={customCommodity}
              InputLabelProps={{ shrink: true }}
              onChange={e => setCustomCommodity(e.target.value)}
            />
            <TextField
              fullWidth
              margin="dense"
              type="number"
              label={labels.conversionLabel}
              value={conversionValue}
              InputLabelProps={{ shrink: true }}
              error={isNaN(parseFloat(conversionValue))}
              helperText={isNaN(parseFloat(conversionValue)) ? "Must be a valid number" : ""}
              onChange={e => setConversionValue(e.target.value)}
            />
          </React.Fragment>
        )}
        {/* <TextField
            fullWidth
            margin="dense"
            type="variant"
            label="Variant"
            value={variant}
            InputLabelProps={{ shrink: true }}
            onChange={e => setVariant(e.target.value)}
          /> */}
        <TextField
          fullWidth
          margin="dense"
          type="number"
          InputProps={{
            endAdornment: <InputAdornment position="end">{labels.adornment}</InputAdornment>
          }}
          value={contractSize}
          error={isNaN(parseFloat(contractSize))}
          helperText={isNaN(parseFloat(contractSize)) ? "Must be a valid number" : ""}
          InputLabelProps={{ shrink: true }}
          onChange={e => {
            setContractSize(e.target.value);
          }}
          label={labels.sizeLabel}
        />
        <TextField
          fullWidth
          margin="dense"
          type="number"
          InputProps={{
            endAdornment: <InputAdornment position="end">{labels.adornment}</InputAdornment>
          }}
          value={deliveredAmount}
          error={isNaN(parseFloat(deliveredAmount))}
          helperText={isNaN(parseFloat(deliveredAmount)) ? "Must be a valid number" : ""}
          InputLabelProps={{ shrink: true }}
          onChange={e => {
            setDeliveredAmount(e.target.value);
          }}
          label={labels.deliveryLabel}
        />
      </React.Fragment>
    );
  };

  const stepper = () => {
    if (contract === undefined) {
      return (
        <Stepper activeStep={currentTab}>
          <Step key={"general"}>
            <StepLabel>General</StepLabel>
          </Step>
          <Step key={"details"}>
            <StepLabel>Commodity</StepLabel>
          </Step>
        </Stepper>
      );
    }

    return (
      <Box display="flex" justifyContent="center" width="100%">
        <Tabs
          value={currentTab}
          onChange={(_, value) => setCurrentTab(value)}
          indicatorColor="primary"
          textColor="primary"
          variant="fullWidth"
          aria-label="bin tabs"
          //classes={{ root: classes.tabs }}
        >
          <Tab label="General" />
          <Tab label="Commodity" />
        </Tabs>
      </Box>
    );
  };

  const stepperContent = (step: number) => {
    switch (step) {
      case 1:
        return details();
      default:
        return general();
    }
  };

  return (
    <React.Fragment>
      <ResponsiveDialog open={open} onClose={closeSettings}>
        <DialogTitle>Contract Settings</DialogTitle>
        <DialogContent>
          {/* <Tabs 
            value={currentTab}
            onChange={(_, value) => setCurrentTab(value)}>
              <Tab label="General" />
              <Tab label="Commodity" />
          </Tabs>
          <TabPanelMine value={currentTab} index={0}>
            {general()}
          </TabPanelMine>
          <TabPanelMine value={currentTab} index={1}>
            {details()}
          </TabPanelMine> */}
          {stepper()}
          {stepperContent(currentTab)}
        </DialogContent>
        <DialogActions>
          <Grid container direction="row-reverse" justifyContent="space-between">
            <Grid>
              <Button
                variant="contained"
                color="primary"
                onClick={close}
                style={{ marginRight: 10 }}>
                Cancel
              </Button>
              {!contract && currentTab > 0 && (
                <Button
                  variant="contained"
                  color="primary"
                  onClick={() => {
                    setCurrentTab(currentTab - 1);
                  }}
                  style={{ marginRight: 10 }}>
                  Back
                </Button>
              )}
              {(contract || currentTab === 1) && (
                <Button
                  variant="contained"
                  color="primary"
                  onClick={submit}
                  style={{ marginRight: 10 }}
                  disabled={!stepValid()}>
                  Submit
                </Button>
              )}
              {!contract && currentTab < 1 && (
                <Button
                  variant="contained"
                  color="primary"
                  onClick={() => {
                    setCurrentTab(currentTab + 1);
                  }}
                  style={{ marginRight: 10 }}
                  disabled={!stepValid()}>
                  Next
                </Button>
              )}
            </Grid>
            {contract && (
              <Grid>
                <Button
                  variant="contained"
                  style={{ backgroundColor: "red" }}
                  onClick={() => {
                    setDeleteWindow(true);
                  }}>
                  Delete
                </Button>
              </Grid>
            )}
          </Grid>
        </DialogActions>
      </ResponsiveDialog>
      {deleteConfirmation()}
    </React.Fragment>
  );
}
