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

export type Carrier = {
  id: number;
  short_name: string;
  full_name: string;
  slogan: string;
  city: string;
  city_id: number;
  logo: string;
  main_color: string;
  left_color: string;
  right_color: string;
};

type CarrierData = {
  data: Carrier[];
  loaded: boolean;
};

type Carriers = {
  ru: CarrierData;
  en: CarrierData;
  zh: CarrierData;
};

type CashedCarrier = Record<
  number,
  {
    ru: Carrier | null;
    en: Carrier | null;
    zh: Carrier | null;
  }
>;

class CarrierStore {
  carriers: Carriers = {
    ru: {
      data: [],
      loaded: false,
    },
    en: {
      data: [],
      loaded: false,
    },
    zh: {
      data: [],
      loaded: false,
    },
  };
  carrier: CashedCarrier = {};

  constructor() {
    makeAutoObservable(this);
  }

  getCarriers = async (language: Language) => {
    if (this.carriers[language as keyof Carriers].loaded) return;

    const response = await languageInstance(language).get("/carrier");

    runInAction(() => {
      this.carriers[language as keyof Carriers].data = response.data;
      this.carriers[language as keyof Carriers].loaded = true;
    });
  };

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

    runInAction(() => {
      for (const language of ["ru", "en", "zh"] as const) {
        this.carriers[language].data = this.carriers[language].data.filter(
          (carrier: Carrier) => carrier.id !== id
        );
      }
      delete this.carrier[id];
    });
  };

  getCarrier = async (id: number) => {
    if (this.carrier[id]?.ru && this.carrier[id]?.en && this.carrier[id]?.zh)
      return;

    const ruResponse = await languageInstance("ru").get(`/carrier/${id}`);
    const enResponse = await languageInstance("en").get(`/carrier/${id}`);
    const zhResponse = await languageInstance("zh").get(`/carrier/${id}`);

    runInAction(() => {
      if (!this.carrier[id]) {
        this.carrier[id] = {
          ru: null,
          en: null,
          zh: null,
        };
      }
      this.carrier[id].ru = ruResponse.data;
      this.carrier[id].en = enResponse.data;
      this.carrier[id].zh = zhResponse.data;
    });
    return this.carrier[id];
  };

  createCarrierData = {
    city_id: 0,
    logo: "",
    main_color: "",
    left_color: "",
    right_color: "",
    ru: {
      full_name: "",
      short_name: "",
      slogan: "",
    },
    en: {
      full_name: "",
      short_name: "",
      slogan: "",
    },
    zh: {
      full_name: "",
      short_name: "",
      slogan: "",
    },
  };

  setCreateCarrierData = (
    fullName: string,
    shortName: string,
    cityId: number,
    slogan: string,
    logoId: string,
    language: Language,
    colors?: { main_color?: string; left_color?: string; right_color?: string }
  ) => {
    this.createCarrierData.city_id = cityId;
    this.createCarrierData.logo = logoId;
    if (colors) {
      if (colors.main_color !== undefined) this.createCarrierData.main_color = colors.main_color;
      if (colors.left_color !== undefined) this.createCarrierData.left_color = colors.left_color;
      if (colors.right_color !== undefined) this.createCarrierData.right_color = colors.right_color;
    }
    this.createCarrierData[language] = {
      full_name: fullName,
      short_name: shortName,
      slogan: slogan,
    };
  };

  private resolveCityName = (cityId: number, preferredLanguage: Language) => {
    if (!cityId) {
      return "";
    }

    const languages: Language[] = ["ru", "en", "zh"];

    const fromCityStorePreferred = cityStore.cities[preferredLanguage].data.find(
      (city) => city.id === cityId
    )?.name;
    if (fromCityStorePreferred) {
      return fromCityStorePreferred;
    }

    for (const language of languages) {
      const cityName = cityStore.cities[language].data.find(
        (city) => city.id === cityId
      )?.name;
      if (cityName) {
        return cityName;
      }
    }

    const fromMePreferred = authStore.meCities[preferredLanguage].find(
      (city) => city.city_id === cityId
    )?.name;
    if (fromMePreferred) {
      return fromMePreferred;
    }

    for (const language of languages) {
      const cityName = authStore.meCities[language].find(
        (city) => city.city_id === cityId
      )?.name;
      if (cityName) {
        return cityName;
      }
    }

    return "";
  };

  createCarrier = async () => {
    const { language } = languageStore;
    const cityName = this.resolveCityName(this.createCarrierData.city_id, language);

    const payload = {
      full_name: (this.createCarrierData[language].full_name || "").trim(),
      short_name: (this.createCarrierData[language].short_name || "").trim(),
      city: cityName,
      city_id: this.createCarrierData.city_id,
      slogan: (this.createCarrierData[language].slogan || "").trim(),
      ...(this.createCarrierData.logo ? { logo: this.createCarrierData.logo } : {}),
      ...(this.createCarrierData.main_color ? { main_color: this.createCarrierData.main_color } : {}),
      ...(this.createCarrierData.left_color ? { left_color: this.createCarrierData.left_color } : {}),
      ...(this.createCarrierData.right_color ? { right_color: this.createCarrierData.right_color } : {}),
    };

    const response = await languageInstance(language).post("/carrier", payload);

    const carrierId = response.data.id;

    runInAction(() => {
      this.carriers[language].data.push(response.data);
    });

    for (const lang of ["ru", "en", "zh"].filter((l) => l !== language)) {
      const cityNameForLang = this.resolveCityName(
        this.createCarrierData.city_id,
        lang as Language
      );
      const patchPayload = {
        // @ts-ignore
        full_name: ((this.createCarrierData[lang as any].full_name as string) || "").trim(),
        // @ts-ignore
        short_name: ((this.createCarrierData[lang as any].short_name as string) || "").trim(),
        city: cityNameForLang || cityName,
        city_id: this.createCarrierData.city_id,
        // @ts-ignore
        slogan: ((this.createCarrierData[lang as any].slogan as string) || "").trim(),
        ...(this.createCarrierData.logo
          ? { logo: this.createCarrierData.logo }
          : {}),
      };

      const response = await languageInstance(lang as Language).patch(
        `/carrier/${carrierId}`,
        patchPayload
      );

      runInAction(() => {
        this.carriers[lang as keyof Carriers].data.push(response.data);
      });
    }

    this.createCarrierData = {
      city_id: 0,
      logo: "",
      main_color: "",
      left_color: "",
      right_color: "",
      ru: {
        full_name: "",
        short_name: "",
        slogan: "",
      },
      en: {
        full_name: "",
        short_name: "",
        slogan: "",
      },
      zh: {
        full_name: "",
        short_name: "",
        slogan: "",
      },
    };
  };

  editCarrierData = {
    ru: {
      full_name: "",
      short_name: "",
      slogan: "",
    },
    en: {
      full_name: "",
      short_name: "",
      slogan: "",
    },
    zh: {
      full_name: "",
      short_name: "",
      slogan: "",
    },
    city_id: 0,
    logo: "",
    main_color: "",
    left_color: "",
    right_color: "",
  };

  setEditCarrierData = (
    fullName: string,
    shortName: string,
    cityId: number,
    slogan: string,
    logoId: string,
    language: Language,
    colors?: { main_color?: string; left_color?: string; right_color?: string }
  ) => {
    this.editCarrierData.city_id = cityId;
    this.editCarrierData.logo = logoId;
    if (colors) {
      if (colors.main_color !== undefined) this.editCarrierData.main_color = colors.main_color;
      if (colors.left_color !== undefined) this.editCarrierData.left_color = colors.left_color;
      if (colors.right_color !== undefined) this.editCarrierData.right_color = colors.right_color;
    }
    this.editCarrierData[language] = {
      full_name: fullName,
      short_name: shortName,
      slogan: slogan,
    };
  };

  editCarrier = async (id: number) => {
    for (const lang of ["ru", "en", "zh"] as const) {
      const cityName = this.resolveCityName(this.editCarrierData.city_id, lang);
      const response = await languageInstance(lang).patch(`/carrier/${id}`, {
        ...this.editCarrierData[lang],
        full_name: (this.editCarrierData[lang].full_name || "").trim(),
        short_name: (this.editCarrierData[lang].short_name || "").trim(),
        slogan: (this.editCarrierData[lang].slogan || "").trim(),
        city: cityName,
        city_id: this.editCarrierData.city_id,
        ...(this.editCarrierData.logo ? { logo: this.editCarrierData.logo } : {}),
        ...(this.editCarrierData.main_color ? { main_color: this.editCarrierData.main_color } : {}),
        ...(this.editCarrierData.left_color ? { left_color: this.editCarrierData.left_color } : {}),
        ...(this.editCarrierData.right_color ? { right_color: this.editCarrierData.right_color } : {}),
      });

      runInAction(() => {
        if (this.carrier[id]) {
          this.carrier[id][lang] = response.data;
        }

        this.carriers[lang].data = this.carriers[lang].data.map(
          (carrier: Carrier) =>
            carrier.id === id ? { ...carrier, ...response.data } : carrier
        );
      });
    }
  };
}

export const carrierStore = new CarrierStore();
