import AddIcon from "@mui/icons-material/Add";
import RefreshIcon from "@mui/icons-material/Refresh";
import { IconButton, Tooltip } from "@mui/material";
import { DataGrid, GridActionsCellItem, GridColDef } from "@mui/x-data-grid";
import { Account, AccountApi } from "../api/AccountApi";
import { useAccounts } from "../hooks/AccountsListProvider";
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
import { TimeWidget } from "../widgets/TimeWidget";
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
import { AccountIconWidget } from "../widgets/AccountIconWidget";
import { ServerApi } from "../api/ServerApi";

export function AccountsRoute(): React.ReactElement {
  const alert = useAlert();
  const confirm = useConfirm();
  const snackbar = useSnackbar();

  const accounts = useAccounts();

  const list = accounts.list.list;

  const createAccount = async () => {
    try {
      await AccountApi.Create(`New account #${list.length + 1}`);

      snackbar("New account successfully created!");

      await accounts.reload();
    } catch (e) {
      console.error("Failed to create new account!", e);
      alert(`Failed to create new account! ${e}`);
    }
  };

  const setDefaultAccount = async (account: Account) => {
    try {
      await AccountApi.SetDefaultAccount(account);

      snackbar("Default account successfully updated!");

      await accounts.reload();

      return accounts.get(account.id);
    } catch (e) {
      console.error("Failed to change default account!", e);
      alert(`Failed to change default account! ${e}`);
      return account;
    }
  };

  const updateAccount = async (account: Account) => {
    try {
      await AccountApi.Update(account);

      snackbar("Account successfully updated!");

      await accounts.reload();

      return accounts.get(account.id);
    } catch (e) {
      console.error("Failed to update account!", e);
      alert(`Failed to update account! ${e}`);
      return account;
    }
  };

  const deleteAccount = async (account: Account) => {
    try {
      if (
        !(await confirm(
          `Do you really want to delete account ${account.name}?`,
          "Delete account"
        ))
      )
        return;

      await AccountApi.Delete(account);

      snackbar("Account successfully deleted!");

      await accounts.reload();
    } catch (e) {
      console.error(`Failed to delete account!`, e);
      alert(`Failed to delete account! ${e}`);
    }
  };

  const columns: GridColDef<(typeof list)[number]>[] = [
    { field: "id", headerName: "ID", flex: 1 },
    {
      field: "type",
      headerName: "Type",
      flex: 2,
      editable: true,
      type: "singleSelect",
      valueOptions: ServerApi.Config.accounts_types.map((v) => {
        return { label: v.label, value: v.code };
      }),
      renderCell(params) {
        return (
          <span
            style={{
              display: "flex",
              flexDirection: "row",
              justifyContent: "start",
              alignItems: "center",
            }}
          >
            <AccountIconWidget account={params.row} />
            {
              ServerApi.Config.accounts_types.find(
                (t) => t.code === params.row.type
              )!.label
            }
          </span>
        );
      },
    },
    { field: "name", headerName: "Name", flex: 6, editable: true },
    {
      field: "time_create",
      headerName: "Time created",
      flex: 2,
      renderCell(params) {
        return <TimeWidget time={params.row.time_create} />;
      },
    },
    {
      field: "time_update",
      headerName: "Time updated",
      flex: 2,
      renderCell(params) {
        return <TimeWidget time={params.row.time_update} />;
      },
    },
    {
      field: "default_account",
      headerName: "Default",
      flex: 1,
      type: "boolean",
      editable: true,
    },
    {
      field: "actions",
      type: "actions",
      headerName: "",
      flex: 1,
      cellClassName: "actions",
      getActions: ({ row }) => {
        return [
          <GridActionsCellItem
            key={row.id}
            icon={<DeleteIcon />}
            label="Delete account"
            onClick={() => deleteAccount(row)}
            color="inherit"
          />,
        ];
      },
    },
  ];

  return (
    <MoneyMgrWebRouteContainer
      label="Accounts"
      actions={
        <span>
          <Tooltip title="Create a new account">
            <IconButton onClick={createAccount}>
              <AddIcon />
            </IconButton>
          </Tooltip>
          <Tooltip title="Refresh accounts list">
            <IconButton onClick={() => accounts.reload()}>
              <RefreshIcon />
            </IconButton>
          </Tooltip>
        </span>
      }
    >
      <DataGrid<Account>
        rows={list}
        columns={columns}
        disableRowSelectionOnClick
        processRowUpdate={(updated, original) => {
          if (updated.default_account && !original.default_account) {
            return setDefaultAccount(updated);
          }

          if (
            updated.name !== original.name ||
            updated.type !== original.type
          ) {
            return updateAccount(updated);
          }

          return original as any;
        }}
      />
    </MoneyMgrWebRouteContainer>
  );
}
