import { createSelector } from "@reduxjs/toolkit";
import { Box, IconButton, MenuItem, Select } from "@mui/material";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import { GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
import { RootState } from "@/app/redux/store";
import { TABLE_COLUMNS } from "../constants";
import { selectTransactionStatuses } from "@/app/redux/metadata/selectors";
import { DataRowBase } from "../types";

const TRANSACTION_STATUS_FALLBACK: string[] = [
  "pending",
  "completed",
  "failed",
  "inprogress",
  "error",
];

type StatusChangeHandler = (rowId: number, newStatus: string) => void;

const selectEnableStatusActions = (
  _state: RootState,
  enableStatusActions: boolean
) => enableStatusActions;

const selectExtraColumns = (
  _state: RootState,
  _enableStatusActions: boolean,
  extraColumns?: string[] | null
) => extraColumns ?? null;

const selectShowExtraColumns = (
  _state: RootState,
  _enableStatusActions: boolean,
  _extraColumns?: string[] | null,
  showExtraColumns = false
) => showExtraColumns;

const selectLocalRows = (
  _state: RootState,
  _enableStatusActions: boolean,
  _extraColumns?: string[] | null,
  _showExtraColumns?: boolean,
  localRows?: DataRowBase[]
) => localRows ?? [];

const noopStatusChangeHandler: StatusChangeHandler = () => {};

const selectStatusChangeHandler = (
  _state: RootState,
  _enableStatusActions: boolean,
  _extraColumns?: string[] | null,
  _showExtraColumns?: boolean,
  _localRows?: DataRowBase[],
  handleStatusChange?: StatusChangeHandler
) => handleStatusChange ?? noopStatusChangeHandler;

export const selectBaseColumns = createSelector(
  [selectEnableStatusActions],
  enableStatusActions => {
    if (!enableStatusActions) {
      return TABLE_COLUMNS;
    }

    return [
      ...TABLE_COLUMNS,
      {
        field: "actions",
        headerName: "Actions",
        width: 160,
        sortable: false,
        filterable: false,
      } as GridColDef,
    ];
  }
);

export const selectVisibleColumns = createSelector(
  [selectBaseColumns, selectExtraColumns, selectShowExtraColumns],
  (baseColumns, extraColumns, showExtraColumns) => {
    if (!extraColumns || extraColumns.length === 0) {
      return baseColumns;
    }

    return showExtraColumns
      ? baseColumns
      : baseColumns.filter(col => !extraColumns.includes(col.field));
  }
);

export const selectResolvedTransactionStatuses = createSelector(
  [selectTransactionStatuses],
  statuses => (statuses.length > 0 ? statuses : TRANSACTION_STATUS_FALLBACK)
);

export const selectEnhancedColumns = createSelector(
  [
    selectVisibleColumns,
    selectLocalRows,
    selectStatusChangeHandler,
    selectResolvedTransactionStatuses,
  ],
  (
    visibleColumns,
    localRows,
    handleStatusChange,
    resolvedStatusOptions
  ): GridColDef[] => {
    return visibleColumns.map(col => {
      if (col.field === "status") {
        return {
          ...col,
          renderCell: (params: GridRenderCellParams) => {
            const value = params.value?.toLowerCase();
            let bgColor = "#e0e0e0";
            let textColor = "#000";
            switch (value) {
              case "completed":
                bgColor = "#d0f0c0";
                textColor = "#1b5e20";
                break;
              case "pending":
                bgColor = "#fff4cc";
                textColor = "#9e7700";
                break;
              case "inprogress":
                bgColor = "#cce5ff";
                textColor = "#004085";
                break;
              case "error":
                bgColor = "#ffcdd2";
                textColor = "#c62828";
                break;
            }
            return (
              <Box
                sx={{
                  backgroundColor: bgColor,
                  color: textColor,
                  px: 1.5,
                  py: 0.5,
                  borderRadius: 1,
                  fontWeight: 500,
                  textTransform: "capitalize",
                  display: "inline-block",
                  width: "100%",
                  textAlign: "center",
                }}
              >
                {params.value}
              </Box>
            );
          },
        };
      }

      if (col.field === "userId") {
        return {
          ...col,
          headerAlign: "center",
          align: "center",
          renderCell: (params: GridRenderCellParams) => (
            <Box
              sx={{
                display: "grid",
                gridTemplateColumns: "1fr auto",
                alignItems: "center",
                width: "100%",
                px: 1,
              }}
              onClick={e => e.stopPropagation()}
            >
              <Box
                sx={{
                  fontWeight: 500,
                  fontSize: "0.875rem",
                  color: "text.primary",
                }}
              >
                {params.value}
              </Box>
              <IconButton
                href={`/users/${params.value}`}
                target="_blank"
                rel="noopener noreferrer"
                size="small"
                sx={{ p: 0.5, ml: 1 }}
                onClick={e => e.stopPropagation()}
              >
                <OpenInNewIcon fontSize="small" />
              </IconButton>
            </Box>
          ),
        };
      }

      if (col.field === "actions") {
        return {
          ...col,
          renderCell: (params: GridRenderCellParams) => {
            const currentRow = localRows.find(row => row.id === params.id);
            const options =
              currentRow?.options?.map(option => option.value) ??
              resolvedStatusOptions;
            const uniqueOptions: string[] = Array.from(new Set(options));

            return (
              <Select<string>
                value={currentRow?.status ?? ""}
                onChange={e =>
                  handleStatusChange(
                    params.id as number,
                    e.target.value as string
                  )
                }
                size="small"
                fullWidth
                displayEmpty
                sx={{
                  "& .MuiOutlinedInput-notchedOutline": { border: "none" },
                  "& .MuiSelect-select": { py: 0.5 },
                }}
                onClick={e => e.stopPropagation()}
              >
                {uniqueOptions.map(option => (
                  <MenuItem key={option} value={option}>
                    {option}
                  </MenuItem>
                ))}
              </Select>
            );
          },
        };
      }

      return col;
    }) as GridColDef[];
  }
);
