import { useState, useEffect } from "react";
import {
  Stack,
  Typography,
  Accordion,
  AccordionSummary,
  AccordionDetails,
  useTheme,
  TextField,
  Autocomplete,
  TableCell,
  TableContainer,
  Table,
  TableHead,
  TableRow,
  Paper,
  TableBody,
  Checkbox,
  FormControlLabel,
  Tabs,
  Tab,
  Box,
} from "@mui/material";
import { observer } from "mobx-react-lite";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";

import {
  AnimatedCircleButton,
  authInstance,
  languageStore,
  selectedCityStore,
} from "@shared";

type Field<T> = {
  label: string;
  data: keyof T;
  render?: (value: any) => React.ReactNode;
};

type LinkedSightsProps<T> = {
  parentId: string | number;
  fields: Field<T>[];
  setItemsParent?: (items: T[]) => void;
  type: "show" | "edit";
  onUpdate?: () => void;
  disableCreation?: boolean;
  updatedLinkedItems?: T[];
  refresh?: number;
};

export const LinkedSights = <
  T extends { id: number; name: string; [key: string]: any }
>(
  props: LinkedSightsProps<T>
) => {
  const theme = useTheme();

  return (
    <>
      <Accordion sx={{ width: "100%" }}>
        <AccordionSummary
          expandIcon={<ExpandMoreIcon />}
          sx={{
            background: theme.palette.background.paper,
            borderBottom: `1px solid ${theme.palette.divider}`,
            width: "100%",
          }}
        >
          <Typography variant="subtitle1" fontWeight="bold">
            Привязанные достопримечательности
          </Typography>
        </AccordionSummary>

        <AccordionDetails
          sx={{ background: theme.palette.background.paper, width: "100%" }}
        >
          <Stack gap={2} width="100%">
            <LinkedSightsContents {...props} />
          </Stack>
        </AccordionDetails>
      </Accordion>
    </>
  );
};

const LinkedSightsContentsInner = <
  T extends { id: number; name: string; [key: string]: any }
>({
  parentId,
  setItemsParent,
  fields,
  type,
  onUpdate,
  disableCreation = false,
  updatedLinkedItems,
  refresh,
}: LinkedSightsProps<T>) => {
  const { language } = languageStore;

  const [allItems, setAllItems] = useState<T[]>([]);
  const [linkedItems, setLinkedItems] = useState<T[]>([]);
  const [selectedItemId, setSelectedItemId] = useState<number | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);
  const [activeTab, setActiveTab] = useState(0);
  const [selectedItems, setSelectedItems] = useState<Set<number>>(new Set());
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedToDetach, setSelectedToDetach] = useState<Set<number>>(
    new Set()
  );
  const [isLinkingSingle, setIsLinkingSingle] = useState(false);
  const [isLinkingBulk, setIsLinkingBulk] = useState(false);
  const [isBulkDetaching, setIsBulkDetaching] = useState(false);
  const [detachingIds, setDetachingIds] = useState<Set<number>>(new Set());

  useEffect(() => {}, [error]);

  const parentResource = "station";
  const childResource = "sight";

  const buildPayload = (ids: number[]) => ({
    [`${childResource}_ids`]: ids,
  });

  const availableItems = allItems
    .filter((item) => !linkedItems.some((linked) => linked.id === item.id))
    .filter((item) => {
      // Фильтруем по городу из навбара
      const selectedCityId = selectedCityStore.selectedCityId;
      if (selectedCityId && "city_id" in item) {
        return item.city_id === selectedCityId;
      }
      return true;
    })
    .sort((a, b) => a.name.localeCompare(b.name));

  const filteredAvailableItems = availableItems.filter((item) => {
    if (!searchQuery.trim()) return true;
    return String(item.name).toLowerCase().includes(searchQuery.toLowerCase());
  });

  useEffect(() => {
    if (updatedLinkedItems) {
      setLinkedItems(updatedLinkedItems);
    }
  }, [updatedLinkedItems]);

  useEffect(() => {
    setItemsParent?.(linkedItems);
  }, [linkedItems, setItemsParent]);

  useEffect(() => {
    setSelectedToDetach((prev) => {
      const updated = new Set<number>();
      linkedItems.forEach((item) => {
        if (prev.has(item.id)) {
          updated.add(item.id);
        }
      });
      return updated;
    });
  }, [linkedItems]);

  const linkItem = () => {
    if (selectedItemId !== null) {
      setError(null);
      const requestData = buildPayload([selectedItemId]);

      setIsLinkingSingle(true);
      authInstance
        .post(`/${parentResource}/${parentId}/${childResource}`, requestData)
        .then(() => {
          const newItem = allItems.find((item) => item.id === selectedItemId);
          if (newItem) {
            setLinkedItems([...linkedItems, newItem]);
          }
          setSelectedItemId(null);
          onUpdate?.();
        })
        .catch((error) => {
          console.error("Error linking sight:", error);
          setError("Failed to link sight");
        })
        .finally(() => {
          setIsLinkingSingle(false);
        });
    }
  };

  const deleteItem = (itemId: number) => {
    setError(null);
    setDetachingIds((prev) => {
      const next = new Set(prev);
      next.add(itemId);
      return next;
    });
    authInstance
      .delete(`/${parentResource}/${parentId}/${childResource}`, {
        data: buildPayload([itemId]),
      })
      .then(() => {
        setLinkedItems(linkedItems.filter((item) => item.id !== itemId));
        onUpdate?.();
      })
      .catch((error) => {
        console.error("Error deleting sight:", error);
        setError("Failed to delete sight");
      })
      .finally(() => {
        setDetachingIds((prev) => {
          const next = new Set(prev);
          next.delete(itemId);
          return next;
        });
      });
  };

  const handleCheckboxChange = (itemId: number) => {
    const updated = new Set(selectedItems);
    if (updated.has(itemId)) {
      updated.delete(itemId);
    } else {
      updated.add(itemId);
    }
    setSelectedItems(updated);
  };

  const handleBulkLink = async () => {
    if (selectedItems.size === 0) return;
    setError(null);

    setIsLinkingBulk(true);
    const idsToLink = Array.from(selectedItems);

    try {
      await authInstance.post(
        `/${parentResource}/${parentId}/${childResource}`,
        buildPayload(idsToLink)
      );

      const newItems = allItems.filter((item) => idsToLink.includes(item.id));
      setLinkedItems((prev) => {
        const existingIds = new Set(prev.map((item) => item.id));
        const additions = newItems.filter((item) => !existingIds.has(item.id));
        return [...prev, ...additions];
      });
      setSelectedItems((prev) => {
        const remaining = new Set(prev);
        idsToLink.forEach((id) => remaining.delete(id));
        return remaining;
      });
      onUpdate?.();
    } catch (error) {
      console.error("Error linking sights:", error);
      setError("Failed to link sights");
    }

    setIsLinkingBulk(false);
  };

  const toggleDetachSelection = (itemId: number) => {
    const updated = new Set(selectedToDetach);
    if (updated.has(itemId)) {
      updated.delete(itemId);
    } else {
      updated.add(itemId);
    }
    setSelectedToDetach(updated);
  };

  const handleToggleAllDetach = (checked: boolean) => {
    if (!checked) {
      setSelectedToDetach(new Set());
      return;
    }
    setSelectedToDetach(new Set(linkedItems.map((item) => item.id)));
  };

  const handleBulkDetach = async () => {
    const idsToDetach = Array.from(selectedToDetach);
    if (idsToDetach.length === 0) return;
    setError(null);

    setIsBulkDetaching(true);
    setDetachingIds((prev) => {
      const next = new Set(prev);
      idsToDetach.forEach((id) => next.add(id));
      return next;
    });

    try {
      await authInstance.delete(
        `/${parentResource}/${parentId}/${childResource}`,
        {
          data: buildPayload(idsToDetach),
        }
      );

      setLinkedItems((prev) =>
        prev.filter((item) => !idsToDetach.includes(item.id))
      );
      setSelectedToDetach((prev) => {
        const remaining = new Set(prev);
        idsToDetach.forEach((id) => remaining.delete(id));
        return remaining;
      });
      onUpdate?.();
    } catch (error) {
      console.error("Error deleting sights:", error);
      setError("Failed to delete sights");
    }

    setDetachingIds((prev) => {
      const next = new Set(prev);
      idsToDetach.forEach((id) => next.delete(id));
      return next;
    });
    setIsBulkDetaching(false);
  };

  const allSelectedForDetach =
    linkedItems.length > 0 &&
    linkedItems.every((item) => selectedToDetach.has(item.id));
  const isIndeterminateDetach =
    selectedToDetach.size > 0 && !allSelectedForDetach;

  useEffect(() => {
    if (parentId) {
      setIsLoading(true);
      setError(null);
      authInstance
        .get(`/${parentResource}/${parentId}/${childResource}`)
        .then((response) => {
          setLinkedItems(response?.data || []);
        })
        .catch((error) => {
          console.error("Error fetching linked sights:", error);
          setError("Failed to load linked sights");
          setLinkedItems([]);
        })
        .finally(() => {
          setIsLoading(false);
        });
    }
  }, [parentId, language, refresh]);

  useEffect(() => {
    if (type === "edit") {
      setError(null);
      authInstance
        .get(`/${childResource}`)
        .then((response) => {
          setAllItems(response?.data || []);
        })
        .catch((error) => {
          console.error("Error fetching all sights:", error);
          setError(null);
          setAllItems([]);
        });
    }
  }, [type]);

  return (
    <>
      {linkedItems?.length > 0 && (
        <TableContainer component={Paper} sx={{ width: "100%" }}>
          <Table sx={{ width: "100%" }}>
            <TableHead>
              <TableRow>
                {type === "edit" && (
                  <TableCell width="50px">
                    <Checkbox
                      size="small"
                      checked={allSelectedForDetach}
                      indeterminate={isIndeterminateDetach}
                      onChange={(e) => handleToggleAllDetach(e.target.checked)}
                    />
                  </TableCell>
                )}
                <TableCell key="id" width="60px">
                  №
                </TableCell>
                {fields.map((field) => (
                  <TableCell key={String(field.data)}>{field.label}</TableCell>
                ))}
                {type === "edit" && (
                  <TableCell width="120px">Действие</TableCell>
                )}
              </TableRow>
            </TableHead>

            <TableBody>
              {linkedItems.map((item, index) => (
                <TableRow key={item.id} hover>
                  {type === "edit" && (
                    <TableCell>
                      <Checkbox
                        size="small"
                        checked={selectedToDetach.has(item.id)}
                        onChange={() => toggleDetachSelection(item.id)}
                      />
                    </TableCell>
                  )}
                  <TableCell>{index + 1}</TableCell>
                  {fields.map((field, idx) => (
                    <TableCell key={String(field.data) + String(idx)}>
                      {field.render
                        ? field.render(item[field.data])
                        : item[field.data]}
                    </TableCell>
                  ))}
                  {type === "edit" && (
                    <TableCell>
                      <AnimatedCircleButton
                        variant="outlined"
                        color="error"
                        size="small"
                        onClick={(e) => {
                          e.stopPropagation();
                          deleteItem(item.id);
                        }}
                        disabled={detachingIds.has(item.id)}
                        loading={detachingIds.has(item.id)}
                      >
                        Отвязать
                      </AnimatedCircleButton>
                    </TableCell>
                  )}
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
      )}

      {type === "edit" && linkedItems.length > 0 && (
        <Stack direction="row" gap={2} mt={2}>
          <AnimatedCircleButton
            variant="outlined"
            color="error"
            onClick={handleBulkDetach}
            disabled={selectedToDetach.size === 0 || isBulkDetaching}
            loading={isBulkDetaching}
          >
            Отвязать выбранные ({selectedToDetach.size})
          </AnimatedCircleButton>
        </Stack>
      )}

      {linkedItems.length === 0 && !isLoading && (
        <Typography color="textSecondary" textAlign="center" py={2}>
          Достопримечательности не найдены
        </Typography>
      )}

      {type === "edit" && !disableCreation && (
        <Stack gap={2} mt={2}>
          <Typography variant="subtitle1">
            Добавить достопримечательности
          </Typography>
          <Tabs
            value={activeTab}
            onChange={(_, value) => setActiveTab(value)}
            variant="fullWidth"
          >
            <Tab label="По одной" />
            <Tab label="Массово" />
          </Tabs>

          <Box sx={{ mt: 1 }}>
            {activeTab === 0 && (
              <Stack gap={2}>
                <Autocomplete
                  fullWidth
                  value={
                    availableItems?.find(
                      (item) => item.id === selectedItemId
                    ) || null
                  }
                  onChange={(_, newValue) =>
                    setSelectedItemId(newValue?.id || null)
                  }
                  options={availableItems}
                  getOptionLabel={(item) => String(item.name)}
                  renderInput={(params) => (
                    <TextField
                      {...params}
                      label="Выберите достопримечательность"
                      fullWidth
                    />
                  )}
                  isOptionEqualToValue={(option, value) =>
                    option.id === value?.id
                  }
                  filterOptions={(options, { inputValue }) => {
                    const searchWords = inputValue
                      .toLowerCase()
                      .split(" ")
                      .filter(Boolean);
                    return options.filter((option) => {
                      const optionWords = String(option.name)
                        .toLowerCase()
                        .split(" ");
                      return searchWords.every((searchWord) =>
                        optionWords.some((word) => word.startsWith(searchWord))
                      );
                    });
                  }}
                  renderOption={(props, option) => (
                    <li {...props} key={option.id}>
                      {String(option.name)}
                    </li>
                  )}
                />

                <AnimatedCircleButton
                  variant="contained"
                  onClick={linkItem}
                  disabled={!selectedItemId || isLinkingSingle}
                  loading={isLinkingSingle}
                  sx={{ alignSelf: "flex-start" }}
                >
                  Добавить
                </AnimatedCircleButton>
              </Stack>
            )}

            {activeTab === 1 && (
              <Stack gap={2}>
                <TextField
                  fullWidth
                  label="Поиск достопримечательностей"
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                  placeholder="Введите название..."
                  size="small"
                />

                <Paper sx={{ maxHeight: 300, overflow: "auto", p: 2 }}>
                  <Stack gap={1}>
                    {filteredAvailableItems.map((item) => (
                      <FormControlLabel
                        key={item.id}
                        control={
                          <Checkbox
                            checked={selectedItems.has(item.id)}
                            onChange={() => handleCheckboxChange(item.id)}
                            size="small"
                          />
                        }
                        label={String(item.name)}
                        sx={{
                          margin: 0,
                          "& .MuiFormControlLabel-label": {
                            fontSize: "0.9rem",
                          },
                        }}
                      />
                    ))}
                    {filteredAvailableItems.length === 0 && (
                      <Typography
                        color="textSecondary"
                        textAlign="center"
                        py={1}
                      >
                        {searchQuery.trim()
                          ? "Достопримечательности не найдены"
                          : "Нет доступных достопримечательностей"}
                      </Typography>
                    )}
                  </Stack>
                </Paper>

                <AnimatedCircleButton
                  variant="contained"
                  onClick={handleBulkLink}
                  disabled={selectedItems.size === 0 || isLinkingBulk}
                  loading={isLinkingBulk}
                  sx={{ alignSelf: "flex-start" }}
                >
                  Добавить выбранные ({selectedItems.size})
                </AnimatedCircleButton>
              </Stack>
            )}
          </Box>
        </Stack>
      )}

      {isLoading && (
        <Typography color="textSecondary" textAlign="center" py={2}>
          Загрузка...
        </Typography>
      )}

      {error && (
        <Typography color="error" textAlign="center" py={2}>
          {error}
        </Typography>
      )}
    </>
  );
};

export const LinkedSightsContents = observer(
  LinkedSightsContentsInner
) as typeof LinkedSightsContentsInner;
