import {
  Button,
  Checkbox,
  Paper,
  TextField,
  Box,
  Typography,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Radio,
  RadioGroup,
  Divider,
} from "@mui/material";
import { observer } from "mobx-react-lite";
import { ArrowLeft, Loader2, Save } from "lucide-react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
import {
  userStore,
  languageStore,
  LoadingSpinner,
  mediaStore,
  isMediaIdEmpty,
  SelectMediaDialog,
  UploadMediaDialog,
  PreviewMediaDialog,
  authStore,
  cityStore,
  MultiSelect,
  selectedCityStore,
  type User,
  type UserCity,
} from "@shared";
import { useEffect, useState } from "react";
import { ImageUploadCard, DeleteModal } from "@widgets";

const ROLE_RESOURCES = [
  { key: "snapshot", label: "Экспорт" },
  { key: "devices", label: "Устройства" },
  { key: "vehicles", label: "Транспорт" },
  { key: "users", label: "Пользователи" },
  { key: "sights", label: "Достопримечательности" },
  { key: "stations", label: "Остановки" },
  { key: "routes", label: "Маршруты" },
  { key: "countries", label: "Страны" },
  { key: "cities", label: "Города" },
  { key: "carriers", label: "Перевозчики" },
] as const;

type PermissionLevel = "none" | "ro" | "rw";

function getPermissionLevel(roles: string[], resource: string): PermissionLevel {
  if (roles.includes(`${resource}_rw`)) return "rw";
  if (roles.includes(`${resource}_ro`)) return "ro";
  return "none";
}

function applyPermissionChange(
  roles: string[],
  resource: string,
  level: PermissionLevel,
): string[] {
  const filtered = roles.filter(
    (r) => r !== `${resource}_ro` && r !== `${resource}_rw`,
  );
  if (level === "ro") return [...filtered, `${resource}_ro`];
  if (level === "rw") return [...filtered, `${resource}_rw`];
  return filtered;
}

export const UserEditPage = observer(() => {
  const navigate = useNavigate();
  const [isLoading, setIsLoading] = useState(false);
  const [isLoadingData, setIsLoadingData] = useState(true);

  const { id } = useParams();
  const { editUserData, editUser, getUser, setEditUserData, setEditUserRoles } = userStore;
  const canReadCities = authStore.canRead("cities");

  const [localRoles, setLocalRoles] = useState<string[]>([]);
  const [localCityIds, setLocalCityIds] = useState<number[]>([]);
  const [initialUserCities, setInitialUserCities] = useState<UserCity[]>([]);

  const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
  const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false);
  const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false);
  const [mediaId, setMediaId] = useState("");
  const [isDeleteIconModalOpen, setIsDeleteIconModalOpen] = useState(false);
  const [activeMenuType, setActiveMenuType] = useState<
    "thumbnail" | "watermark_lu" | "watermark_rd" | "image" | null
  >(null);

  useEffect(() => {
    selectedCityStore.setIsLocked(true);
    return () => selectedCityStore.setIsLocked(false);
  }, []);

  useEffect(() => {
    languageStore.setLanguage("ru");
  }, []);

  useEffect(() => {
    const allRw = ROLE_RESOURCES.every(({ key }) => localRoles.includes(`${key}_rw`));
    const isAdmin = allRw && !localRoles.includes("devices_maintenance_rw");
    if (isAdmin !== editUserData.is_admin) {
      setEditUserData(
        editUserData.name || "",
        editUserData.email || "",
        editUserData.password || "",
        isAdmin,
        editUserData.icon || ""
      );
    }
  }, [localRoles]);

  useEffect(() => {
    (async () => {
      if (id) {
        setIsLoadingData(true);
        try {
          if (!authStore.me) {
            await authStore.getMeAction().catch(() => undefined);
          }
          await Promise.all([
            mediaStore.getMedia(),
            authStore.canRead("cities")
              ? cityStore.getRuCities()
              : authStore.fetchMeCities().catch(() => undefined),
          ]);
          const data = (await getUser(Number(id))) as User | undefined;

          if (data) {
            setEditUserData(
              data.name || "",
              data.email || "",
              data.password || "",
              data.is_admin || false,
              data.icon || "",
            );

            const roles = data.roles ?? [];
            setLocalRoles(roles);
            setEditUserRoles(roles);

            const cityIds = (data.cities ?? []).map((c) => c.city_id);
            setLocalCityIds(cityIds);
            setInitialUserCities(data.cities ?? []);
          }
        } finally {
          setIsLoadingData(false);
        }
      } else {
        setIsLoadingData(false);
      }
    })();
  }, [id]);

  const handleSave = async () => {
    try {
      setIsLoading(true);

      const mandatoryRoles = ["articles_ro", "articles_rw", "media_ro", "media_rw"];
      const rolesToSave = Array.from(new Set([...localRoles, ...mandatoryRoles]));
      setEditUserRoles(rolesToSave);
      await editUser(Number(id));

      await userStore.addUserCityAction({
        id: Number(id),
        city_ids: localCityIds,
      });

      toast.success("Пользователь успешно обновлён");
      navigate("/user");
    } catch {
      toast.error("Ошибка при обновлении пользователя");
    } finally {
      setIsLoading(false);
    }
  };

  const handleMediaSelect = (media: {
    id: string;
    filename: string;
    media_name?: string;
    media_type: number;
  }) => {
    setEditUserData(
      editUserData.name || "",
      editUserData.email || "",
      editUserData.password || "",
      editUserData.is_admin || false,
      media.id,
    );
  };

  const selectedMedia =
    editUserData.icon && !isMediaIdEmpty(editUserData.icon)
      ? mediaStore.media.find((m) => m.id === editUserData.icon)
      : null;
  const effectiveIconUrl = isMediaIdEmpty(editUserData.icon)
    ? null
    : (selectedMedia?.id ?? editUserData.icon ?? null);

  const cityOptionsMap = new Map<number, string>();

  const sourceCities: UserCity[] = canReadCities
    ? cityStore.ruCities.data
        .filter((city) => city.id !== undefined)
        .map((city) => ({
          city_id: city.id as number,
          name: city.name,
        }))
    : authStore.meCities.ru;

  for (const city of sourceCities) {
    cityOptionsMap.set(city.city_id, city.name);
  }

  for (const city of initialUserCities) {
    if (!cityOptionsMap.has(city.city_id)) {
      cityOptionsMap.set(city.city_id, city.name);
    }
  }

  const cityOptions = Array.from(cityOptionsMap.entries()).map(([value, label]) => ({
    value,
    label,
  }));

  if (isLoadingData) {
    return (
      <Box
        sx={{
          display: "flex",
          justifyContent: "center",
          alignItems: "center",
          minHeight: "60vh",
        }}
      >
        <LoadingSpinner message="Загрузка данных пользователя..." />
      </Box>
    );
  }

  return (
    <Paper className="w-full p-6 flex flex-col gap-8">
      <button className="flex items-center gap-2 self-start" onClick={() => navigate(-1)}>
        <ArrowLeft size={20} />
        Назад
      </button>

      {/* ── Основные данные ── */}
      <section className="flex flex-col gap-6">
        <Typography variant="h6">Основные данные</Typography>

        <TextField
          fullWidth
          label="Имя"
          value={editUserData.name || ""}
          required
          onChange={(e) =>
            setEditUserData(
              e.target.value,
              editUserData.email || "",
              editUserData.password || "",
              editUserData.is_admin || false,
              editUserData.icon,
            )
          }
        />
        <TextField
          fullWidth
          label="Email"
          value={editUserData.email || ""}
          required
          onChange={(e) =>
            setEditUserData(
              editUserData.name || "",
              e.target.value,
              editUserData.password || "",
              editUserData.is_admin || false,
              editUserData.icon,
            )
          }
        />
        <TextField
          fullWidth
          label="Пароль"
          placeholder="Оставить пустым, чтобы не менять"
          value={editUserData.password || ""}
          onChange={(e) =>
            setEditUserData(
              editUserData.name || "",
              editUserData.email || "",
              e.target.value,
              editUserData.is_admin || false,
              editUserData.icon,
            )
          }
        />

        <div className="w-full flex flex-col gap-4 max-w-[300px]">
          <ImageUploadCard
            title="Аватар"
            imageKey="thumbnail"
            imageUrl={effectiveIconUrl}
            onImageClick={() => {
              setIsPreviewMediaOpen(true);
              setMediaId(effectiveIconUrl ?? "");
            }}
            onDeleteImageClick={() => setIsDeleteIconModalOpen(true)}
            onSelectFileClick={() => {
              setActiveMenuType("image");
              setIsSelectMediaOpen(true);
            }}
            setUploadMediaOpen={() => {
              setIsUploadMediaOpen(true);
              setActiveMenuType("image");
            }}
          />
        </div>
      </section>

      <Divider />

      {/* ── Права доступа ── */}
      <section className="flex flex-col gap-4">
        <Typography variant="h6">Права доступа</Typography>

        <Box sx={{ display: "flex", gap: 1 }}>
          <Button
            variant="outlined"
            size="small"
            onClick={() => {
              setEditUserData(editUserData.name || "", editUserData.email || "", editUserData.password || "", true, editUserData.icon || "");
              const next: string[] = [];
              for (const { key } of ROLE_RESOURCES) {
                next.push(`${key}_rw`);
              }
              next.push("snapshot_create");
              setLocalRoles(next);
            }}
          >
            Полный доступ (admin)
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={() => {
              setEditUserData(editUserData.name || "", editUserData.email || "", editUserData.password || "", false, editUserData.icon || "");
              setLocalRoles(["devices_ro", "vehicles_ro", "devices_maintenance_rw"]);
            }}
          >
            Администратор ТО
          </Button>
        </Box>

        <Box sx={{ border: "1px solid", borderColor: "divider", borderRadius: 1 }}>
          <Table size="small">
            <TableHead>
              <TableRow sx={{ bgcolor: "action.hover" }}>
                <TableCell sx={{ fontWeight: 600, width: 220 }}>Ресурс</TableCell>
                <TableCell align="center" sx={{ fontWeight: 600 }}>Нет доступа</TableCell>
                <TableCell align="center" sx={{ fontWeight: 600 }}>Чтение</TableCell>
                <TableCell align="center" sx={{ fontWeight: 600 }}>Чтение/Запись</TableCell>
                <TableCell align="center" sx={{ fontWeight: 600 }}>
                  Доп. права
                </TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {ROLE_RESOURCES.map(({ key, label }) => {
                const level = getPermissionLevel(localRoles, key);
                const isSnapshotResource = key === "snapshot";

                const handleChange = (val: string) => {
                  setLocalRoles((prev) => {
                    let updated = applyPermissionChange(prev, key, val as PermissionLevel);

                    if (key === "devices") {
                      updated = applyPermissionChange(
                        updated,
                        "vehicles",
                        val as PermissionLevel,
                      );
                    }

                    return updated;
                  });
                };

                const isDevicesResource = key === "devices";

                const handleSnapshotCreateChange = (checked: boolean) => {
                  if (!isSnapshotResource) {
                    return;
                  }
                  setLocalRoles((prev) => {
                    const withoutSnapshotCreate = prev.filter(
                      (role) => role !== "snapshot_create"
                    );
                    return checked
                      ? [...withoutSnapshotCreate, "snapshot_create"]
                      : withoutSnapshotCreate;
                  });
                };

                const handleMaintenanceChange = (checked: boolean) => {
                  setLocalRoles((prev) => {
                    const without = prev.filter((r) => r !== "devices_maintenance_rw");
                    return checked ? [...without, "devices_maintenance_rw"] : without;
                  });
                };

                return (
                  <TableRow key={key} hover>
                    <TableCell>{label}</TableCell>
                    <TableCell align="center" padding="checkbox">
                      <RadioGroup
                        row
                        value={level}
                        onChange={(e) => handleChange(e.target.value)}
                        sx={{ justifyContent: "center", flexWrap: "nowrap" }}
                      >
                        <Radio value="none" size="small" />
                      </RadioGroup>
                    </TableCell>
                    <TableCell align="center" padding="checkbox">
                      {isSnapshotResource ? (
                        <Typography variant="body2" color="text.secondary">
                          -
                        </Typography>
                      ) : (
                        <RadioGroup
                          row
                          value={level}
                          onChange={(e) => handleChange(e.target.value)}
                          sx={{ justifyContent: "center", flexWrap: "nowrap" }}
                        >
                          <Radio value="ro" size="small" />
                        </RadioGroup>
                      )}
                    </TableCell>
                    <TableCell align="center" padding="checkbox">
                      <RadioGroup
                        row
                        value={level}
                        onChange={(e) => handleChange(e.target.value)}
                        sx={{ justifyContent: "center", flexWrap: "nowrap" }}
                      >
                        <Radio value="rw" size="small" />
                      </RadioGroup>
                    </TableCell>
                    <TableCell align="center" padding="checkbox">
                      {isSnapshotResource ? (
                        <Checkbox
                          checked={localRoles.includes("snapshot_create")}
                          onChange={(e) =>
                            handleSnapshotCreateChange(e.target.checked)
                          }
                          size="small"
                          title="Разрешает создавать новые снапшоты"
                        />
                      ) : isDevicesResource ? (
                        <Box sx={{ display: "flex", gap: 0.5, justifyContent: "center" }}>
                          <Checkbox
                            checked={localRoles.includes("devices_maintenance_rw")}
                            onChange={(e) => handleMaintenanceChange(e.target.checked)}
                            size="small"
                            title="Техническое обслуживание (ТО)"
                          />
                        </Box>
                      ) : (
                        <Typography variant="body2" color="text.secondary">
                          -
                        </Typography>
                      )}
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </Box>
      </section>

      <Divider />

      {/* ── Города ── */}
      <section className="flex flex-col gap-4">
        <Typography variant="h6">Города</Typography>
        <MultiSelect
          options={cityOptions}
          value={localCityIds}
          onChange={(ids) => setLocalCityIds(ids as number[])}
          label="Города"
          placeholder="Выберите города"
          loading={canReadCities ? !cityStore.ruCities.loaded : isLoadingData}
        />
      </section>

      <Button
        variant="contained"
        className="self-end"
        startIcon={isLoading ? <Loader2 size={20} className="animate-spin" /> : <Save size={20} />}
        onClick={handleSave}
        disabled={isLoading || !editUserData.name || !editUserData.email}
      >
        Сохранить
      </Button>

      <SelectMediaDialog
        open={isSelectMediaOpen}
        onClose={() => setIsSelectMediaOpen(false)}
        onSelectMedia={handleMediaSelect}
        mediaType={1}
      />
      <UploadMediaDialog
        open={isUploadMediaOpen}
        onClose={() => setIsUploadMediaOpen(false)}
        contextObjectName={editUserData.name || "Пользователь"}
        contextType="user"
        afterUpload={handleMediaSelect}
        hardcodeType={activeMenuType}
      />
      <PreviewMediaDialog
        open={isPreviewMediaOpen}
        onClose={() => setIsPreviewMediaOpen(false)}
        mediaId={mediaId}
      />
      <DeleteModal
        open={isDeleteIconModalOpen}
        onDelete={() => {
          setEditUserData(
            editUserData.name || "",
            editUserData.email || "",
            editUserData.password || "",
            editUserData.is_admin || false,
            "",
          );
          setIsDeleteIconModalOpen(false);
        }}
        onCancel={() => setIsDeleteIconModalOpen(false)}
        edit
      />
    </Paper>
  );
});
