import { mdiCash, mdiFolderZipOutline } from "@mdi/js";
import Icon from "@mdi/react";
import DownloadIcon from "@mui/icons-material/Download";
import UploadIcon from "@mui/icons-material/Upload";
import {
  Alert,
  Button,
  Card,
  CardActions,
  CardContent,
  CardHeader,
  Grid,
  Typography,
} from "@mui/material";
import { BackupApi } from "../api/BackupApi";
import { useAccounts } from "../hooks/AccountsListProvider";
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
import { RouterLink } from "../widgets/RouterLink";
import excelIcon from "./excel.svg";

export function BackupRoute(): React.ReactElement {
  return (
    <MoneyMgrWebRouteContainer label={"Backup & Restore"}>
      <Grid container spacing={2}>
        {/* ZIP */}
        <ImportExportModal
          icon={<Icon path={mdiFolderZipOutline} size={1} />}
          label="ZIP"
          description={
            <>
              Perform an exhaustive export or import (of accounts, inbox,
              movements and files).
            </>
          }
          importWarning="Existing data will be COMPLETELY ERASED, before starting import!"
          exportURL={BackupApi.ZIPExportURL}
          onImport={(f) => BackupApi.ZIPImport(f)}
          acceptedFiles={"application/zip"}
        />

        {/* FinancesManager */}
        <ImportExportModal
          icon={<Icon path={mdiCash} size={1} />}
          label="FinancesManager"
          description={
            <>
              Import and export movements using{" "}
              <a
                href="https://gitlab.com/pierre42100/cpp-financesmanager"
                target="_blank"
                rel="noreferrer"
                style={{ color: "inherit" }}
              >
                FinancesManager
              </a>{" "}
              file format (does not support file attachments).
            </>
          }
          importWarning="Existing data will not be touched, movement will be inserted in newly created accounts."
          exportURL={BackupApi.FinancesManagerExportURL}
          onImport={(f) => BackupApi.FinancesManagerImport(f)}
        />

        {/* Excel */}
        <ImportExportModal
          icon={<img src={excelIcon} width={"25em"} />}
          label="Excel"
          description={"Export data in Excel format"}
          exportURL={BackupApi.ExcelExportURL()}
        />
      </Grid>
    </MoneyMgrWebRouteContainer>
  );
}

function ImportExportModal(p: {
  icon: React.ReactElement;
  label: string;
  description: string | React.ReactElement;
  importWarning?: string;
  exportURL: string;
  onImport?: (file: File) => Promise<void>;
  acceptedFiles?: string;
}): React.ReactElement {
  const confirm = useConfirm();
  const alert = useAlert();
  const snackbar = useSnackbar();
  const loadingMessage = useLoadingMessage();
  const accounts = useAccounts();

  const doImport = async () => {
    try {
      const fileEl = document.createElement("input");
      fileEl.type = "file";
      if (p.acceptedFiles) fileEl.accept = p.acceptedFiles;
      fileEl.click();

      // Wait for a file to be chosen
      await new Promise((res) => {
        fileEl.addEventListener("change", () => {
          res(null);
        });
      });

      if (fileEl.files?.length === 0) return;

      if (
        !(await confirm(
          <>
            <p>Do you really want to perform import from {p.label}?</p>
            {p.importWarning && (
              <Alert severity="warning">{p.importWarning}</Alert>
            )}
          </>,
          `Import from ${p.label}`,
          "Perform import"
        ))
      )
        return;

      loadingMessage.show("Performing import...");

      await p.onImport!(fileEl.files![0]);

      snackbar("The import was successuflly executed!");
      accounts.reload();
    } catch (e) {
      console.error("Failed to perform import!", e);
      alert(`Failed to perform import! ${e}`);
    } finally {
      loadingMessage.hide();
    }
  };

  return (
    <Grid
      size={{ sm: 12, md: 6, lg: 4 }}
      style={{ height: "100%", maxHeight: "250px" }}
    >
      <Card
        elevation={3}
        variant="outlined"
        style={{
          height: "100%",
          display: "flex",
          flexDirection: "column",
        }}
      >
        <CardHeader avatar={p.icon} title={p.label} />
        <CardContent style={{ flex: 1 }}>
          <Typography style={{ textAlign: "justify" }}>
            {p.description}
          </Typography>
        </CardContent>{" "}
        <CardActions>
          <span style={{ flex: 1 }}>
            <RouterLink to={p.exportURL} target="_blank">
              <Button
                startIcon={<DownloadIcon />}
                variant="outlined"
                color="info"
                fullWidth
              >
                Export
              </Button>
            </RouterLink>
          </span>
          <span style={{ flex: 1 }}>
            <Button
              startIcon={<UploadIcon />}
              variant="outlined"
              color="warning"
              fullWidth
              disabled={!p.onImport}
              onClick={doImport}
            >
              Import
            </Button>
          </span>
        </CardActions>
      </Card>
    </Grid>
  );
}
