<template>
  <div class="carrierinfo">
    <div class="bg" :class="{ hidden: isHidden }">
      <div class="gos-container">
        <img class="gos-logo" :src="spbGerb" />
        <span class="gos-name" v-html="t('govt_support')"></span>
      </div>

      <br />

      <button
        v-if="hasGovernorAppeal"
        class="stop-button yellow"
        @click="toggleGovernorAppeal"
      >
        {{ governorAppealTitle || t("appeal") }}
      </button>

      <div ref="dropdownWrapper" class="dropdown-wrapper">
        <div class="stop-buttons-container">
          <button class="stop-button white" @click="toggleSights">
            {{ t("sights") }}
          </button>

          <ul
            v-if="sights.length"
            id="sightList"
            class="dropdown-list"
            :class="{
              show: showSightsList,
              fullscreen: showSightsList,
            }"
          >
            <div class="dropdown-name" @click="toggleSights">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="21"
                height="12"
                fill="none"
                viewBox="0 0 21 12"
                v-if="showSightsList"
                class="toggle-arrow arrow-rotated"
              >
                <path
                  fill="#fff"
                  d="M10.427 3.53c-.135.188-.203.316-.301.414C7.632 6.43 5.134 8.91 2.64 11.395c-.446.445-.96.623-1.573.44A1.485 1.485 0 0 1 .35 9.452c.075-.09.16-.171.243-.254L9.182.658c.884-.878 1.673-.877 2.559.003 2.896 2.878 5.798 5.753 8.68 8.646.25.252.46.606.542.948.155.646-.184 1.26-.749 1.563a1.519 1.519 0 0 1-1.765-.238c-.377-.352-.736-.725-1.1-1.09-2.204-2.195-4.408-4.389-6.61-6.585-.082-.082-.15-.179-.311-.374h-.001Z"
                />
              </svg>
              {{ t("sights") }}
            </div>
            <li
              v-for="sight in sights"
              :key="sight.id"
              :class="{ checked: selectedSightId === sight.id }"
              @click="selectSight(sight.id)"
            >
              <div class="sight-name">{{ sight.name }}</div>
              <div
                class="sight-transfer-list"
                v-if="
                  selectedSightId === sight.id && hasTransfers(sight.transfers)
                "
              >
                <div
                  class="transfer-row"
                  v-for="item in filteredEntries(sight.transfers)"
                  :key="item.key"
                >
                  <img
                    :src="transferIcons[item.key]"
                    class="transfer-icon"
                    alt=""
                  />
                  <span class="transfer-text">{{ item.val }}</span>
                </div>
              </div>
            </li>
          </ul>
          <button class="stop-button white" @click="toggleList">
            {{ t("stops") }}
          </button>
        </div>

        <ul
          v-if="stations.length"
          id="dropdownList"
          class="dropdown-list"
          :class="{ show: showList, fullscreen: showList }"
        >
          <div class="dropdown-name" @click="toggleList">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="21"
              height="12"
              fill="none"
              viewBox="0 0 21 12"
              v-if="showList"
              class="toggle-arrow arrow-rotated"
            >
              <path
                fill="#fff"
                d="M10.427 3.53c-.135.188-.203.316-.301.414C7.632 6.43 5.134 8.91 2.64 11.395c-.446.445-.96.623-1.573.44A1.485 1.485 0 0 1 .35 9.452c.075-.09.16-.171.243-.254L9.182.658c.884-.878 1.673-.877 2.559.003 2.896 2.878 5.798 5.753 8.68 8.646.25.252.46.606.542.948.155.646-.184 1.26-.749 1.563a1.519 1.519 0 0 1-1.765-.238c-.377-.352-.736-.725-1.1-1.09-2.204-2.195-4.408-4.389-6.61-6.585-.082-.082-.15-.179-.311-.374h-.001Z"
              />
            </svg>
            {{ t("stops") }}
          </div>
          <li v-for="station in stations" :key="station.id">
            <div class="sight-name">{{ station.name }}</div>
          </li>
        </ul>
      </div>

      <div class="carrier-container">
        <img v-if="carrierLogoUrl" class="carrier-img" :src="carrierLogoUrl" />
        <div v-if="carrierSlogan" class="carrier-slogan">
          {{ carrierSlogan }}
        </div>
      </div>

      <span class="hashtag">{{ t("hashtag") }}</span>
    </div>
    <button class="carrier-toggle" @click="toggleCarrierInfo">
      <svg
        v-if="isHidden"
        xmlns="http://www.w3.org/2000/svg"
        width="48"
        height="48"
        fill="none"
        viewBox="0 0 48 48"
      >
        <path
          fill="#fff"
          d="M24 0c13.25 0 24 10.75 24 24S37.25 48 24 48 0 37.25 0 24 10.75 0 24 0ZM10.46 25.84c0 .56.45 1.01 1.01 1.01h15.94c.45 0 .67.54.36.86l-7.45 7.45c-.4.4-.4 1.04 0 1.43l2.6 2.6c.4.4 1.04.4 1.43 0l11.16-11.16 3.32-3.32c.4-.4.4-1.04 0-1.43l-3.32-3.32L24.35 8.8c-.4-.4-1.04-.4-1.43 0l-2.6 2.6c-.4.4-.4 1.04 0 1.43l7.45 7.45c.32.32.09.86-.36.86H11.47c-.56 0-1.01.45-1.01 1.01v3.69Z"
        />
      </svg>
      <svg
        v-else
        xmlns="http://www.w3.org/2000/svg"
        width="48"
        height="48"
        fill="none"
        viewBox="0 0 48 48"
      >
        <path
          fill="#fff"
          d="M24 0C10.75 0 0 10.75 0 24s10.75 24 24 24 24-10.75 24-24S37.25 0 24 0Zm13.54 25.84c0 .56-.45 1.01-1.01 1.01H20.59c-.45 0-.67.54-.36.86l7.45 7.45c.4.4.4 1.04 0 1.43l-2.6 2.6c-.4.4-1.04.4-1.43 0L12.49 28.03l-3.32-3.32c-.4-.4-.4-1.04 0-1.43l3.32-3.32L23.65 8.8c.4-.4 1.04-.4 1.43 0l2.6 2.6c.4.4.4 1.04 0 1.43l-7.45 7.45c-.32.32-.09.86.36.86h15.94c.56 0 1.01.45 1.01 1.01v3.69Z"
        />
      </svg>
    </button>
    <!-- single‑button globe – shown until the user clicks it -->
    <button
      v-if="showLangToggle"
      class="carrier-toggle lang-toggle"
      @click="toggleLanguageOptions"
    >
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="48"
        height="48"
        fill="none"
        viewBox="0 0 48 48"
      >
        <path
          fill="#fff"
          fill-rule="evenodd"
          d="M0 24C0 10.75 10.75 0 24 0s24 10.75 24 24-10.75 24-24 24S0 37.25 0 24Zm36.05-4.59 2.22 6.06 2.2-6.08-1.3.38c-.01-.02-.01-.42-.01-.45-.58-6.91-6.17-12.17-13.22-12.17-.52 0-.95.43-.95.95s.43.95.95.95c5.98 0 10.74 4.42 11.32 10.26l.005.235.005.235-1.22-.37ZM8.903 27.537c2.45-.58 4.73-1.693 6.667-3.253a13.372 13.372 0 0 0 5.911 3.268c.106.013.213.013.32 0a1.483 1.483 0 0 0 1.337-.567c.31-.406.37-.94.16-1.402a1.46 1.46 0 0 0-1.178-.835 10.091 10.091 0 0 1-4.357-2.399 20.41 20.41 0 0 0 5.403-8.413 1.368 1.368 0 0 0-.29-1.22 1.469 1.469 0 0 0-1.163-.56H16.63v-1.754c0-.5-.277-.963-.726-1.214a1.495 1.495 0 0 0-1.452 0c-.449.25-.726.713-.726 1.214v1.78H8.643c-.52 0-.998.268-1.258.701-.26.434-.26.97 0 1.403.26.433.74.7 1.258.7h11.022a19.358 19.358 0 0 1-3.95 5.413 19.152 19.152 0 0 1-2.295-3.24 1.428 1.428 0 0 0-.83-.806 1.498 1.498 0 0 0-1.176.052 1.416 1.416 0 0 0-.75.877c-.11.382-.048.79.171 1.125a22.29 22.29 0 0 0 2.716 3.745 13.713 13.713 0 0 1-5.243 2.58 1.472 1.472 0 0 0-.982.515 1.374 1.374 0 0 0 .216 1.983c.3.236.686.346 1.071.307a.982.982 0 0 0 .29 0ZM34.9 38.88c.351.15.748.16 1.107.027.374-.12.681-.383.851-.727.17-.344.188-.74.05-1.096l-6.565-16.307a1.41 1.41 0 0 0-.532-.65 1.49 1.49 0 0 0-1.635-.007c-.24.157-.426.381-.534.642l-6.506 15.761c-.192.465-.112.995.21 1.389a1.48 1.48 0 0 0 1.35.519c.514-.073.95-.404 1.141-.87l1.568-3.912h6.913l1.816 4.459c.14.344.415.622.766.772Zm-5.995-13.715 2.28 5.68h-4.619l2.339-5.68Z"
          clip-rule="evenodd"
        />
      </svg>
    </button>

    <!-- three language icons – appear after the globe is pressed -->
    <div v-if="showLanguageOptions" class="language-options">
      <!-- RU -->
      <button
        class="carrier-toggle lang-option"
        :style="{ opacity: selectedLang === 'ru' ? 1 : 0.8 }"
        @click="setLanguage('ru')"
      >
        <!-- RU SVG -->
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="48"
          height="48"
          fill="none"
          viewBox="0 0 48 48"
        >
          <g clip-path="url(#a)">
            <path
              fill="#fff"
              d="M24 0C10.75 0 0 10.75 0 24s10.75 24 24 24 24-10.75 24-24S37.25 0 24 0Zm.2 33.55h-4.28l-3.63-7.09h-3.18v7.09H9.12V14.18h7.2c2.29 0 4.05.51 5.3 1.53s1.86 2.46 1.86 4.32c0 1.32-.29 2.42-.86 3.31-.57.88-1.44 1.59-2.6 2.11l4.19 7.92v.19l-.01-.01Zm16.1-6.61c0 2.12-.66 3.8-1.99 5.03-1.33 1.23-3.14 1.85-5.44 1.85-2.3 0-4.06-.6-5.39-1.8-1.33-1.2-2.01-2.84-2.04-4.94v-12.9h3.99v12.79c0 1.27.3 2.19.91 2.77.61.58 1.45.87 2.52.87 2.24 0 3.38-1.18 3.42-3.54V14.18h4v12.76h.02Z"
            />
            <path
              fill="#fff"
              d="M16.309 17.41h-3.21v5.81h3.22c1 0 1.78-.26 2.33-.77s.82-1.21.82-2.11c0-.9-.26-1.63-.78-2.16-.52-.53-1.32-.79-2.39-.79l.01.02Z"
            />
          </g>
          <defs>
            <clipPath id="a"><path fill="#fff" d="M0 0h48v48H0z" /></clipPath>
          </defs>
        </svg>
      </button>

      <!-- ZH -->
      <button
        class="carrier-toggle lang-option"
        :style="{ opacity: selectedLang === 'zh' ? 1 : 0.8 }"
        @click="setLanguage('zh')"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="48"
          height="48"
          fill="none"
          viewBox="0 0 48 48"
        >
          <path
            fill="#fff"
            d="M10.287 20.382H6.291v3.765h3.996v-3.765Zm3.417 3.765h4.017v-3.765h-4.017v3.765Zm22.421-4.101h-6.267c.803 1.895 1.86 3.598 3.193 5.076 1.26-1.43 2.28-3.11 3.074-5.076Z"
          />
          <path
            fill="#fff"
            fill-rule="evenodd"
            d="M24 48c13.255 0 24-10.745 24-24S37.255 0 24 0 0 10.745 0 24s10.745 24 24 24ZM10.287 13.5h3.417v3.654h7.413v11.292h-3.396v-1.071h-4.017v6.594h-3.417v-6.594H6.291v1.176H3V17.154h7.287V13.5Zm21.063 0h3.354v3.318h8.379v3.228h-3.194c-1.085 2.905-2.514 5.337-4.308 7.36 2.068 1.518 4.584 2.648 7.587 3.323l.679.153-.5.483c-.572.551-1.37 1.712-1.758 2.429l-.14.258-.285-.074c-3.325-.87-6.04-2.226-8.267-4.053-2.267 1.77-4.958 3.108-8.095 4.09l-.313.098-.139-.297c-.278-.596-1.057-1.787-1.545-2.377l-.374-.452.568-.15c2.937-.772 5.404-1.867 7.438-3.343-1.76-2.088-3.118-4.58-4.196-7.448h-3.144v-3.228h8.253V13.5Z"
            clip-rule="evenodd"
          />
        </svg>
      </button>

      <!-- EN -->
      <button
        class="carrier-toggle lang-option"
        :style="{ opacity: selectedLang === 'en' ? 1 : 0.8 }"
        @click="setLanguage('en')"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="48"
          height="48"
          fill="none"
          viewBox="0 0 48 48"
        >
          <g clip-path="url(#b)">
            <path
              fill="#fff"
              d="M24 0C10.75 0 0 10.75 0 24s10.75 24 24 24 24-10.75 24-24S37.25 0 24 0Zm-2.43 33.79H8.41V14.15h13.14v3.28h-9.1v4.68h7.77v3.17h-7.77v5.26h9.12v3.25Zm17.97 0h-4.05l-7.88-12.92v12.92h-4.05V14.15h4.05L35.5 27.1V14.15h4.03v19.64h.01Z"
            />
          </g>
          <defs>
            <clipPath id="b"><path fill="#fff" d="M0 0h48v48H0z" /></clipPath>
          </defs>
        </svg>
      </button>
    </div>
  </div>
  <transition name="slide-fade">
    <div v-if="showGovernorAppeal" class="governor-appeal sight-preview-panel">
      <img :src="governorAppealImage" v-if="governorAppealImage" />
      <h3>{{ governorAppealTitle }}</h3>
      <p>{{ governorAppealText }}</p>
    </div>
  </transition>
  <transition name="slide-fade" mode="out-in">
    <div
      v-if="showSightPreview"
      :key="selectedSightId"
      class="sight-preview-panel"
    >
      <div class="sight-preview-wrapper" style="position: relative">
        <img :src="selectedSightImage" v-if="selectedSightImage" />
        <img
          v-if="selectedSightWatermarkLU"
          :src="selectedSightWatermarkLU"
          class="watermark watermark-lu"
        />
        <img
          v-if="selectedSightWatermarkRD"
          :src="selectedSightWatermarkRD"
          class="watermark watermark-rd"
        />
      </div>
      <h3>{{ selectedSightName }}</h3>
      <p>{{ selectedSightText }}</p>
    </div>
  </transition>
</template>

<script>
import "../assets/style/main.css";
import { API_URL, GEO_URL } from "../config";

export default {
  name: "CarrierInfo",
  data() {
    return {
      stations: [],
      showList: false,
      sights: [],
      showSightsList: false,
      routeId: 1,
      isHidden: true,
      selectedSightId: null,
      selectedSightName: "",
      selectedSightText: "",
      selectedSightImage: "",
      showSightPreview: false,
      governorAppealTitle: "",
      governorAppealText: "",
      governorAppealImage: "",
      hasGovernorAppeal: false,
      showGovernorAppeal: false,
      governorAppealId: null,
      selectedSightWatermarkLU: "",
      selectedSightWatermarkRD: "",
      inactivityTimer: null,
      stopsInterval: null,
      sightTransfers: {},
      showSightTransfers: false,
      spbGerb: require("@/icons/spb-gerb.svg"),
      transferIcons: {
        tram: require("@/icons/tram.svg"),
        trolleybus: require("@/icons/trolleybus.svg"),
        bus: require("@/icons/bus.svg"),
        train: require("@/icons/train.svg"),
        metro_red: require("@/icons/metro_red.svg"),
        metro_green: require("@/icons/metro_green.svg"),
        metro_blue: require("@/icons/metro_blue.svg"),
        metro_purple: require("@/icons/metro_purple.svg"),
        metro_orange: require("@/icons/metro_orange.svg"),
      },
      selectedLang: localStorage.getItem("selectedLang") || "ru",
      showLangToggle: true,
      showLanguageOptions: false,
      languageOptionsTimer: null,
      langRevertTimer: null,
      translations: {
        sights: { ru: "Достопримечательности", en: "Landmarks", zh: "景点" },
        stops: { ru: "Остановки", en: "Stops", zh: "站点" },
        appeal: { ru: "Обращение", en: "Appeal", zh: "致辞" },
        govt_support: {
          ru: "При поддержке Правительства <br /> Санкт-Петербурга",
          en: "Supported by the Government <br /> of St&nbsp;Petersburg",
          zh: "圣彼得堡政府支持",
        },
        hashtag: { ru: "#ВсемПоПути", en: "#OnOurWay", zh: "#同路人" },
      },
      carrierId: null,
      carrierLogoUrl: "",
      carrierSlogan: "",
    };
  },
  computed: {
    filteredSightTransfers() {
      return Object.fromEntries(
        Object.entries(this.sightTransfers || {}).filter(
          ([, v]) => v && v.toString().trim() !== ""
        )
      );
    },
  },
  methods: {
    getCookie(name) {
      const matches = document.cookie.match(
        new RegExp(
          "(?:^|; )" +
            name.replace(/([.$?*|{}()[\]\\/+^])/g, "\\$1") +
            "=([^;]*)"
        )
      );
      return matches ? decodeURIComponent(matches[1]) : undefined;
    },
    t(key) {
      const dict = this.translations[key] || {};
      return dict[this.selectedLang] || dict.ru || key;
    },
    async loadGovernorAppeal(appealId) {
      try {
        const articleRes = await fetch(
          this.addLangParam(`${API_URL}/article/${appealId}`)
        );
        const articleData = await articleRes.json();
        this.governorAppealTitle = articleData.heading;
        this.governorAppealText = articleData.body;

        const mediaRes = await fetch(
          this.addLangParam(`${API_URL}/article/${appealId}/media`)
        );
        const mediaData = await mediaRes.json();
        this.governorAppealImage = mediaData.length
          ? (
              await fetch(
                this.addLangParam(
                  `${API_URL}/media/${mediaData[0].id}/download`
                )
              )
            ).url
          : "";

        this.hasGovernorAppeal = true; // кнопка появится (v-if)
      } catch (err) {
        console.error("Ошибка при получении обращения губернатора:", err);
      }
    },
    async fetchCarrierInfo(carrierId) {
      try {
        const res = await fetch(
          this.addLangParam(`${API_URL}/carrier/${carrierId}`)
        );
        const data = await res.json();
        this.carrierSlogan = data.slogan;
        if (data.logo) {
          const logoRes = await fetch(
            this.addLangParam(`${API_URL}/media/${data.logo}/download`)
          );
          this.carrierLogoUrl = logoRes.url;
        }
      } catch (err) {
        console.error("Ошибка при получении данных перевозчика:", err);
      }
    },
    async fetchStops() {
      try {
        const geoResponse = await fetch(`${GEO_URL}/v1/geolocation/context`);
        const geoData = await geoResponse.json();
        const routeDetailsRes = await fetch(
          this.addLangParam(`${API_URL}/route/${geoData.routeId}`)
        );
        const routeDetails = await routeDetailsRes.json();
        const carrierId = routeDetails.carrier_id;
        const appealId = routeDetails.governor_appeal;

        if (carrierId && carrierId !== this.carrierId) {
          this.carrierId = carrierId;
          await this.fetchCarrierInfo(carrierId);
        }

        console.log(
          "Получено значение governor_appeal:",
          appealId,
          "из routeDetails:",
          routeDetails
        );

        if (appealId && appealId !== 0) {
          if (this.governorAppealId !== appealId) {
            this.governorAppealId = appealId;
            await this.loadGovernorAppeal(appealId);
          }
        }

        this.routeId = geoData.routeId;
        if (!this.routeId) throw new Error("Route number not found");

        const stopsResponse = await fetch(
          this.addLangParam(`${API_URL}/route/${this.routeId}/station`)
        );
        const stopsData = await stopsResponse.json();
        this.stations = stopsData;
      } catch (error) {
        console.error("Ошибка при получении данных об остановках:", error);
      }
    },
    async fetchSights() {
      try {
        const response = await fetch(
          this.addLangParam(`${API_URL}/route/${this.routeId}/sight`)
        );
        const rawSights = await response.json();

        const detailedSights = await Promise.all(
          rawSights.map(async (sight) => {
            const detailRes = await fetch(
              this.addLangParam(`${API_URL}/sight/${sight.id}`)
            );
            const detail = await detailRes.json();
            return { id: sight.id, name: detail.name, transfers: {} };
          })
        );

        this.sights = detailedSights;
      } catch (error) {
        console.error("Ошибка при получении достопримечательностей:", error);
      }
    },
    hasTransfers(transfers) {
      if (!transfers) return false;
      return Object.values(transfers).some(
        (v) => v && v.toString().trim() !== ""
      );
    },
    filteredEntries(transfers) {
      if (!transfers) return [];
      return Object.entries(transfers)
        .filter(([, v]) => v && v.toString().trim() !== "")
        .map(([key, val]) => ({ key, val }));
    },
    startStopsPolling() {
      if (this.stopsInterval) return;
      this.stopsInterval = setInterval(async () => {
        if (!this.stations.length) {
          await this.fetchStops();
        } else {
          clearInterval(this.stopsInterval);
          this.stopsInterval = null;
        }
      }, 3000);
    },

    async findTransfersForSight(sightId) {
      this.showSightTransfers = false;
      this.sightTransfers = {};
      try {
        const stationsRes = await fetch(
          this.addLangParam(`${API_URL}/route/${this.routeId}/station`)
        );
        const stationsData = await stationsRes.json();

        for (const station of stationsData) {
          try {
            const res = await fetch(
              this.addLangParam(`${API_URL}/station/${station.id}/sight`)
            );
            const stationSights = await res.json();
            const hasSight = stationSights.some((s) => s.id === sightId);
            if (hasSight) {
              this.sightTransfers = station.transfers || {};
              // update transfers on the selected sight object
              const idx = this.sights.findIndex((s) => s.id === sightId);
              if (idx !== -1) {
                this.sights[idx].transfers = this.sightTransfers;
              }
              this.showSightTransfers = true;
              console.log(
                `Пересадки на станции ${station.name}:`,
                station.transfers
              );
              break;
            }
          } catch (innerErr) {
            console.error(
              `Ошибка при получении достопримечательностей станции ${station.id}:`,
              innerErr
            );
          }
        }
      } catch (err) {
        console.error(
          "Ошибка при поиске пересадок для достопримечательности:",
          err
        );
      }
    },
    async toggleSights() {
      this.showGovernorAppeal = false;
      this.$emit("president-appeal-toggle", this.showGovernorAppeal);

      if (!this.sights.length) {
        await this.fetchSights();
      }
      if (this.showSightsList) {
        this.showSightsList = false;
        this.showSightPreview = false;
        this.selectedSightId = null;
        this.showSightTransfers = false;
      } else {
        this.showSightsList = true;
      }
    },
    async selectSight(sightId) {
      this.selectedSightId = sightId;
      try {
        const sightRes = await fetch(
          this.addLangParam(`${API_URL}/sight/${sightId}`)
        );
        const sightData = await sightRes.json();
        this.selectedSightName = sightData.name;

        const articleId = sightData.left_article;

        const articleRes = await fetch(
          this.addLangParam(`${API_URL}/article/${articleId}`)
        );
        const articleData = await articleRes.json();
        this.selectedSightText = articleData.body;

        const mediaRes = await fetch(
          this.addLangParam(`${API_URL}/article/${articleId}/media`)
        );
        const mediaData = await mediaRes.json();
        if (mediaData.length) {
          const imageRes = await fetch(
            this.addLangParam(`${API_URL}/media/${mediaData[0].id}/download`)
          );
          this.selectedSightImage = await imageRes.url;
          this.selectedSightWatermarkLU = sightData.watermark_lu
            ? this.addLangParam(
                `${API_URL}/media/${sightData.watermark_lu}/download`
              )
            : "";
          this.selectedSightWatermarkRD = sightData.watermark_rd
            ? this.addLangParam(
                `${API_URL}/media/${sightData.watermark_rd}/download`
              )
            : "";
        } else {
          this.selectedSightImage = "";
        }

        this.showSightPreview = true;
        await this.findTransfersForSight(sightId);
      } catch (err) {
        console.error("Ошибка при выборе достопримечательности:", err);
      }
    },
    async toggleList() {
      this.showGovernorAppeal = false;
      this.$emit("president-appeal-toggle", this.showGovernorAppeal);

      if (!this.stations.length) {
        await this.fetchStops();
      }
      this.showList = !this.showList;
    },
    toggleCarrierInfo() {
      this.isHidden = !this.isHidden;
      this.showList = false;
      this.showSightsList = false;
      this.showSightPreview = false;
      this.showGovernorAppeal = false;
      this.showSightTransfers = false;
      this.$emit("president-appeal-toggle", this.showGovernorAppeal);

      const root = document.documentElement;
      root.style.setProperty(
        "--panel-offset",
        this.isHidden ? "20px" : "320px"
      );

      const routeInfo = document.querySelector(".routeinfo");
      const weatherInfo = document.querySelector(".weatherinfo");

      requestAnimationFrame(() => {
        if (this.isHidden) {
          routeInfo?.classList.add("shifted-left");
          weatherInfo?.classList.add("shifted-left");
        } else {
          routeInfo?.classList.remove("shifted-left");
          weatherInfo?.classList.remove("shifted-left");
        }
      });
      this.resetInactivityTimer();
    },
    handleClickOutside() {
      // пупупу
    },
    toggleGovernorAppeal() {
      console.log("Кнопка обращения губернатора нажата");
      this.showGovernorAppeal = !this.showGovernorAppeal;
      this.showSightPreview = false;

      this.$emit("president-appeal-toggle", this.showGovernorAppeal);
    },
    resetInactivityTimer() {
      clearTimeout(this.inactivityTimer);
      this.inactivityTimer = setTimeout(this.hidePanelIfActive, 300000); //  5m
    },
    hidePanelIfActive() {
      if (!this.isHidden) {
        this.toggleCarrierInfo();
      }
    },
    handleUserActivity() {
      this.resetInactivityTimer();
      this.resetLangRevertTimer();
    },
    toggleLanguageOptions() {
      this.showLangToggle = false;
      this.showLanguageOptions = true;
      this.startLanguageOptionsTimer();
    },
    startLanguageOptionsTimer() {
      clearTimeout(this.languageOptionsTimer);
      this.languageOptionsTimer = setTimeout(this.hideLanguageOptions, 10000);
    },
    hideLanguageOptions() {
      this.showLanguageOptions = false;
      this.showLangToggle = true;
    },
    setLanguage(lang) {
      if (this.selectedLang === lang) {
        this.hideLanguageOptions();
        this.resetLangRevertTimer();
        return;
      }
      this.selectedLang = lang;
      localStorage.setItem("selectedLang", lang);

      this.hideLanguageOptions();
      this.resetLangRevertTimer();

      // заново тянем данные в нужном языке
      this.fetchStops(); // остановки + обращение губернатора
      this.fetchSights(); // список достопримечательностей
      if (this.selectedSightId) {
        // если была открыта карточка – обновляем и её
        this.selectSight(this.selectedSightId);
      }
      // подтягиваем заголовок обращения губернатора в новом языке
      if (this.governorAppealId) {
        this.loadGovernorAppeal(this.governorAppealId);
      }
      if (this.carrierId) {
        this.fetchCarrierInfo(this.carrierId);
      }
    },
    addLangParam(url) {
      // add ?lang=XX to every API_URL request when language ≠ ru
      if (this.selectedLang !== "ru" && url.startsWith(API_URL)) {
        return (
          url + (url.includes("?") ? "&" : "?") + "lang=" + this.selectedLang
        );
      }
      return url;
    },
    resetLangRevertTimer() {
      clearTimeout(this.langRevertTimer);
      this.langRevertTimer = setTimeout(() => {
        if (this.selectedLang !== "ru") {
          this.setLanguage("ru");
        }
      }, 300000);
    },
  },
  mounted() {
    document.addEventListener("click", this.handleClickOutside);
    ["mousemove", "touchstart", "keydown", "click"].forEach((evt) =>
      document.addEventListener(evt, this.handleUserActivity)
    );
    this.resetInactivityTimer();
    this.resetLangRevertTimer();
    const root = document.documentElement;
    root.style.setProperty("--panel-offset", "20px");
    const routeInfo = document.querySelector(".routeinfo");
    const weatherInfo = document.querySelector(".weatherinfo");
    routeInfo?.classList.add("shifted-left");
    weatherInfo?.classList.add("shifted-left");
    this.fetchStops();
    this.fetchSights();
    this.startStopsPolling();
    console.log("hasGovernorAppeal в mounted:", this.hasGovernorAppeal);
  },
  beforeUnmount() {
    ["mousemove", "touchstart", "keydown", "click"].forEach((evt) =>
      document.removeEventListener(evt, this.handleUserActivity)
    );
    clearTimeout(this.inactivityTimer);
    document.removeEventListener("click", this.handleClickOutside);
    if (this.stopsInterval) {
      clearInterval(this.stopsInterval);
    }
  },
};
</script>

<style scoped>
.sight-transfers {
  margin-top: 8px;
  font-size: 14px;
}
.transfer-row {
  display: flex;
  align-items: center;
}
.transfer-key {
  font-weight: 600;
  margin-right: 4px;
}
.transfer-value {
  white-space: pre;
}
.sight-transfer-list {
  margin-top: 4px;
  margin: 10px 20px 0 20px;
  padding-bottom: 10px;
  font-size: 11px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.transfer-icon {
  width: 18px;
  height: 18px;
  margin-right: 4px;
}

.transfer-text {
  white-space: pre;
  font-size: 16px;
}
/* slide‑fade transition */
.slide-fade-enter-active,
.slide-fade-leave-active {
  transition: all 0.3s ease;
}

.slide-fade-enter-from,
.slide-fade-leave-to {
  opacity: 0;
  transform: translateX(-20px);
}
/* simple fade */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
.language-options {
  display: flex;
  gap: 8px;
  z-index: 1001;
}
.lang-option svg {
  width: 48px;
  height: 48px;
}

.toggle-arrow {
  margin-top: 15px;
}
</style>
