import {
  articlesStore,
  authInstance,
  Language,
  languageInstance,
  mediaStore,
} from "@shared";
import { makeAutoObservable, runInAction } from "mobx";

export type SightLanguageInfo = {
  id: number;
  name: string;
  short_name: string;
  address: string;
  left: {
    heading: string;
    body: string;
    media: { id: string; media_type: number; filename: string }[];
  };
  right: {
    id: number;
    heading: string;
    body: string;
    media: { id: string; media_type: number; filename: string }[];
  }[];
};

export type SightCommonInfo = {
  id: number;
  city_id: number;
  city: string;
  latitude: number;
  longitude: number;
  is_default_icon: boolean;
  thumbnail: string | null;
  icon: string | null;
  alt_icon: string | null;
  watermark_lu: string | null;
  watermark_rd: string | null;
  left_article: number;
  preview_media: string | null;
  video_preview: string | null;
  preview_font_size?: number;
};

export type SightBaseInfo = {
  common: SightCommonInfo;
} & {
  [key in Language]: SightLanguageInfo;
};
class EditSightStore {
  sight: SightBaseInfo = {
    common: {
      id: 0,
      city_id: 0,
      city: "",
      latitude: 0,
      longitude: 0,
      is_default_icon: false,
      thumbnail: null,
      icon: null,
      alt_icon: null,
      watermark_lu: null,
      watermark_rd: null,
      left_article: 0,
      preview_media: null,
      video_preview: null,
    },
    ru: {
      id: 0,
      name: "",
      short_name: "",
      address: "",
      left: { heading: "", body: "", media: [] },
      right: [],
    },
    en: {
      id: 0,
      name: "",
      short_name: "",
      address: "",
      left: { heading: "", body: "", media: [] },
      right: [],
    },
    zh: {
      id: 0,
      name: "",
      short_name: "",
      address: "",
      left: { heading: "", body: "", media: [] },
      right: [],
    },
  };

  constructor() {
    makeAutoObservable(this);
  }

  hasLoadedCommon = false;
  isLoading = false;

  getSightInfo = async (id: number, language: Language) => {
    this.isLoading = true;
    try {
      const response = await languageInstance(language).get(`/sight/${id}`);
      const data = response.data;

      if (data.left_article != 0 && data.left_article != null) {
        await this.getLeftArticle(data.left_article);
      }

      runInAction(() => {
        this.sight[language] = {
          ...this.sight[language],
          ...data,
        };

        if (!this.hasLoadedCommon) {
          this.sight.common = {
            ...this.sight.common,
            ...data,
          };
          this.hasLoadedCommon = true;
        }
      });
    } finally {
      this.isLoading = false;
    }
  };

  updateLeftInfo = (language: Language, heading: string, body: string) => {
    this.sight[language].left.heading = heading;
    this.sight[language].left.body = body;
  };

  getRightArticles = async (id: number) => {
    let responseRu = await languageInstance("ru").get(`/sight/${id}/article`);
    let responseEn = await languageInstance("en").get(`/sight/${id}/article`);
    let responseZh = await languageInstance("zh").get(`/sight/${id}/article`);

    const mediaMap = new Map();
    for (const article of responseRu.data) {
      const responseMedia = await authInstance.get(
        `/article/${article.id}/media`
      );
      mediaMap.set(article.id, responseMedia.data);
    }

    const addMediaToArticles = (articles: any[]) => {
      return articles.map((article) => ({
        ...article,
        media: mediaMap.get(article.id),
      }));
    };

    const data = {
      ru: {
        right: addMediaToArticles(responseRu.data),
      },
      en: {
        right: addMediaToArticles(responseEn.data),
      },
      zh: {
        right: addMediaToArticles(responseZh.data),
      },
    };

    runInAction(() => {
      this.sight = {
        ...this.sight,
        ru: {
          ...this.sight.ru,
          right: data.ru.right,
        },
        en: {
          ...this.sight.en,
          right: data.en.right,
        },
        zh: {
          ...this.sight.zh,
          right: data.zh.right,
        },
      };
    });
  };

  clearSightInfo = () => {
    this.needLeaveAgree = false;
    this.hasLoadedCommon = false;
    this.isLoading = false;
    this.sight = {
      common: {
        id: 0,
        city_id: 0,
        city: "",
        latitude: 0,
        longitude: 0,
        is_default_icon: false,
        thumbnail: null,
        icon: null,
        alt_icon: null,
        watermark_lu: null,
        watermark_rd: null,
        left_article: 0,
        preview_media: null,
        video_preview: null,
      },
      ru: {
        id: 0,
        name: "",
        short_name: "",
        address: "",
        left: { heading: "", body: "", media: [] },
        right: [],
      },

      en: {
        id: 0,
        name: "",
        short_name: "",
        address: "",
        left: { heading: "", body: "", media: [] },
        right: [],
      },

      zh: {
        id: 0,
        name: "",
        short_name: "",
        address: "",
        left: { heading: "", body: "", media: [] },
        right: [],
      },
    };
  };

  updateSightInfo = (
    language: Language,
    content: Partial<SightLanguageInfo | SightCommonInfo>,
    common: boolean = false
  ) => {
    this.needLeaveAgree = true;
    if (common) {
      this.sight.common = {
        ...this.sight.common,
        ...content,
      };
    } else {
      this.sight[language] = {
        ...this.sight[language],
        ...content,
      };
    }
  };

  unlinkLeftArticle = async () => {
    this.sight.common.left_article = 0;
    this.sight.ru.left.heading = "";
    this.sight.en.left.heading = "";
    this.sight.zh.left.heading = "";
    this.sight.ru.left.body = "";
    this.sight.en.left.body = "";
    this.sight.zh.left.body = "";
  };

  updateSight = async () => {
    let createdLeftArticleId = this.sight.common.left_article;

    if (this.sight.common.left_article == 10000000) {
      const response = await languageInstance("ru").post(`/article`, {
        heading: this.sight.ru.left.heading,
        body: this.sight.ru.left.body,
      });
      createdLeftArticleId = response.data.id;
      await languageInstance("en").patch(`/article/${createdLeftArticleId}`, {
        heading: this.sight.en.left.heading,
        body: this.sight.en.left.body,
      });

      await languageInstance("zh").patch(`/article/${createdLeftArticleId}`, {
        heading: this.sight.zh.left.heading,
        body: this.sight.zh.left.body,
      });

      this.sight.common.left_article = createdLeftArticleId;
    } else if (
      this.sight.common.left_article != 0 &&
      this.sight.common.left_article != null
    ) {
      await authInstance.patch(`/article/${this.sight.common.left_article}`, {
        translations: {
          heading: {
            ru: this.sight.ru.left.heading,
            en: this.sight.en.left.heading,
            zh: this.sight.zh.left.heading,
          },
          body: {
            ru: this.sight.ru.left.body,
            en: this.sight.en.left.body,
            zh: this.sight.zh.left.body,
          },
        },
      });
    }

    await authInstance.patch(`/sight/${this.sight.common.id}`, {
      ...this.sight.common,
      translations: {
        name: {
          ru: (this.sight.ru.name || "").trim(),
          en: (this.sight.en.name || "").trim(),
          zh: (this.sight.zh.name || "").trim(),
        },
        short_name: {
          ru: (this.sight.ru.short_name || "").trim(),
          en: (this.sight.en.short_name || "").trim(),
          zh: (this.sight.zh.short_name || "").trim(),
        },
        address: {
          ru: this.sight.ru.address,
          en: this.sight.en.address,
          zh: this.sight.zh.address,
        },
      },
    });

    for (let index = 0; index < this.sight.ru.right.length; index++) {
      const article = this.sight.ru.right[index];
      if (article.id == 0 || article.id == null) {
        continue;
      }
      await authInstance.patch(`/article/${article.id}`, {
        translations: {
          heading: {
            ru: this.sight.ru.right[index].heading,
            en: this.sight.en.right[index].heading,
            zh: this.sight.zh.right[index].heading,
          },
          body: {
            ru: this.sight.ru.right[index].body,
            en: this.sight.en.right[index].body,
            zh: this.sight.zh.right[index].body,
          },
        },
      });
    }

    const articleIdsInObject = this.sight.ru.right.map((article) => ({
      id: article.id,
    }));

    await authInstance.post(`/sight/${this.sight.common.id}/article/order`, {
      articles: articleIdsInObject,
    });

    this.needLeaveAgree = false;
  };

  getLeftArticle = async (id: number) => {
    const response = await languageInstance("ru").get(`/article/${id}`);
    const responseEn = await languageInstance("en").get(`/article/${id}`);
    const responseZh = await languageInstance("zh").get(`/article/${id}`);
    const mediaIds = await authInstance.get(`/article/${id}/media`);
    runInAction(() => {
      this.sight.ru.left = {
        heading: response.data.heading,
        body: response.data.body,
        media: mediaIds.data,
      };
      this.sight.en.left = {
        heading: responseEn.data.heading,
        body: responseEn.data.body,
        media: mediaIds.data,
      };
      this.sight.zh.left = {
        heading: responseZh.data.heading,
        body: responseZh.data.body,
        media: mediaIds.data,
      };
    });
  };

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

    runInAction(() => {
      articlesStore.articles.ru = articlesStore.articles.ru.filter(
        (article) => article.id !== id
      );
      articlesStore.articles.en = articlesStore.articles.en.filter(
        (article) => article.id !== id
      );
      articlesStore.articles.zh = articlesStore.articles.zh.filter(
        (article) => article.id !== id
      );
    });
    this.sight.common.left_article = 0;
    this.sight.ru.left.heading = "";
    this.sight.en.left.heading = "";
    this.sight.zh.left.heading = "";
    this.sight.ru.left.body = "";
    this.sight.en.left.body = "";
    this.sight.zh.left.body = "";
  };

  createLeftArticle = async () => {
    const ruName = (this.sight.ru.name || "").trim();
    const enName = (this.sight.en.name || "").trim();
    const zhName = (this.sight.zh.name || "").trim();
    const hasAnyName = !!(ruName || enName || zhName);

    const response = await languageInstance("ru").post(`/article`, {
      heading: hasAnyName ? ruName : "",
      body: "",
    });

    this.sight.common.left_article = response.data.id;

    await languageInstance("en").patch(
      `/article/${this.sight.common.left_article}`,
      {
        heading: hasAnyName ? enName : "",
        body: "",
      }
    );
    await languageInstance("zh").patch(
      `/article/${this.sight.common.left_article}`,
      {
        heading: hasAnyName ? zhName : "",
        body: "",
      }
    );

    this.sight.ru.left.heading = hasAnyName ? ruName : "";
    this.sight.en.left.heading = hasAnyName ? enName : "";
    this.sight.zh.left.heading = hasAnyName ? zhName : "";
    this.sight.ru.left.body = "";
    this.sight.en.left.body = "";
    this.sight.zh.left.body = "";
  };

  deleteMedia = async (article_id: number, media_id: string) => {
    await authInstance.delete(`/article/${article_id}/media`, {
      data: {
        media_id: media_id,
      },
    });

    this.sight.ru.left.media = this.sight.ru.left.media.filter(
      (media) => media.id !== media_id
    );
    this.sight.en.left.media = this.sight.en.left.media.filter(
      (media) => media.id !== media_id
    );
    this.sight.zh.left.media = this.sight.zh.left.media.filter(
      (media) => media.id !== media_id
    );
  };

  unlinkRightArticle = async (article_id: number) => {
    await authInstance.delete(`/sight/${this.sight.common.id}/article`, {
      data: {
        article_id: article_id,
      },
    });

    this.sight.ru.right = this.sight.ru.right.filter(
      (article) => article.id !== article_id
    );
    this.sight.en.right = this.sight.en.right.filter(
      (article) => article.id !== article_id
    );
    this.sight.zh.right = this.sight.zh.right.filter(
      (article) => article.id !== article_id
    );
  };

  deleteRightArticle = async (article_id: number) => {
    this.sight.ru.right = this.sight.ru.right.filter(
      (article) => article.id !== article_id
    );
    this.sight.en.right = this.sight.en.right.filter(
      (article) => article.id !== article_id
    );
    this.sight.zh.right = this.sight.zh.right.filter(
      (article) => article.id !== article_id
    );

    await authInstance.delete(`/article/${article_id}`);
  };

  uploadMediaOpen = false;
  setUploadMediaOpen = (open: boolean) => {
    this.uploadMediaOpen = open;
  };
  fileToUpload: File | null = null;
  setFileToUpload = (file: File | null) => {
    this.fileToUpload = file;
  };
  uploadMedia = async (
    filename: string,
    type: number,
    file: File,
    media_name?: string
  ) => {
    const formData = new FormData();
    formData.append("file", file);
    formData.append("filename", filename);
    if (media_name) {
      formData.append("media_name", media_name);
    }
    formData.append("type", type.toString());

    const response = await authInstance.post(`/media`, formData);
    this.fileToUpload = null;
    this.uploadMediaOpen = false;

    mediaStore.getMedia();

    return {
      id: response.data.id,
      filename: filename,
      media_name: media_name,
      media_type: type,
    };
  };

  createLinkWithArticle = async (media: {
    id: string;
    filename: string;
    media_name?: string;
    media_type: number;
  }) => {
    await authInstance.post(
      `/article/${this.sight.common.left_article}/media`,
      {
        media_id: media.id,
        media_order: 1,
      }
    );

    this.sight.ru.left.media.unshift({
      id: media.id,
      media_type: media.media_type,
      filename: media.filename,
    });
    this.sight.en.left.media.unshift({
      id: media.id,
      media_type: media.media_type,
      filename: media.filename,
    });
    this.sight.zh.left.media.unshift({
      id: media.id,
      media_type: media.media_type,
      filename: media.filename,
    });
  };

  unlinkPreviewMedia = async () => {
    this.sight.common.preview_media = null;
  };

  linkPreviewMedia = async (mediaId: string) => {
    this.sight.common.preview_media = mediaId;
  };

  linkArticle = async (article_id: number) => {
    const response = await languageInstance("ru").get(`/article/${article_id}`);
    const responseEn = await languageInstance("en").get(
      `/article/${article_id}`
    );
    const responseZh = await languageInstance("zh").get(
      `/article/${article_id}`
    );
    const mediaIds = await authInstance.get(`/article/${article_id}/media`);
    runInAction(() => {
      this.sight.ru.right.push({
        id: article_id,
        heading: response.data.heading,
        body: response.data.body,
        media: mediaIds.data,
      });
      this.sight.en.right.push({
        id: article_id,
        heading: responseEn.data.heading,
        body: responseEn.data.body,
        media: mediaIds.data,
      });
      this.sight.zh.right.push({
        id: article_id,
        heading: responseZh.data.heading,
        body: responseZh.data.body,
        media: mediaIds.data,
      });
    });

    return article_id;
  };

  deleteRightArticleMedia = async (article_id: number, media_id: string) => {
    await authInstance.delete(`/article/${article_id}/media`, {
      data: {
        media_id: media_id,
      },
    });

    this.sight.ru.right = this.sight.ru.right.map((article) => {
      if (article.id === article_id) {
        article.media = article.media.filter((media) => media.id !== media_id);
      }
      return article;
    });

    this.sight.en.right = this.sight.en.right.map((article) => {
      if (article.id === article_id) {
        article.media = article.media.filter((media) => media.id !== media_id);
      }
      return article;
    });

    this.sight.zh.right = this.sight.zh.right.map((article) => {
      if (article.id === article_id) {
        article.media = article.media.filter((media) => media.id !== media_id);
      }
      return article;
    });
  };

  createNewRightArticle = async () => {
    const articleRuData = {
      heading: "Новый заголовок (RU)",
      body: "Новый текст (RU)",
    };
    const articleEnData = {
      heading: "New Heading (EN)",
      body: "New Text (EN)",
    };
    const articleZhData = {
      heading: "Новый заголовок (ZH)",
      body: "Новый текст (ZH)",
    };
    const articleId = await authInstance.post("/article", {
      translations: {
        heading: {
          ru: articleRuData.heading,
          en: articleEnData.heading,
          zh: articleZhData.heading,
        },
        body: {
          ru: articleRuData.body,
          en: articleEnData.body,
          zh: articleZhData.body,
        },
      },
    });
    const { id } = articleId.data;

    await authInstance.post(`/sight/${this.sight.common.id}/article`, {
      article_id: id,
      page_num: this.sight.ru.right.length + 1,
    });

    this.sight.ru.right.push({
      id: id,
      heading: articleRuData.heading,
      body: articleRuData.body,
      media: [],
    });
    this.sight.en.right.push({
      id: id,
      heading: articleEnData.heading,
      body: articleEnData.body,
      media: [],
    });
    this.sight.zh.right.push({
      id: id,
      heading: articleZhData.heading,
      body: articleZhData.body,
      media: [],
    });

    runInAction(() => {
      articlesStore.articles.ru.push({
        id: id,
        heading: articleRuData.heading,
        body: articleRuData.body,
        service_name: articleRuData.heading,
      });
      articlesStore.articles.en.push({
        id: id,
        heading: articleEnData.heading,
        body: articleEnData.body,
        service_name: articleEnData.heading,
      });
      articlesStore.articles.zh.push({
        id: id,
        heading: articleZhData.heading,
        body: articleZhData.body,
        service_name: articleZhData.heading,
      });
    });

    return id;
  };

  createLinkWithRightArticle = async (
    media: {
      id: string;
      filename: string;
      media_name?: string;
      media_type: number;
    },
    article_id: number
  ) => {
    await authInstance.post(`/article/${article_id}/media`, {
      media_id: media.id,
      media_order: 1,
    });
    this.sight.ru.right = this.sight.ru.right.map((article) => {
      if (article.id === article_id) {
        article.media.unshift({
          id: media.id,
          media_type: media.media_type,
          filename: media.filename,
        });
      }
      return article;
    });
    this.sight.en.right = this.sight.en.right.map((article) => {
      if (article.id === article_id) {
        article.media.unshift({
          id: media.id,
          media_type: media.media_type,
          filename: media.filename,
        });
      }
      return article;
    });
    this.sight.zh.right = this.sight.zh.right.map((article) => {
      if (article.id === article_id) {
        article.media.unshift({
          id: media.id,
          media_type: media.media_type,
          filename: media.filename,
        });
      }
      return article;
    });
  };

  updateRightArticleInfo = (
    index: number,
    language: Language,
    heading: string,
    body: string
  ) => {
    this.sight[language].right[index].heading = heading;
    this.sight[language].right[index].body = body;
  };

  updateRightArticles = async (articles: any[]) => {
    const articlesIds = articles.map((article) => article.id);

    const sortArticles = (existing: any[]) => {
      const articleMap = new Map(
        existing.map((article) => [article.id, article])
      );
      return articlesIds
        .map((id) => articleMap.get(id))
        .filter(
          (article): article is (typeof existing)[number] =>
            article !== undefined
        );
    };

    this.sight.ru.right = sortArticles(this.sight.ru.right);
    this.sight.en.right = sortArticles(this.sight.en.right);
    this.sight.zh.right = sortArticles(this.sight.zh.right);

    this.needLeaveAgree = true;
  };

  needLeaveAgree = false;
  setNeedLeaveAgree = (need: boolean) => {
    this.needLeaveAgree = need;
  };
}

export const editSightStore = new EditSightStore();
