import { makeAutoObservable, runInAction } from "mobx";
import {
  authInstance,
  languageInstance,
  languageStore,
  isMediaIdEmpty,
} from "@shared";

export type Route = {
  route_name: string;
  carrier: string;
  carrier_id: number;
  center_latitude: number;
  center_longitude: number;
  governor_appeal: number;
  id: number;
  icon: string;
  path: number[][];
  rotate: number;
  route_direction: boolean;
  route_number: string;
  route_sys_number: string;
  scale_max: number;
  scale_min: number;
  video_preview: string;
  video_timer: number;
};

class RouteStore {
  routes: {
    data: Route[];
    loaded: boolean;
  } = {
    data: [],
    loaded: false,
  };

  route: Record<string, Route> = {};

  constructor() {
    makeAutoObservable(this);
  }

  getRoutes = async () => {
    if (this.routes.loaded) return;
    const response = await authInstance.get("/route");

    runInAction(() => {
      this.routes = {
        data: response.data,
        loaded: true,
      };
    });
  };

  createRoute = async (route: any): Promise<number> => {
    const response = await authInstance.post("/route", route);
    const id = response.data.id;

    runInAction(() => {
      this.route[id] = { ...route, id };
      this.routes.data = [...this.routes.data, { ...route, id }];
    });

    return id;
  };

  deleteRoute = async (id: number) => {
    await authInstance.delete(`/route/${id}`);

    runInAction(() => {
      this.routes = {
        data: this.routes.data.filter((route) => route.id !== id),
        loaded: true,
      };
    });
  };

  routeStations: Record<string, any[]> = {};

  getRoute = async (id: number) => {
    if (this.route[id]) return this.route[id];
    const response = await authInstance.get(`/route/${id}`);
    const stations = await authInstance.get(`/route/${id}/station`);

    runInAction(() => {
      this.route[id] = response.data;
      this.routeStations[id] = stations.data;
    });

    return response.data;
  };

  setRouteStations = (routeId: number, stationId: number, data: any) => {
    this.routeStations[routeId] = this.routeStations[routeId]?.map((station) =>
      station.id === stationId ? { ...station, ...data } : station
    );
  };

  saveRouteStations = async (routeId: number, stationId: number) => {
    const { language } = languageStore;

    const stationResponse = await languageInstance(language).get(
      `/station/${stationId}`
    );
    const fullStationData = stationResponse.data;

    // Получаем отредактированные данные из локального кеша
    const editedStationData = this.routeStations[routeId]?.find(
      (station) => station.id === stationId
    );

    const dataToSend: any = {
      station_id: stationId,
      offset_x: editedStationData?.offset_x ?? fullStationData.offset_x ?? 0,
      offset_y: editedStationData?.offset_y ?? fullStationData.offset_y ?? 0,
      align: editedStationData?.align ?? fullStationData.align ?? 0,
      transfers: fullStationData.transfers || {},
    };

    await authInstance.patch(`/route/${routeId}/station`, dataToSend);

    // Обновляем локальный кеш после успешного сохранения
    runInAction(() => {
      if (this.routeStations[routeId]) {
        this.routeStations[routeId] = this.routeStations[routeId].map(
          (station) =>
            station.id === stationId
              ? {
                  ...station,
                  ...dataToSend,
                }
              : station
        );
      }
    });
  };

  editRouteData = {
    route_name: "",
    carrier: "",
    carrier_id: 0,
    center_latitude: "",
    center_longitude: "",
    governor_appeal: 0,
    id: 0,
    icon: "",
    path: [] as number[][],
    rotate: 0,
    route_direction: false,
    route_number: "",
    route_sys_number: "",
    scale_max: 0,
    scale_min: 0,
    video_preview: "" as string | undefined,
    video_timer: 420,
  };

  setEditRouteData = (data: any) => {
    this.editRouteData = { ...this.editRouteData, ...data };
  };

  editRoute = async (id: number) => {
    if (
      !this.editRouteData.video_preview ||
      isMediaIdEmpty(this.editRouteData.video_preview)
    ) {
      delete this.editRouteData.video_preview;
    }
    if (!this.editRouteData.icon || isMediaIdEmpty(this.editRouteData.icon)) {
      delete (this.editRouteData as any).icon;
    }
    const dataToSend: any = {
      ...this.editRouteData,
      route_name: (this.editRouteData.route_name || "").trim(),
      route_number: (this.editRouteData.route_number || "").trim(),
      route_sys_number: (this.editRouteData.route_sys_number || "").trim(),
      center_latitude: parseFloat(this.editRouteData.center_latitude),
      center_longitude: parseFloat(this.editRouteData.center_longitude),
    };
    if (
      this.editRouteData.governor_appeal === 0 ||
      !this.editRouteData.governor_appeal
    ) {
      dataToSend.governor_appeal = null;
    }
    const response = await authInstance.patch(`/route/${id}`, dataToSend);

    runInAction(() => {
      this.route[id] = response.data;
      this.routes.data = this.routes.data.map((route) =>
        route.id === id ? response.data : route
      );
    });
  };

  copyRouteAction = async (id: number) => {
    const response = await authInstance.post(`/route/${id}/copy`);

    runInAction(() => {
      this.routes.data = [...this.routes.data, response.data];
    });
  };

  sightCounts: Map<number, number> = new Map();
  stationCounts: Map<number, number> = new Map();
  countsLoading = false;

  loadCounts = async (routeIds: number[]) => {
    if (routeIds.length === 0) return;

    runInAction(() => {
      this.countsLoading = true;
    });

    const batchSize = 20;
    for (let i = 0; i < routeIds.length; i += batchSize) {
      const batch = routeIds.slice(i, i + batchSize);
      const results = await Promise.allSettled(
        batch.flatMap((id) => [
          authInstance.get(`/route/${id}/sight/count`).then((res) => ({ id, type: "sight", data: res.data })),
          authInstance.get(`/route/${id}/station/count`).then((res) => ({ id, type: "station", data: res.data })),
        ])
      );

      runInAction(() => {
        for (const result of results) {
          if (result.status === "fulfilled") {
            const { id, type, data } = result.value;
            let count = 0;
            if (typeof data === "number") {
              count = data;
            } else if (data && typeof data === "object") {
              count = Object.values(data).reduce((sum: number, v: any) => sum + (Number(v) || 0), 0);
            }
            if (type === "sight") this.sightCounts.set(id, count);
            else this.stationCounts.set(id, count);
          }
        }
      });
    }

    runInAction(() => {
      this.countsLoading = false;
    });
  };

  selectedStationId = 0;

  setSelectedStationId = (id: number) => {
    this.selectedStationId = id;
  };
}

export const routeStore = new RouteStore();
