import { useState, useMemo, useCallback } from "react";
import {
  Box,
  Chip,
  IconButton,
  TextField,
  Button,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogContentText,
  DialogActions,
  Snackbar,
  Alert,
  Tooltip,
  Typography,
} from "@mui/material";
import { DataGrid, GridColDef, GridRenderCellParams, GridRowParams } from "@mui/x-data-grid";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
import ClearIcon from "@mui/icons-material/Clear";
import RadioButtonCheckedIcon from "@mui/icons-material/RadioButtonChecked";
import RadioButtonUncheckedIcon from "@mui/icons-material/RadioButtonUnchecked";
import { useAppStore } from "../store";
import {
  createUpdateSelectionGroup,
  deleteSelectionGroup,
  loadSelectionGroup,
} from "../myapi/client";

interface SelectionGroupRow {
  id: string;
  name: string;
  isCurrent: boolean;
  isActive: boolean;
  selections: Record<string, number>; // geometry -> count
  rawData: Record<string, number[]>; // geometry -> indices array
}

export default function SelectionGroupsPanel() {
  const { roomId, selections, selectionGroups, activeSelectionGroup, updateSelectionForGeometry } =
    useAppStore();

  // Local state
  const [currentGroupName, setCurrentGroupName] = useState("");
  const [editingGroupName, setEditingGroupName] = useState<string | null>(null);
  const [editNameValue, setEditNameValue] = useState("");
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  const [groupToDelete, setGroupToDelete] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [snackbar, setSnackbar] = useState<{
    open: boolean;
    message: string;
    severity: "success" | "error";
  }>({
    open: false,
    message: "",
    severity: "success",
  });

  // Get all unique geometry keys across all groups and current selection
  const allGeometryKeys = useMemo(() => {
    const keys = new Set<string>();

    // Add keys from current selection
    Object.keys(selections).forEach((key) => {
      if (selections[key] && selections[key].length > 0) {
        keys.add(key);
      }
    });

    // Add keys from all saved groups
    Object.values(selectionGroups).forEach((group) => {
      Object.keys(group).forEach((key) => {
        if (group[key] && group[key].length > 0) {
          keys.add(key);
        }
      });
    });

    return Array.from(keys).sort();
  }, [selections, selectionGroups]);

  // Prepare rows for DataGrid
  const rows = useMemo((): SelectionGroupRow[] => {
    const result: SelectionGroupRow[] = [];

    // Current selection row (always first)
    const currentSelectionCounts: Record<string, number> = {};
    allGeometryKeys.forEach((key) => {
      currentSelectionCounts[key] = selections[key]?.length || 0;
    });

    result.push({
      id: "current",
      name: "", // Will show input field
      isCurrent: true,
      isActive: false,
      selections: currentSelectionCounts,
      rawData: selections,
    });

    // Saved group rows
    const groupNames = Object.keys(selectionGroups).sort();
    groupNames.forEach((groupName) => {
      const groupData = selectionGroups[groupName];
      const groupCounts: Record<string, number> = {};

      allGeometryKeys.forEach((key) => {
        groupCounts[key] = groupData[key]?.length || 0;
      });

      result.push({
        id: groupName,
        name: groupName,
        isCurrent: false,
        isActive: activeSelectionGroup === groupName,
        selections: groupCounts,
        rawData: groupData,
      });
    });

    return result;
  }, [selections, selectionGroups, activeSelectionGroup, allGeometryKeys]);

  // Generate dynamic columns
  const columns = useMemo((): GridColDef[] => {
    const cols: GridColDef[] = [
      // Name column with radio button
      {
        field: "name",
        headerName: "Name",
        width: 200,
        flex: 1,
        renderCell: (params: GridRenderCellParams<SelectionGroupRow>) => {
          const row = params.row;

          if (row.isCurrent) {
            // Current selection row - show input
            return (
              <Box sx={{ display: "flex", alignItems: "center", gap: 1, width: "100%", height: "100%" }}>
                <TextField
                  size="small"
                  fullWidth
                  placeholder="Type name to save..."
                  value={currentGroupName}
                  onChange={(e) => setCurrentGroupName(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter" && currentGroupName.trim()) {
                      handleSaveCurrentSelection();
                    }
                  }}
                  onBlur={() => {
                    if (currentGroupName.trim()) {
                      handleSaveCurrentSelection();
                    }
                  }}
                  disabled={isLoading || !hasCurrentSelection}
                  sx={{ "& .MuiInputBase-root": { fontSize: "0.875rem" } }}
                />
              </Box>
            );
          }

          // Saved group row
          const isEditing = editingGroupName === row.id;

          return (
            <Box sx={{ display: "flex", alignItems: "center", gap: 1, width: "100%", height: "100%" }}>
              {row.isActive ? (
                <RadioButtonCheckedIcon sx={{ color: "success.main" }} fontSize="small" />
              ) : (
                <RadioButtonUncheckedIcon sx={{ color: "action.disabled" }} fontSize="small" />
              )}
              {isEditing ? (
                <TextField
                  size="small"
                  fullWidth
                  autoFocus
                  value={editNameValue}
                  onChange={(e) => setEditNameValue(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") {
                      handleSaveNameEdit(row.id);
                    } else if (e.key === "Escape") {
                      setEditingGroupName(null);
                    }
                  }}
                  onBlur={() => handleSaveNameEdit(row.id)}
                  sx={{ "& .MuiInputBase-root": { fontSize: "0.875rem" } }}
                />
              ) : (
                <Typography
                  sx={{
                    fontWeight: row.isActive ? "bold" : "normal",
                    fontSize: "0.875rem",
                    flex: 1,
                  }}
                  onDoubleClick={() => {
                    setEditingGroupName(row.id);
                    setEditNameValue(row.name);
                  }}
                >
                  {row.name}
                </Typography>
              )}
            </Box>
          );
        },
      },
    ];

    // Add dynamic geometry columns
    allGeometryKeys.forEach((geometryKey) => {
      cols.push({
        field: geometryKey,
        headerName: geometryKey,
        width: 100,
        align: "center",
        headerAlign: "center",
        renderCell: (params: GridRenderCellParams<SelectionGroupRow>) => {
          const row = params.row;
          const count = row.selections[geometryKey] || 0;

          if (count === 0) {
            return (
              <Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }}>
                <Typography sx={{ color: "text.disabled", fontSize: "0.875rem" }}>-</Typography>
              </Box>
            );
          }

          let chipColor: "primary" | "success" | "default" = "default";
          if (row.isCurrent) {
            chipColor = "primary";
          } else if (row.isActive) {
            chipColor = "success";
          }

          return (
            <Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }}>
              <Chip label={count} size="small" color={chipColor} />
            </Box>
          );
        },
      });
    });

    // Actions column
    cols.push({
      field: "actions",
      headerName: "Actions",
      width: 100,
      sortable: false,
      renderCell: (params: GridRenderCellParams<SelectionGroupRow>) => {
        const row = params.row;

        if (row.isCurrent) {
          // Current selection - Clear button
          return (
            <Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }}>
              <Tooltip title="Clear all current selections">
                <span>
                  <IconButton
                    size="small"
                    onClick={(e) => {
                      e.stopPropagation();
                      handleClearCurrent();
                    }}
                    disabled={!hasCurrentSelection || isLoading}
                  >
                    <ClearIcon fontSize="small" />
                  </IconButton>
                </span>
              </Tooltip>
            </Box>
          );
        }

        // Saved group - Edit and Delete buttons
        return (
          <Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 0.5, height: "100%" }}>
            <Tooltip title="Edit name">
              <IconButton
                size="small"
                onClick={(e) => {
                  e.stopPropagation();
                  setEditingGroupName(row.id);
                  setEditNameValue(row.name);
                }}
                disabled={isLoading}
              >
                <EditIcon fontSize="small" />
              </IconButton>
            </Tooltip>
            <Tooltip title="Delete group">
              <IconButton
                size="small"
                onClick={(e) => {
                  e.stopPropagation();
                  setGroupToDelete(row.id);
                  setDeleteDialogOpen(true);
                }}
                disabled={isLoading}
              >
                <DeleteIcon fontSize="small" />
              </IconButton>
            </Tooltip>
          </Box>
        );
      },
    });

    return cols;
  }, [allGeometryKeys, currentGroupName, editingGroupName, editNameValue, isLoading]);

  // Check if current selection has any data
  const hasCurrentSelection = useMemo(
    () => Object.values(selections).some((indices) => indices && indices.length > 0),
    [selections]
  );

  // Handlers
  const handleSaveCurrentSelection = useCallback(async () => {
    if (!roomId || !currentGroupName.trim()) return;

    // Check for duplicate name
    if (selectionGroups[currentGroupName.trim()]) {
      setSnackbar({
        open: true,
        message: `Group "${currentGroupName.trim()}" already exists`,
        severity: "error",
      });
      return;
    }

    setIsLoading(true);
    try {
      await createUpdateSelectionGroup(roomId, currentGroupName.trim(), selections);
      setCurrentGroupName("");
      setSnackbar({
        open: true,
        message: `Group "${currentGroupName.trim()}" saved`,
        severity: "success",
      });
    } catch (err) {
      console.error("Failed to save selection group:", err);
      setSnackbar({
        open: true,
        message: "Failed to save selection group",
        severity: "error",
      });
    } finally {
      setIsLoading(false);
    }
  }, [roomId, currentGroupName, selections, selectionGroups]);

  const handleSaveNameEdit = useCallback(
    async (oldName: string) => {
      if (!roomId || !editNameValue.trim() || editNameValue.trim() === oldName) {
        setEditingGroupName(null);
        return;
      }

      // Check for duplicate name
      if (selectionGroups[editNameValue.trim()] && editNameValue.trim() !== oldName) {
        setSnackbar({
          open: true,
          message: `Group "${editNameValue.trim()}" already exists`,
          severity: "error",
        });
        setEditingGroupName(null);
        return;
      }

      setIsLoading(true);
      try {
        // Delete old group
        await deleteSelectionGroup(roomId, oldName);
        // Create new group with new name
        await createUpdateSelectionGroup(roomId, editNameValue.trim(), selectionGroups[oldName]);
        setEditingGroupName(null);
        setSnackbar({
          open: true,
          message: `Group renamed to "${editNameValue.trim()}"`,
          severity: "success",
        });
      } catch (err) {
        console.error("Failed to rename group:", err);
        setSnackbar({
          open: true,
          message: "Failed to rename group",
          severity: "error",
        });
        setEditingGroupName(null);
      } finally {
        setIsLoading(false);
      }
    },
    [roomId, editNameValue, selectionGroups]
  );

  const handleRowClick = useCallback(
    async (params: GridRowParams<SelectionGroupRow>) => {
      const row = params.row;

      // Don't load current selection row or if already editing
      if (row.isCurrent || editingGroupName) return;

      if (!roomId) return;

      setIsLoading(true);
      try {
        await loadSelectionGroup(roomId, row.id);
        setSnackbar({
          open: true,
          message: `Loaded group "${row.name}"`,
          severity: "success",
        });
      } catch (err) {
        console.error("Failed to load selection group:", err);
        setSnackbar({
          open: true,
          message: `Failed to load group "${row.name}"`,
          severity: "error",
        });
      } finally {
        setIsLoading(false);
      }
    },
    [roomId, editingGroupName]
  );

  const handleClearCurrent = useCallback(() => {
    if (!hasCurrentSelection) return;

    // Clear all geometry selections
    allGeometryKeys.forEach((key) => {
      if (selections[key] && selections[key].length > 0) {
        updateSelectionForGeometry(key, []);
      }
    });
  }, [hasCurrentSelection, allGeometryKeys, selections, updateSelectionForGeometry]);

  const handleDeleteConfirm = useCallback(async () => {
    if (!roomId || !groupToDelete) return;

    setIsLoading(true);
    setDeleteDialogOpen(false);

    try {
      await deleteSelectionGroup(roomId, groupToDelete);
      setSnackbar({
        open: true,
        message: `Group "${groupToDelete}" deleted`,
        severity: "success",
      });
    } catch (err) {
      console.error("Failed to delete group:", err);
      setSnackbar({
        open: true,
        message: `Failed to delete group "${groupToDelete}"`,
        severity: "error",
      });
    } finally {
      setIsLoading(false);
      setGroupToDelete(null);
    }
  }, [roomId, groupToDelete]);

  return (
    <Box sx={{ height: "100%", width: "100%", display: "flex", flexDirection: "column", p: 2 }}>
      <Typography variant="h6" sx={{ mb: 1 }}>
        Selection Groups
      </Typography>

      {/* DataGrid */}
      <Box sx={{ flexGrow: 1, minHeight: 0 }}>
        <DataGrid
          rows={rows}
          columns={columns}
          disableRowSelectionOnClick
          disableColumnMenu
          hideFooter
          onRowClick={handleRowClick}
          getRowClassName={(params) => {
            if (params.row.isCurrent) return "current-selection-row";
            if (params.row.isActive) return "active-group-row";
            return "";
          }}
          sx={{
            "& .MuiDataGrid-columnHeaders": {
              minHeight: "48px !important",
              maxHeight: "48px !important",
            },
            "& .MuiDataGrid-columnHeader": {
              padding: "8px",
            },
            "& .current-selection-row": {
              bgcolor: "rgba(33, 150, 243, 0.08)",
              borderTop: "2px solid",
              borderTopColor: "primary.main",
              "&:hover": {
                bgcolor: "rgba(33, 150, 243, 0.12)",
              },
            },
            "& .active-group-row": {
              bgcolor: "rgba(76, 175, 80, 0.08)",
              "&:hover": {
                bgcolor: "rgba(76, 175, 80, 0.12)",
              },
            },
            "& .MuiDataGrid-row": {
              cursor: "pointer",
            },
            "& .MuiDataGrid-row.current-selection-row": {
              cursor: "default",
            },
          }}
        />
      </Box>

      {/* Delete Confirmation Dialog */}
      <Dialog open={deleteDialogOpen} onClose={() => setDeleteDialogOpen(false)}>
        <DialogTitle>Delete Selection Group</DialogTitle>
        <DialogContent>
          <DialogContentText>
            Are you sure you want to delete the group "{groupToDelete}"? This action cannot be
            undone.
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setDeleteDialogOpen(false)}>Cancel</Button>
          <Button onClick={handleDeleteConfirm} color="error" variant="contained">
            Delete
          </Button>
        </DialogActions>
      </Dialog>

      {/* Snackbar for feedback */}
      <Snackbar
        open={snackbar.open}
        autoHideDuration={3000}
        onClose={() => setSnackbar({ ...snackbar, open: false })}
        anchorOrigin={{ vertical: "top", horizontal: "center" }}
      >
        <Alert severity={snackbar.severity} onClose={() => setSnackbar({ ...snackbar, open: false })}>
          {snackbar.message}
        </Alert>
      </Snackbar>
    </Box>
  );
}
