import {
  authInstance,
  languageInstance,
  Language,
  languageStore,
  countryStore,
  CashedCountries,
} from "@shared";
import { makeAutoObservable, runInAction } from "mobx";

export type City = {
  id?: number;
  name: string;
  country: string;
  country_code: string;
  arms: string;
  weather_city_code?: number;
};

export type CashedCities = {
  ru: {
    data: City[];
    loaded: boolean;
  };
  en: {
    data: City[];
    loaded: boolean;
  };
  zh: {
    data: City[];
    loaded: boolean;
  };
};

export type CashedCity = {
  ru: City | null;
  en: City | null;
  zh: City | null;
};

class CityStore {
  cities: CashedCities = {
    ru: {
      data: [],
      loaded: false,
    },
    en: {
      data: [],
      loaded: false,
    },
    zh: {
      data: [],
      loaded: false,
    },
  };

  city: Record<string, CashedCity> = {};

  constructor() {
    makeAutoObservable(this);
  }

  ruCities: {
    data: City[];
    loaded: boolean;
  } = {
    data: [],
    loaded: false,
  };

  getRuCities = async () => {
    if (this.ruCities.loaded) {
      return;
    }

    const response = await languageInstance("ru").get(`/city`);

    runInAction(() => {
      this.ruCities.data = response.data;
      this.ruCities.loaded = true;
    });
  };

  getCities = async (language: keyof CashedCities) => {
    if (this.cities[language].loaded) {
      return;
    }

    const response = await languageInstance(language).get(`/city`);

    runInAction(() => {
      this.cities[language].data = response.data;
      this.cities[language].loaded = true;
    });
  };

  getCity = async (code: string, language: keyof CashedCities) => {
    if (this.city[code]?.[language] && this.city[code][language] !== null) {
      return;
    }

    const response = await languageInstance(language).get(`/city/${code}`);

    runInAction(() => {
      if (!this.city[code]) {
        this.city[code] = {
          ru: null,
          en: null,
          zh: null,
        };
      }
      this.city[code][language] = response.data;
    });

    return response.data;
  };

  deleteCity = async (code: string) => {
    await authInstance.delete(`/city/${code}`);

    runInAction(() => {
      for (const secondaryLanguage of ["ru", "en", "zh"] as Language[]) {
        this.cities[secondaryLanguage].data = this.cities[
          secondaryLanguage
        ].data.filter((city) => city.id !== Number(code));
        if (this.city[code]) {
          this.city[code][secondaryLanguage] = null;
        }
      }
    });
  };

  createCityData = {
    country_code: "",
    arms: "",
    weather_city_code: 0,
    ru: {
      name: "",
    },
    en: {
      name: "",
    },
    zh: {
      name: "",
    },
  };

  setCreateCityData = (
    name: string,
    country_code: string,
    arms: string,
    language: keyof CashedCities
  ) => {
    this.createCityData = {
      ...this.createCityData,
      country_code: country_code,
      arms: arms,
      [language]: {
        name: name,
      },
    };
  };

  setCreateCityWeatherCode = (weather_city_code: number) => {
    this.createCityData = { ...this.createCityData, weather_city_code };
  };

  async createCity() {
    const language = languageStore.language as Language;
    const { country_code, arms, weather_city_code } = this.createCityData;
    const { name } = this.createCityData[language];

    if (!name || !country_code) {
      return;
    }

    try {
      // Create city in primary language
      const cityPayload = {
        name: name.trim(),
        country:
          countryStore.countries[language as keyof CashedCountries]?.data.find(
            (c) => c.code === country_code
          )?.name || "",
        country_code,
        ...(arms ? { arms } : {}),
        weather_city_code: weather_city_code ?? 0,
      };

      const cityResponse = await languageInstance(language).post(
        "/city",
        cityPayload
      );

      const cityId = cityResponse.data.id;

      // Create/update other language versions
      for (const secondaryLanguage of (["ru", "en", "zh"] as Language[]).filter(
        (l) => l !== language
      )) {
        const { name: secondaryName } = this.createCityData[secondaryLanguage];

        // Get country name in secondary language
        const countryName =
          countryStore.countries[secondaryLanguage]?.data.find(
            (c) => c.code === country_code
          )?.name || "";

        const patchPayload = {
          name: (secondaryName || "").trim(),
          country: countryName,
          country_code: country_code || "",
          ...(arms ? { arms } : {}),
        };

        const patchResponse = await languageInstance(secondaryLanguage).patch(
          `/city/${cityId}`,
          patchPayload
        );

        runInAction(() => {
          this.cities[secondaryLanguage].data = [
            ...this.cities[secondaryLanguage].data,
            patchResponse.data,
          ];
        });
      }

      // Update primary language data
      runInAction(() => {
        this.cities[language].data = [
          ...this.cities[language].data,
          cityResponse.data,
        ];
      });

      // Reset form data
      runInAction(() => {
        this.createCityData = {
          country_code: "",
          arms: "",
          weather_city_code: 0,
          ru: { name: "" },
          en: { name: "" },
          zh: { name: "" },
        };
      });
    } catch (error) {
      console.error("Error creating city:", error);
      throw error;
    }
  }

  editCityData = {
    country_code: "",
    arms: "",
    weather_city_code: 0,
    ru: {
      name: "",
    },
    en: {
      name: "",
    },
    zh: {
      name: "",
    },
  };

  setEditCityData = (
    name: string,
    country_code: string,
    arms: string,
    language: keyof CashedCities
  ) => {
    this.editCityData = {
      ...this.editCityData,
      country_code: country_code,
      arms: arms,
      [language]: {
        name: name,
      },
    };
  };

  setEditCityWeatherCode = (weather_city_code: number) => {
    this.editCityData = { ...this.editCityData, weather_city_code };
  };

  editCity = async (code: string) => {
    for (const language of ["ru", "en", "zh"]) {
      const { country_code, arms, weather_city_code } = this.editCityData;
      const { name } = this.editCityData[language as keyof CashedCities];
      const { countries } = countryStore;

      const country = countries[language as keyof CashedCities].data.find(
        (country) => country.code === country_code
      );

      await languageInstance(language as Language).patch(`/city/${code}`, {
        name: (name || "").trim(),
        country: country?.name || "",
        country_code: country_code,
        arms,
        weather_city_code: weather_city_code ?? 0,
      });

      runInAction(() => {
        if (this.city[code]) {
          this.city[code][language as keyof CashedCities] = {
            name,
            country: country?.name || "",
            country_code: country_code,
            arms,
          };
        }

        if (this.cities[language as keyof CashedCities]) {
          this.cities[language as keyof CashedCities].data = this.cities[
            language as keyof CashedCities
          ].data.map((city) =>
            city.id === Number(code)
              ? {
                  id: city.id,
                  name,
                  country: country?.name || "",
                  country_code: country_code,
                  arms,
                }
              : city
          );
        }
      });
    }
  };
}

export const cityStore = new CityStore();
