import React, { useState } from "react";
import {
  Show,
  SimpleShowLayout,
  BooleanField,
  TextField,
  ShowProps,
  EditButton,
  TopToolbar,
  useTranslate,
  useRefresh,
} from "react-admin";
import {
  TextField as MuiTextField,
  Button,
  Card,
  Grid,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  Typography,
  Box,
  CircularProgress,
} from "@material-ui/core";
import { SixDigitInput } from "../../DigitInput";
import {
  sanitizeE164Number,
  isValidE164Number,
} from "../../../lib/phone-numbers";

const Sidebar = ({ record }: any) => {
  const [phoneNumber, setPhoneNumber] = useState("");
  const [errorNumber, setErrorNumber] = useState(false);
  const handlePhoneNumberChange = (event: any) => {
    setPhoneNumber(event.target.value);
  };

  const [message, setMessage] = useState("");
  const handleMessageChange = (event: any) => {
    setMessage(event.target.value);
  };

  const sendMessage = async (phoneNumber: string, message: string) => {
    await fetch(`/api/v1/signal/bots/${record.token}/send`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ phoneNumber, message }),
    });
  };

  const resetSession = async (phoneNumber: string) => {
    await fetch(`/api/v1/signal/bots/${record.token}/resetSession`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ phoneNumber }),
    });
  };

  const handleBlurNumber = () => {
    setErrorNumber(!isValidE164Number(sanitizeE164Number(phoneNumber)));
  };

  const handleSend = () => {
    const sanitized = sanitizeE164Number(phoneNumber);
    if (isValidE164Number(sanitized)) {
      setErrorNumber(false);
      sendMessage(sanitized, message);
    } else setErrorNumber(false);
  };

  const handleResetSession = () => {
    const sanitized = sanitizeE164Number(phoneNumber);
    if (isValidE164Number(sanitized)) {
      setErrorNumber(false);
      resetSession(sanitized);
    } else setErrorNumber(false);
  };

  return (
    <Card style={{ width: "33%", marginLeft: 20, padding: 14 }}>
      <Grid container direction="column" spacing={2}>
        <Grid item>
          <Typography variant="h6">Send message</Typography>
        </Grid>
        <Grid item>
          <MuiTextField
            variant="outlined"
            label="Phone number"
            fullWidth
            size="small"
            error={errorNumber}
            onBlur={handleBlurNumber}
            value={phoneNumber}
            onChange={handlePhoneNumberChange}
          />
        </Grid>
        <Grid item>
          <MuiTextField
            variant="outlined"
            label="Message"
            multiline
            minRows={3}
            fullWidth
            size="small"
            value={message}
            onChange={handleMessageChange}
          />
        </Grid>
        <Grid item container direction="row-reverse">
          <Button
            variant="contained"
            color="primary"
            onClick={() => handleSend()}
          >
            Send
          </Button>
          <Button variant="contained" onClick={() => handleResetSession()}>
            Reset Session
          </Button>
        </Grid>
      </Grid>
    </Card>
  );
};

const MODE = {
  SMS: "SMS",
  VOICE: "VOICE",
};

const handleRequestCode = async ({
  verifyMode,
  id,
  onSuccess,
  onFailure,
  captchaCode = undefined,
}: any) => {
  if (verifyMode === MODE.SMS) console.log("REQUESTING sms");
  else if (verifyMode === MODE.VOICE) console.log("REQUESTING voice");
  let response: Response;
  let url = `/api/v1/signal/bots/${id}/requestCode?mode=${verifyMode.toLowerCase()}`;
  if (captchaCode) {
    url += `&captcha=${captchaCode}`;
  }

  try {
    response = await fetch(url, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });

    if (response && response.ok) {
      onSuccess();
    } else {
      onFailure(response.status || 400);
    }
  } catch (error: any) {
    console.error("Failed to request verification code:", error);
  }
};

const VerificationCodeRequest = ({
  verifyMode,
  data,
  onSuccess,
  onFailure,
}: any) => {
  React.useEffect(() => {
    (async () => {
      await handleRequestCode({
        verifyMode,
        id: data.id,
        onSuccess,
        onFailure,
      });
    })();
  }, [data.id, onFailure, onSuccess, verifyMode]);

  return (
    <>
      <DialogTitle id="form-dialog-title">
        Requesting code for {data.phoneNumber}
      </DialogTitle>
      <DialogContent>
        <Box display="flex">
          <Box m="auto">
            <CircularProgress />
          </Box>
        </Box>
      </DialogContent>
    </>
  );
};

const VerificationCaptcha = ({
  verifyMode,
  data,
  onSuccess,
  onFailure,
  handleClose,
}: any) => {
  const [code, setCode] = React.useState(undefined);
  const [isSubmitting, setSubmitting] = React.useState(false);

  const handleSubmitVerification = async () => {
    setSubmitting(true);
    await handleRequestCode({
      verifyMode,
      id: data.id,
      onSuccess,
      onFailure,
      captchaCode: code,
    });
    setSubmitting(false);
  };

  const handleCaptchaChange = (value: any) => {
    if (value)
      setCode(
        value
          .replace(/signalcaptcha:\/\//, "")
          .replace("“", "")
          .replace("”", "")
          .trim()
      );
    else setCode(value);
  };

  return (
    <>
      <DialogTitle id="form-dialog-title">
        Captcha for {data.phoneNumber}
      </DialogTitle>
      <DialogContent>
        <MuiTextField
          value={code}
          onChange={(ev) => handleCaptchaChange(ev.target.value)}
        />
      </DialogContent>
      <DialogActions>
        {isSubmitting && <CircularProgress />}
        {!isSubmitting && (
          <Button onClick={handleClose} color="primary">
            Cancel
          </Button>
        )}
        {!isSubmitting && (
          <Button onClick={handleSubmitVerification} color="primary">
            Request
          </Button>
        )}
      </DialogActions>
    </>
  );
};

const VerificationCodeInput = ({
  data,
  verifyMode,
  handleClose,
  handleRestartVerification,
  confirmVerification,
}: any) => {
  const [code, setValue] = React.useState("");
  const [isSubmitting, setSubmitting] = React.useState(false);
  const [isValid, setValid] = React.useState(false);
  const [submissionError, setSubmissionError] = React.useState(undefined);
  const translate = useTranslate();

  const validator = (v: any) => v.trim().length === 6;

  const handleValueChange = (newValue: any) => {
    setValue(newValue);
    setValid(validator(newValue));
  };

  const handleSubmitVerification = async () => {
    setSubmitting(true);
    // await sleep(2000)
    const response = await fetch(
      `/api/v1/signal/bots/${data.id}/register?code=${code}`,
      {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
      }
    );
    setSubmitting(false);
    const responseBody = await response.json();
    console.log(responseBody);
    if (response.status === 200) {
      confirmVerification();
    } else if (responseBody.message)
      // @ts-expect-error
      setSubmissionError(`Error: ${responseBody.message}`);
    else {
      setSubmissionError(
        // @ts-expect-error
        "There was an error, sorry about that. Please try again later or contact support."
      );
    }
  };

  const title =
    verifyMode === MODE.SMS
      ? translate("resources.signalBots.verifyDialog.sms", {
          phoneNumber: data.phoneNumber,
        })
      : translate("resources.signalBots.verifyDialog.voice", {
          phoneNumber: data.phoneNumber,
        });
  return (
    <>
      <DialogTitle id="form-dialog-title">
        Verify {data.phoneNumber}
      </DialogTitle>
      <DialogContent>
        <DialogContentText>{title}</DialogContentText>
        <SixDigitInput value={code} onChange={handleValueChange} />
        {submissionError && (
          <Typography variant="body1" gutterBottom color="error">
            {submissionError}
          </Typography>
        )}
      </DialogContent>
      <DialogActions>
        {isSubmitting && <CircularProgress />}
        {!isSubmitting && (
          <Button onClick={handleClose} color="primary">
            Cancel
          </Button>
        )}
        {!isSubmitting && (
          <Button onClick={handleRestartVerification} color="primary">
            Restart
          </Button>
        )}
        {!isSubmitting && (
          <Button
            onClick={handleSubmitVerification}
            color="primary"
            disabled={!isValid}
          >
            Verify
          </Button>
        )}
      </DialogActions>
    </>
  );
};

const VerificationCodeDialog = (props: any) => {
  const [stage, setStage] = React.useState("request");
  const onRequestSuccess = () => setStage("verify");
  const onRestartVerification = () => setStage("request");
  const handleClose = () => {
    setStage("request");
    props.handleClose();
  };

  const onFailure = (code: number) => {
    if (code === 402 || code === 500) {
      setStage("captcha");
    } else {
      setStage("request");
    }
  };

  return (
    <Dialog
      open={props.open}
      onClose={props.handleClose}
      aria-labelledby="form-dialog-title"
    >
      {props.open && stage === "request" && (
        <VerificationCodeRequest
          mode={props.verifyMode}
          onSuccess={onRequestSuccess}
          onFailure={onFailure}
          {...props}
        />
      )}
      {props.open && stage === "verify" && (
        <VerificationCodeInput
          {...props}
          handleRestartVerification={onRestartVerification}
          handleClose={handleClose}
        />
      )}
      {props.open && stage === "captcha" && (
        <VerificationCaptcha
          mode={props.verifyMode}
          onSuccess={onRequestSuccess}
          onFailure={onRestartVerification}
          handleClose={handleClose}
          {...props}
        />
      )}
    </Dialog>
  );
};

const SignalBotShowActions = ({ data }: any) => {
  const [open, setOpen] = React.useState(false);
  const [verifyMode, setVerifyMode] = React.useState("");
  const refresh = useRefresh();

  const handleOpenSMS = () => {
    setVerifyMode(MODE.SMS);
    setOpen(true);
  };

  const handleOpenVoice = () => {
    setVerifyMode(MODE.VOICE);
    setOpen(true);
  };

  const handleClose = () => setOpen(false);
  const confirmVerification = () => {
    setOpen(false);
    refresh();
  };

  return (
    <TopToolbar>
      <EditButton record={data} />
      {data && !data.isVerified && (
        <Button onClick={handleOpenSMS} color="primary">
          Verify with SMS
        </Button>
      )}
      {data && !data.isVerified && (
        <Button onClick={handleOpenVoice} color="primary">
          Verify with Voice
        </Button>
      )}
      {data && !data.isVerified && (
        <VerificationCodeDialog
          data={data}
          verifyMode={verifyMode}
          handleClose={handleClose}
          open={open}
          confirmVerification={confirmVerification}
        />
      )}
    </TopToolbar>
  );
};

const SignalBotShow = (props: ShowProps) => (
  <Show
    actions={<SignalBotShowActions />}
    {...props}
    title="Signal Bot"
    aside={<Sidebar />}
  >
    <SimpleShowLayout>
      <TextField source="phoneNumber" />
      <BooleanField source="isVerified" />
      <TextField source="description" />
      <TextField source="token" />
    </SimpleShowLayout>
  </Show>
);

export default SignalBotShow;
