import {
  Button,
  TextField,
  Select,
  MenuItem,
  FormControl,
  InputLabel,
  Typography,
  Box,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
} from "@mui/material";
import {
  MediaViewer,
  VideoPreviewCard,
  ImageUploadCard,
} from "@widgets";
import { observer } from "mobx-react-lite";
import { ArrowLeft, Loader2, Save, Plus, X } from "lucide-react";
import { useEffect, useState, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import {
  carrierStore,
  articlesStore,
  routeStore,
  languageStore,
  mediaStore,
  isMediaIdEmpty,
  ArticleSelectOrCreateDialog,
  SelectMediaDialog,
  selectedCityStore,
  UploadMediaDialog,
  PreviewMediaDialog,
} from "@shared";
import type { Route } from "@shared";

export const RouteCreatePage = observer(() => {
  const navigate = useNavigate();

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

  const [carrier, setCarrier] = useState<string>("");
  const [routeNumber, setRouteNumber] = useState("");
  const [routeCoords, setRouteCoords] = useState("");
  const [govRouteNumber, setGovRouteNumber] = useState("");
  const [governorAppeal, setGovernorAppeal] = useState<string>("");
  const [direction, setDirection] = useState("backward");
  const [scaleMin, setScaleMin] = useState("10");
  const [scaleMax, setScaleMax] = useState("100");
  const [routeName, setRouteName] = useState("");
  const [turn, setTurn] = useState("");
  const [centerLat, setCenterLat] = useState("");
  const [centerLng, setCenterLng] = useState("");
  const [videoTimer, setVideoTimer] = useState(420);
  const [videoPreview, setVideoPreview] = useState<string>("");
  const [icon, setIcon] = useState<string>("");
  const [isLoading, setIsLoading] = useState(false);
  const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
    useState(false);
  const [isSelectVideoDialogOpen, setIsSelectVideoDialogOpen] = useState(false);
  const [isVideoPreviewOpen, setIsVideoPreviewOpen] = useState(false);
  const [isUploadVideoDialogOpen, setIsUploadVideoDialogOpen] = useState(false);
  const [isSelectIconDialogOpen, setIsSelectIconDialogOpen] = useState(false);
  const [isUploadIconDialogOpen, setIsUploadIconDialogOpen] = useState(false);
  const [isPreviewIconOpen, setIsPreviewIconOpen] = useState(false);
  const [previewIconId, setPreviewIconId] = useState("");
  const [activeIconMenuType, setActiveIconMenuType] = useState<
    "thumbnail" | "watermark_lu" | "watermark_rd" | "image" | null
  >(null);
  const [fileToUpload, setFileToUpload] = useState<File | null>(null);
  const { language } = languageStore;

  useEffect(() => {
    carrierStore.getCarriers(language);
    articlesStore.getArticleList();
    mediaStore.getMedia();
  }, [language]);

  const filteredCarriers = useMemo(() => {
    const carriers =
      carrierStore.carriers[language as keyof typeof carrierStore.carriers]
        .data || [];

    if (!selectedCityStore.selectedCityId) {
      return carriers;
    }

    return carriers.filter(
      (carrier: any) => carrier.city_id === selectedCityStore.selectedCityId
    );
  }, [carrierStore.carriers, language, selectedCityStore.selectedCityId]);

  const validateCoordinates = (value: string) => {
    try {
      const lines = value.trim().split("\n");
      const coordinates = lines.map((line) => {
        const [lat, lon] = line
          .trim()
          .split(/[\s,]+/)
          .map(Number);
        return [lat, lon];
      });

      if (coordinates.length === 0) {
        return "Введите хотя бы одну пару координат";
      }

      if (
        !coordinates.every(
          (point) => Array.isArray(point) && point.length === 2
        )
      ) {
        return "Каждая строка должна содержать две координаты";
      }

      if (
        !coordinates.every((point) =>
          point.every((coord) => !isNaN(coord) && typeof coord === "number")
        )
      ) {
        return "Координаты должны быть числами";
      }

      return true;
    } catch {
      return "Неверный формат координат";
    }
  };

  const handleArticleSelect = (articleId: number) => {
    setGovernorAppeal(articleId.toString());
    setIsSelectArticleDialogOpen(false);
    articlesStore.getArticleList();
  };

  const handleVideoSelect = (media: {
    id: string;
    filename: string;
    media_name?: string;
    media_type: number;
  }) => {
    setVideoPreview(media.id);
    setIsSelectVideoDialogOpen(false);
  };

  const handleVideoFileSelect = (file?: File) => {
    if (file) {
      setFileToUpload(file);
      setIsUploadVideoDialogOpen(true);
    } else {
      setIsSelectVideoDialogOpen(true);
    }
  };

  const handleVideoUpload = (media: {
    id: string;
    filename: string;
    media_name?: string;
    media_type: number;
  }) => {
    setVideoPreview(media.id);
    setIsUploadVideoDialogOpen(false);
    setFileToUpload(null);
  };

  const handleVideoPreviewClick = () => {
    setIsVideoPreviewOpen(true);
  };

  const handleIconSelect = (media: {
    id: string;
    filename: string;
    media_name?: string;
    media_type: number;
  }) => {
    setIcon(media.id);
    setIsSelectIconDialogOpen(false);
  };

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

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

      if (!routeName.trim()) {
        toast.error("Заполните название маршрута");
        setIsLoading(false);
        return;
      }
      if (!carrier) {
        toast.error("Выберите перевозчика");
        setIsLoading(false);
        return;
      }
      if (!routeNumber.trim()) {
        toast.error("Заполните номер маршрута");
        setIsLoading(false);
        return;
      }
      if (!govRouteNumber.trim()) {
        toast.error("Заполните номер маршрута в Говорящем Городе");
        setIsLoading(false);
        return;
      }

      const validationResult = validateCoordinates(routeCoords);
      if (validationResult !== true) {
        toast.error(validationResult);
        setIsLoading(false);
        return;
      }

      const scale_min = scaleMin ? Number(scaleMin) : null;
      const scale_max = scaleMax ? Number(scaleMax) : null;

      if (
        scale_min === 0 ||
        scale_max === 0 ||
        scale_min === null ||
        scale_max === null
      ) {
        toast.error("Масштабы не могут быть равны 0");
        setIsLoading(false);
        return;
      }

      if (
        scale_min !== null &&
        scale_max !== null &&
        scale_max !== undefined &&
        scale_min > scale_max
      ) {
        toast.error("Максимальный масштаб не может быть меньше минимального");
        setIsLoading(false);
        return;
      }

      const carrier_id = Number(carrier);
      const governor_appeal = governorAppeal
        ? Number(governorAppeal)
        : undefined;
      const rotate = turn ? Number(turn) : undefined;
      const center_latitude = centerLat ? Number(centerLat) : undefined;
      const center_longitude = centerLng ? Number(centerLng) : undefined;
      const route_direction = direction === "forward";

      const path = routeCoords
        .trim()
        .split("\n")
        .map((line) => {
          const [lat, lon] = line
            .trim()
            .split(/[\s,]+/)
            .map(Number);
          return [lat, lon];
        });

      const newRoute: Partial<Route> = {
        carrier:
          carrierStore.carriers[
            language as keyof typeof carrierStore.carriers
          ].data?.find((c: any) => c.id === carrier_id)?.full_name || "",
        carrier_id,
        route_number: routeNumber.trim(),
        route_sys_number: govRouteNumber.trim(),
        route_name: routeName.trim(),
        route_direction,
        scale_min: scale_min !== null ? scale_min : 0,
        scale_max: scale_max !== null ? scale_max : 0,
        rotate,
        center_latitude,
        center_longitude,
        path,
        video_preview: !isMediaIdEmpty(videoPreview) ? videoPreview : undefined,
        icon: !isMediaIdEmpty(icon) ? icon : undefined,
        video_timer: videoTimer,
      };

      if (governor_appeal !== undefined) {
        newRoute.governor_appeal = governor_appeal;
      }

      const newId = await routeStore.createRoute(newRoute);
      toast.success("Маршрут успешно создан");
      navigate(`/route/${newId}/edit`);
    } catch (error) {
      console.error(error);
      toast.error("Произошла ошибка при создании маршрута");
    } finally {
      setIsLoading(false);
    }
  };

  const selectedArticle = articlesStore.articleList.ru.data.find(
    (article) => article.id === Number(governorAppeal)
  );

  return (
    <div className="w-full h-full p-3 flex flex-col gap-10">
      <div className="flex items-center gap-4">
        <button
          className="flex items-center gap-2"
          onClick={() => navigate(-1)}
        >
          <ArrowLeft size={20} />
          Назад
        </button>
      </div>

      <div className="flex flex-col gap-10 w-full items-end">
        <Box className="flex flex-col gap-6 w-full">
          <TextField
            className="w-full"
            label="Название маршрута"
            required
            value={routeName}
            onChange={(e) => setRouteName(e.target.value)}
          />
          <FormControl fullWidth required>
            <InputLabel>Выберите перевозчика</InputLabel>
            <Select
              value={carrier}
              label="Выберите перевозчика"
              onChange={(e) => setCarrier(e.target.value as string)}
              disabled={filteredCarriers.length === 0}
            >
              <MenuItem value="">Не выбрано</MenuItem>
              {filteredCarriers.map((carrier: any) => (
                <MenuItem key={carrier.id} value={carrier.id}>
                  {carrier.full_name}
                </MenuItem>
              ))}
            </Select>
          </FormControl>
          <TextField
            className="w-full"
            label="Номер маршрута"
            required
            value={routeNumber}
            onChange={(e) => setRouteNumber(e.target.value)}
          />
          <TextField
            className="w-full"
            label="Координаты маршрута"
            multiline
            minRows={2}
            maxRows={10}
            value={routeCoords}
            onChange={(e) => {
              const newValue = e.target.value;
              setRouteCoords(newValue);
            }}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                const lines = routeCoords.split("\n");
                const lastLine = lines[lines.length - 1];

                if (lastLine && lastLine.trim()) {
                  e.preventDefault();
                  const newValue = routeCoords + "\n";
                  setRouteCoords(newValue);
                }
              }
            }}
            error={validateCoordinates(routeCoords) !== true}
            helperText={
              typeof validateCoordinates(routeCoords) === "string"
                ? validateCoordinates(routeCoords)
                : "Формат: широта долгота"
            }
            placeholder="55.7558 37.6173&#10;55.7539 37.6208"
            sx={{
              mt: 1,
              "& .MuiInputBase-root": {
                maxHeight: "500px",
                overflow: "auto",
              },
              "& .MuiInputBase-input": {
                fontFamily: "monospace",
                fontSize: "0.8rem",
                lineHeight: "1.2",
              },
              "& .MuiFormHelperText-root": {
                fontSize: "0.75rem",
                marginTop: "2px",
              },
            }}
          />

          <TextField
            className="w-full"
            label="Номер маршрута в Говорящем Городе"
            required
            value={govRouteNumber}
            onChange={(e) => setGovRouteNumber(e.target.value)}
          />

          <Typography variant="subtitle1" sx={{ fontWeight: 600 }}>
            Обращение к пассажирам
          </Typography>
          <Box className="flex gap-2">
            <TextField
              className="flex-1"
              value={selectedArticle?.heading || "Статья не выбрана"}
              placeholder="Выберите статью"
              disabled
              fullWidth
              sx={{
                "& .MuiInputBase-input": {
                  color: selectedArticle ? "inherit" : "#999",
                },
              }}
            />
            {selectedArticle && (
              <Button
                variant="outlined"
                color="error"
                onClick={() => setGovernorAppeal("")}
                startIcon={<X size={16} />}
                sx={{ minWidth: "auto", px: 2 }}
              >
                Сбросить
              </Button>
            )}
            <Button
              variant="outlined"
              onClick={() => setIsSelectArticleDialogOpen(true)}
              startIcon={<Plus size={16} />}
              sx={{ minWidth: "auto", px: 2 }}
            >
              Выбрать
            </Button>
          </Box>

          <Box className="w-full flex justify-center gap-4 flex-wrap">
            <div className="flex flex-col gap-4 max-w-[300px]">
              <ImageUploadCard
                title="Иконка маршрута"
                imageKey="thumbnail"
                imageUrl={effectiveIconUrl}
                onImageClick={() => {
                  setIsPreviewIconOpen(true);
                  setPreviewIconId(selectedIconMedia?.id ?? icon ?? "");
                }}
                onDeleteImageClick={() => {
                  setIcon("");
                  setActiveIconMenuType(null);
                }}
                onSelectFileClick={() => {
                  setActiveIconMenuType("image");
                  setIsSelectIconDialogOpen(true);
                }}
                setUploadMediaOpen={() => {
                  setIsUploadIconDialogOpen(true);
                  setActiveIconMenuType("image");
                }}
              />
            </div>
            <div className="flex flex-col gap-4 max-w-[300px]">
              <VideoPreviewCard
                title="Видеозаставка"
                videoId={effectiveVideoId}
                onVideoClick={handleVideoPreviewClick}
                onDeleteVideoClick={() => setVideoPreview("")}
                onSelectVideoClick={handleVideoFileSelect}
                className="w-full"
              />
            </div>
          </Box>

          <FormControl fullWidth required>
            <InputLabel>Прямой/обратный маршрут</InputLabel>
            <Select
              value={direction}
              label="Прямой/обратный маршрут"
              onChange={(e) => setDirection(e.target.value)}
            >
              <MenuItem value="forward">Прямой</MenuItem>
              <MenuItem value="backward">Обратный</MenuItem>
            </Select>
          </FormControl>
          <TextField
            className="w-full"
            label="Масштаб (мин)"
            type="number"
            value={scaleMin}
            onChange={(e) => {
              let value = e.target.value;
              if (Number(value) > 297) {
                value = "297";
              }

              if (Number(value) < 10) {
                value = "10";
              }

              setScaleMin(value);
              if (value && scaleMax && Number(value) > Number(scaleMax)) {
                setScaleMax(value);
              }
            }}
            error={
              scaleMin !== "" &&
              scaleMax !== "" &&
              Number(scaleMin) > Number(scaleMax)
            }
            required
            helperText={
              scaleMin !== "" &&
              scaleMax !== "" &&
              Number(scaleMin) > Number(scaleMax)
                ? "Минимальный масштаб не может быть больше максимального"
                : ""
            }
          />
          <TextField
            className="w-full"
            label="Масштаб (макс)"
            type="number"
            value={scaleMax}
            required
            onChange={(e) => {
              if (Number(e.target.value) > 300) {
                e.target.value = "300";
              }

              const value = e.target.value;
              setScaleMax(value);
            }}
          />

          <TextField
            className="w-full"
            label="Поворот"
            value={turn}
            onChange={(e) => setTurn(e.target.value)}
          />
          <TextField
            className="w-full"
            label="Центр. широта"
            value={centerLat}
            onChange={(e) => setCenterLat(e.target.value)}
          />
          <TextField
            className="w-full"
            label="Центр. долгота"
            value={centerLng}
            onChange={(e) => setCenterLng(e.target.value)}
          />
          <TextField
            className="w-full"
            label="Таймер видео заставки (сек)"
            type="number"
            value={videoTimer}
            onChange={(e) => {
              const val = Math.max(1, Math.round(Number(e.target.value)));
              if (Number.isFinite(val)) {
                setVideoTimer(val);
              }
            }}
          />
        </Box>
        <div className="flex w-full justify-end">
          <Button
            variant="contained"
            color="primary"
            className="w-min flex gap-2 items-center"
            startIcon={<Save size={20} />}
            onClick={handleCreateRoute}
            disabled={isLoading}
          >
            {isLoading ? (
              <Loader2 size={20} className="animate-spin" />
            ) : (
              "Сохранить"
            )}
          </Button>
        </div>
      </div>
      <ArticleSelectOrCreateDialog
        open={isSelectArticleDialogOpen}
        onClose={() => setIsSelectArticleDialogOpen(false)}
        onSelectArticle={handleArticleSelect}
      />
      <SelectMediaDialog
        open={isSelectVideoDialogOpen}
        onClose={() => setIsSelectVideoDialogOpen(false)}
        onSelectMedia={handleVideoSelect}
        mediaType={2}
      />
      {effectiveVideoId && (
        <Dialog
          open={isVideoPreviewOpen}
          onClose={() => setIsVideoPreviewOpen(false)}
          maxWidth="md"
          fullWidth
        >
          <DialogTitle>Предпросмотр видео</DialogTitle>
          <DialogContent>
            <Box className="flex justify-center items-center p-4">
              <MediaViewer
                media={{
                  id: effectiveVideoId,
                  media_type: 2,
                  filename: "video_preview",
                }}
              />
            </Box>
          </DialogContent>
          <DialogActions>
            <Button onClick={() => setIsVideoPreviewOpen(false)}>
              Закрыть
            </Button>
          </DialogActions>
        </Dialog>
      )}
      <UploadMediaDialog
        open={isUploadVideoDialogOpen}
        onClose={() => {
          setIsUploadVideoDialogOpen(false);
          setFileToUpload(null);
        }}
        hardcodeType="video_preview"
        contextObjectName={routeName || "Маршрут"}
        contextType="sight"
        initialFile={fileToUpload || undefined}
        afterUpload={handleVideoUpload}
      />

      <SelectMediaDialog
        open={isSelectIconDialogOpen}
        onClose={() => setIsSelectIconDialogOpen(false)}
        onSelectMedia={handleIconSelect}
        mediaType={1}
      />

      <UploadMediaDialog
        open={isUploadIconDialogOpen}
        onClose={() => setIsUploadIconDialogOpen(false)}
        contextObjectName={routeName || "Маршрут"}
        contextType="route"
        afterUpload={handleIconSelect}
        hardcodeType={activeIconMenuType}
      />

      <PreviewMediaDialog
        open={isPreviewIconOpen}
        onClose={() => setIsPreviewIconOpen(false)}
        mediaId={previewIconId}
      />
    </div>
  );
});
