import FolderCopyIcon from "@mui/icons-material/FolderCopy";
import FunctionsIcon from "@mui/icons-material/Functions";
import ImportExportIcon from "@mui/icons-material/ImportExport";
import RefreshIcon from "@mui/icons-material/Refresh";
import ScaleIcon from "@mui/icons-material/Scale";
import { Grid, IconButton, Paper, Tooltip, Typography } from "@mui/material";
import { LineChart } from "@mui/x-charts/LineChart";
import { filesize } from "filesize";
import React from "react";
import { GlobalStats, StatBalanceVariation, StatsApi } from "../api/StatsApi";
import { useAccounts } from "../hooks/AccountsListProvider";
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
import { fmtDateFromTime, time } from "../utils/DateUtils";
import { AmountWidget } from "../widgets/AmountWidget";
import { AsyncWidget } from "../widgets/AsyncWidget";
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";

export function HomeRoute(): React.ReactElement {
  const publicMode = usePublicMode().enabled;
  const account = useAccounts();

  const loadKey = React.useRef(1);

  const [global, setGlobal] = React.useState<GlobalStats | undefined>();
  const [lastYear, setLastYear] = React.useState<
    StatBalanceVariation[] | undefined
  >();

  const load = async () => {
    setGlobal(await StatsApi.GetGlobal());
    const lastyear = await StatsApi.BalanceVariationStats(
      time() - 3600 * 24 * 365,
      time(),
      3600 * 24
    );

    // Manually compute sum
    for (const entry of lastyear) {
      let sum = 0;

      for (const a of account.list.list) {
        sum += entry[a.id.toString()];
      }

      entry.sum = sum;
    }

    setLastYear(lastyear);
  };

  const reload = () => {
    loadKey.current += 1;
    setGlobal(undefined);
  };

  return (
    <MoneyMgrWebRouteContainer
      label={"Welcome to Money Manager"}
      actions={
        <Tooltip title="Refresh dashboard">
          <IconButton onClick={reload}>
            <RefreshIcon />
          </IconButton>
        </Tooltip>
      }
    >
      {publicMode ? (
        <Typography
          variant="body1"
          style={{
            textAlign: "center",
            flex: 1,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          Dashboard is hidden when public mode is enabled.
        </Typography>
      ) : (
        <AsyncWidget
          ready={global !== undefined}
          loadKey={loadKey.current}
          load={load}
          errMsg="Failed to load statistics!"
          build={() => <StatsDashboard global={global!} lastYear={lastYear!} />}
        />
      )}
    </MoneyMgrWebRouteContainer>
  );
}

export function StatsDashboard(p: {
  global: GlobalStats;
  lastYear: StatBalanceVariation[];
}): React.ReactElement {
  return (
    <>
      <Grid container spacing={2}>
        <StatTile
          title="Global balance"
          value={<AmountWidget amount={p.global.global_balance} />}
          icon={<FunctionsIcon />}
        />
        <StatTile
          title="Number of movements"
          value={p.global.number_movements}
          icon={<ImportExportIcon />}
        />
        <StatTile
          title="Number of files"
          value={p.global.number_files}
          icon={<FolderCopyIcon />}
        />
        <StatTile
          title="Total size of files"
          value={filesize(p.global.total_files_size)}
          icon={<ScaleIcon />}
        />
      </Grid>

      <Grid container spacing={2}>
        <Grid size={6}>
          <StatChart label="Last week" start={time() - 3600 * 24 * 7} {...p} />
        </Grid>
        <Grid size={6}>
          <StatChart
            label="Last month"
            start={time() - 3600 * 24 * 31}
            {...p}
          />
        </Grid>
        <Grid size={12}>
          <StatChart label="Last year" {...p} />
        </Grid>
      </Grid>
    </>
  );
}

export function StatTile(p: {
  title: string;
  value: number | string | React.ReactElement;
  icon: React.ReactElement;
}): React.ReactElement {
  return (
    <Grid size={{ sm: 6, md: 4, lg: 3 }}>
      <Paper
        elevation={5}
        style={{
          display: "flex",
          flexDirection: "row",
          alignItems: "center",
          padding: "10px",
          height: "80%",
        }}
      >
        {p.icon}
        <Typography variant="h6" style={{ margin: "0em 1em", flex: 1 }}>
          {p.title}
        </Typography>
        {p.value}
      </Paper>
    </Grid>
  );
}

export function StatChart(p: {
  label: string;
  start?: number;
  lastYear: StatBalanceVariation[];
}): React.ReactElement {
  const accounts = useAccounts();

  return (
    <div style={{ marginBottom: "50px", marginTop: "20px" }}>
      <Typography
        variant="subtitle1"
        style={{ textAlign: "center", fontWeight: "bold" }}
      >
        {p.label}
      </Typography>
      <LineChart
        dataset={p.lastYear}
        yAxis={[
          {
            width: 70,
          },
        ]}
        xAxis={[
          {
            id: "Date",
            dataKey: "time",
            scaleType: "time",
            min: p.start,
            valueFormatter: fmtDateFromTime,
          },
        ]}
        series={[
          {
            id: 0,
            label: "Total",
            dataKey: "sum",
            area: false,
            showMark: false,
          },
          ...accounts.list.list.map((a) => {
            return {
              id: a.id,
              label: a.name,
              dataKey: a.id.toString(),
              area: false,
              showMark: false,
            };
          }),
        ]}
        height={400}
        hideLegend
      />
    </div>
  );
}
