import {
  Alert,
  Box,
  Button,
  Card,
  CardActions,
  CardContent,
  Checkbox,
  FormControlLabel,
  TextField,
  Typography,
} from "@mui/material";
import React from "react";
import { ServerApi } from "../api/ServerApi";
import { ReplacePasswordResponse, User, UserApi } from "../api/UserApi";
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
import { useUser } from "../widgets/BaseAuthenticatedPage";
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
import { PasswordInput } from "../widgets/PasswordInput";
import { formatDate } from "../widgets/TimeWidget";

export function ProfileRoute(): React.ReactElement {
  const user = useUser();

  return (
    <div style={{ maxWidth: "500px", margin: "auto" }}>
      <Typography variant="h3">Profil</Typography>

      <ProfileSettingsCard
        user={user.user}
        onUpdate={() => user.reloadUserInfo()}
      />
      {user.user.has_password && <ChangePasswordCard />}
      <DeleteAccountButton />
    </div>
  );
}

function ProfileSettingsCard(p: { user: User; onUpdate: () => void }) {
  const [newName, setNewName] = React.useState(p.user.name);

  const [error, setError] = React.useState<string | null>(null);
  const [success, setSuccess] = React.useState<string | null>(null);

  const updateProfile = async () => {
    try {
      setSuccess(null);
      setError(null);

      await UserApi.UpdateProfile(newName);

      p.onUpdate();
      setSuccess("Informations du profil enregistrées avec succès !");
    } catch (e) {
      console.error(e);
      setError("Echec de la mise à jour du profil !");
    }
  };

  return (
    <>
      <Card style={{ marginTop: "10px" }}>
        {error && <Alert severity="error">{error}</Alert>}
        {success && <Alert severity="success">{success}</Alert>}

        <CardContent>
          <Typography gutterBottom variant="h5" component="div">
            Paramètres du compte
          </Typography>

          <Box
            component="form"
            sx={{
              "& .MuiTextField-root": { my: 1 },
            }}
            noValidate
            autoComplete="off"
          >
            <TextField
              disabled
              fullWidth
              label="Identifiant"
              value={p.user.id}
            />

            <TextField
              disabled
              fullWidth
              label="Création du compte"
              value={formatDate(p.user.time_create)}
            />

            <TextField
              disabled
              fullWidth
              label="Activation du compte"
              value={formatDate(p.user.time_activate)}
            />

            <TextField
              disabled
              fullWidth
              label="Adresse mail"
              value={p.user.email}
            />

            <TextField
              fullWidth
              label="Nom d'utilisateur"
              value={newName}
              onChange={(e) => setNewName(e.target.value)}
              inputProps={{
                maxLength: ServerApi.Config.constraints.user_name_len.max,
              }}
            />

            <FormControlLabel
              disabled
              control={<Checkbox checked={p.user.admin} />}
              label="Compte administrateur"
            />
          </Box>
        </CardContent>
        <CardActions>
          <Button onClick={updateProfile} style={{ marginLeft: "auto" }}>
            Enregistrer
          </Button>
        </CardActions>
      </Card>
    </>
  );
}

function ChangePasswordCard(): React.ReactElement {
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const [success, setSuccess] = React.useState<string | null>(null);

  const [oldPassword, setOldpassword] = React.useState("");
  const [newPassword, setNewpassword] = React.useState("");
  const [confirmNewPassword, setConfirmNewpassword] = React.useState("");

  const isValid =
    ServerApi.CheckPassword(newPassword) === null &&
    oldPassword.length > 0 &&
    confirmNewPassword === newPassword;

  const updatePassword = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    if (!isValid || loading) return;

    setLoading(true);
    setSuccess(null);
    setError(null);

    try {
      const result = await UserApi.ReplacePassword(oldPassword, newPassword);

      switch (result) {
        case ReplacePasswordResponse.Error:
          setError("Echec du changement de mot de passe !");
          break;
        case ReplacePasswordResponse.Success:
          setSuccess("Mot de passe changé avec succès !");
          break;
        case ReplacePasswordResponse.InvalidOldPassword:
          setError("Ancien mot de passe saisi invalide !");
          break;
        case ReplacePasswordResponse.InvalidNewPassword:
          setError("Nouveau mot de passe saisi invalide !");
          break;
        case ReplacePasswordResponse.TooManyRequests:
          setError(
            "Trop de tentatives de changement de mot de passe, veuillez réessayer ultérieurement !"
          );
          break;
      }
    } catch (e) {
      console.error(e);
      setError("Echec de la mise à jour du mot de passe !");
    }

    setLoading(false);
  };

  return (
    <>
      <Card style={{ marginTop: "10px" }}>
        {error && <Alert severity="error">{error}</Alert>}
        {success && <Alert severity="success">{success}</Alert>}
        <Box
          component="form"
          sx={{
            "& .MuiTextField-root": { my: 1 },
          }}
          noValidate
          autoComplete="off"
          onSubmit={updatePassword}
        >
          <CardContent>
            <Typography gutterBottom variant="h5" component="div">
              Changement du mot de passe
            </Typography>

            <TextField
              fullWidth
              label="Mot de passe actuel"
              value={oldPassword}
              type="password"
              onChange={(e) => setOldpassword(e.target.value)}
            />

            <PasswordInput
              value={newPassword}
              onChange={(n) => setNewpassword(n)}
              label={"Nouveau mot de passe"}
            />

            <TextField
              fullWidth
              error={
                confirmNewPassword !== "" && confirmNewPassword !== newPassword
              }
              helperText={
                confirmNewPassword !== newPassword
                  ? "Le nouveau mot de passe et sa confirmation doivent être identiques !"
                  : ""
              }
              label="Confirmation du nouveau mot de passe"
              value={confirmNewPassword}
              type="password"
              onChange={(e) => setConfirmNewpassword(e.target.value)}
            />
          </CardContent>
          <CardActions>
            <Button
              disabled={!isValid && !loading}
              type="submit"
              style={{ marginLeft: "auto" }}
            >
              Enregistrer
            </Button>
          </CardActions>{" "}
        </Box>
      </Card>
    </>
  );
}

function DeleteAccountButton(): React.ReactElement {
  const alert = useAlert();
  const confirm = useConfirm();

  const requestDelete = async () => {
    try {
      if (
        !(await confirm(
          "Voulez-vous initier la suppression de votre compte ?",
          "Suppression de compte"
        ))
      )
        return;

      await UserApi.RequestAccountDeletion();

      await alert(
        "Demande de suppression de compte enregistrée avec succès. Veuillez consulter votre boîte mail."
      );
    } catch (e) {
      console.error(e);
      alert("Echec de la demande de suppression de compte !");
    }
  };

  return (
    <div style={{ textAlign: "center", margin: "15px 0px" }}>
      <Button onClick={requestDelete} color="error">
        Supprimer mon compte
      </Button>
    </div>
  );
}
