<template>
  <div class="stopinfo">
    <div class="bg">
      <transition name="slide-fade">
        <div
          v-if="cardDetail"
          class="sight-preview-panel left-panel"
          @click.stop
        >
          <div class="sight-preview-wrapper">
            <img v-if="cardDetail.imageUrl" :src="cardDetail.imageUrl" />
          </div>
          <h3>{{ cardDetail.name }}</h3>
          <p>{{ selectedSightArticleBody }}</p>
          <div class="stoparticles">
            <span
              v-for="article in cardDetail.articles"
              :key="article.id"
              :class="{ selected: article.id === selectedSightArticleId }"
              @click.stop="selectSightArticle(article.id)"
              class="stoparticle-option"
            >
              {{ article.heading }}
            </span>
          </div>
        </div>
      </transition>
      <div class="container">
        <div class="image-wrapper">
          <!-- @click="openModal" -->
          <div
            :style="`background-image: url('${imageUrl || defaultImageUrl}')`"
            class="img"
          ></div>
          <img
            v-if="watermarkLU"
            :src="watermarkLU"
            class="watermark watermark-lu"
          />
          <img
            v-if="watermarkRD"
            :src="watermarkRD"
            class="watermark watermark-rd"
          />
        </div>
        <button
          v-if="showBackButton"
          class="back-button"
          @click="returnToNearestSight"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="12"
            height="21"
            fill="none"
            viewBox="0 0 12 21"
          >
            <path
              fill="#fff"
              d="M3.53 10.574c.188.135.316.203.414.3 2.486 2.495 4.966 4.992 7.451 7.486.445.447.623.96.44 1.574a1.485 1.485 0 0 1-2.383.716c-.09-.076-.171-.16-.254-.244L.658 11.82c-.878-.885-.877-1.673.003-2.56C3.539 6.364 6.414 3.463 9.307.58c.252-.25.606-.46.948-.542.646-.154 1.26.184 1.563.75.307.566.22 1.274-.238 1.764-.352.378-.725.736-1.09 1.101-2.195 2.204-4.389 4.407-6.585 6.609-.082.083-.179.15-.374.312Z"
            />
          </svg>

          {{ t("back") }}
        </button>
        <span class="stopname">{{ stopName }}</span>
        <span class="stopdescription">{{ selectedArticleBody }}</span>
        <div class="stoparticles">
          <span
            v-for="article in articles"
            :key="article.id"
            :class="{ selected: article.id === selectedArticleId }"
            @click="selectArticle(article.id)"
            class="stoparticle-option"
          >
            {{ article.heading }}
          </span>
        </div>
      </div>
      <svg
        class="fingers-option"
        xmlns="http://www.w3.org/2000/svg"
        width="39"
        height="48"
        fill="none"
        viewBox="0 0 39 48"
      >
        <path
          fill="#fff"
          fill-rule="evenodd"
          d="M20.072 14.57c0 1.17.5 2.22 1.3 2.95v1.93a5.511 5.511 0 0 1-2.87-4.87c0-3.06 2.49-5.55 5.55-5.55 3.05 0 5.52 2.48 5.51 5.54 0 2.1-1.18 3.93-2.9 4.87v-1.92a3.96 3.96 0 0 0 1.32-2.95c0-2.19-1.76-3.96-3.94-3.96-2.18 0-3.96 1.78-3.96 3.97l-.01-.01Zm14.12 33.34h-9.5c-.08-.28-.15-.56-.22-.83-.17-.65-.34-1.28-.54-1.9-.13-.4-.37-.8-.64-1.12-1.55-1.79-2.57-3.89-3.5-6.04l-.45-1.05c-.65-1.54-1.31-3.07-2.02-4.58-.81-1.7-1.97-3.15-3.48-4.31-.31-.24-.59-.57-.78-.91-.42-.75 0-1.44.85-1.49.99-.05 1.87.3 2.68.82 1.54.97 2.68 2.35 3.76 3.79.3.4.59.82.88 1.23.22.32.48.5.88.37.39-.13.49-.44.49-.82 0-4.57.02-9.13.04-13.7v-2.83c.02-.46.05-.95.53-1.18.57-.28 1.19-.28 1.75.03.19.1.34.36.4.58.08.28.09.6.09.9v8.52c0 .22.02.52.16.64.18.15.51.27.72.21.2-.06.44-.35.48-.57.17-.9.53-1.18 1.56-1.11.8.05 1.23.51 1.23 1.31v2.44c0 .49.26.77.68.77.41 0 .66-.24.71-.71.09-.79.57-1.17 1.45-1.13.8.04 1.31.51 1.31 1.25v2.56c0 .5.23.78.65.8.42.02.68-.24.74-.73.09-.77.64-1.24 1.42-1.22.78.02 1.34.53 1.34 1.3 0 3.01.01 6.02-.03 9.04-.01 1.18-.54 2.23-1.08 3.26-.13.25-.27.51-.4.76-.45.86-.91 1.72-1.27 2.62-.26.65-.43 1.33-.6 2.04-.08.32-.16.65-.25.99h-.04Zm-19.91-16.86a3.94 3.94 0 0 1-3.94-3.96c0-2.19 1.78-3.96 3.96-3.97 1.82 0 3.36 1.24 3.81 2.93a14.1 14.1 0 0 1 1.68 1.58c.02-.18.03-.36.03-.54 0-3.06-2.46-5.54-5.51-5.54s-5.54 2.48-5.54 5.55c0 3.06 2.46 5.54 5.51 5.54.56 0 1.1-.08 1.6-.24-.27-.5-.58-.96-.92-1.4-.22.04-.45.06-.68.06v-.01Z"
          clip-rule="evenodd"
          opacity=".75"
        />
        <path
          fill="#fff"
          d="M9.562 32.63c-.26-.28-.65-.3-.97-.05-.1.08-.19.18-.28.27l-6.51 6.51c-.11.11-.22.2-.4.36v-.56c0-1.52.02-3.04.02-4.56 0-.52-.24-.81-.67-.82-.45 0-.71.29-.71.84-.02 2.25-.04 4.49-.04 6.73 0 .53.24.79.75.79h6.8c.16 0 .35-.04.49-.13.3-.18.37-.48.26-.8-.11-.34-.39-.48-.74-.48h-4.63c-.14 0-.27-.01-.48-.02.14-.15.23-.26.33-.36l6.51-6.51c.09-.09.19-.18.27-.28.25-.3.24-.68 0-.95v.02Zm19.35-23.1c.26.28.65.3.97.05.1-.08.19-.18.28-.27l6.51-6.51c.11-.11.22-.2.4-.36V3c0 1.52-.02 3.04-.02 4.56 0 .52.24.81.67.82.45 0 .71-.29.71-.84l.03-6.73c0-.53-.24-.79-.75-.79-2.26-.02-4.53-.02-6.79-.02-.16 0-.35.04-.49.13-.3.18-.37.48-.26.8.11.34.39.48.74.48h4.63c.14 0 .27.01.48.02-.14.15-.23.26-.33.36l-6.51 6.51c-.09.09-.19.18-.27.28-.25.3-.24.68 0 .95Z"
          opacity=".75"
        />
      </svg>

      <div class="transfer-toggle" @click="toggleTransfers">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="48"
          height="48"
          fill="none"
          viewBox="0 0 48 48"
        >
          <path
            fill="#fff"
            d="M24 0c-.65 0-1.3.03-1.96.08C10.42 1 1.01 10.41.08 22.03c-.51 6.36 1.47 12.25 5.06 16.8.46.59.62 1.38.32 2.06-.7 1.54-1.83 2.75-2.41 3.34-.55.55-1.08 1.04-1.67 1.47-.59.43-.54 1.33.07 1.72.63.4 1.56.57 2.67.57 2.72 0 6.46-1 9.18-1.93.2-.07.4-.1.61-.1.27 0 .55.06.8.17 2.86 1.2 6 1.87 9.29 1.87.65 0 1.32-.03 1.98-.08 11.65-.94 21.08-10.41 21.95-22.07C48.99 11.76 37.87 0 24 0Zm5.51 37.71c-.03.11-.17.23-.28.27-1.49.5-2.96 1.14-4.5 1.44-1.78.35-3.59.26-5.18-.84-1.33-.92-1.82-2.22-1.74-3.78.09-1.89.7-3.67 1.19-5.47.52-1.91 1.11-3.8 1.46-5.74.48-2.65-.68-3.11-3.07-2.85-.59.06-1.16.3-1.81.48.14-.6.25-1.14.41-1.67.03-.1 3.64-1.61 5.45-1.77 1.91-.17 3.76.02 5.16 1.54.79.85 1.01 1.89.99 3.01-.05 2.47-1.01 4.74-1.61 7.09-.37 1.44-.73 2.88-1.05 4.33-.09.4-.09.84-.05 1.25.08.97.56 1.39 1.55 1.57 1.19.21 2.29-.12 3.5-.53-.15.62-.27 1.15-.41 1.66l-.01.01Zm-2.66-22.5c-.2.02-.39.02-.65.04-1.8.02-3.47-1.1-4-2.73-.61-1.87.36-3.81 2.33-4.66 2.26-.98 5.05.21 5.74 2.47.78 2.54-1.21 4.62-3.41 4.88h-.01Z"
          />
        </svg>

        <div v-if="showTransfers" class="transfer-info">
          <div
            v-if="Object.keys(filteredTransfers).length > 0"
            class="transfer-title"
          >
            Доступные пересадки:
          </div>
          <div
            v-for="(value, key) in filteredTransfers"
            :key="key"
            class="transfer-item"
          >
            <img
              v-if="transferIcons[key]"
              :src="transferIcons[key]"
              class="transfer-icon"
              :alt="key"
            />
            <strong v-else>{{ key }}:</strong> {{ value }}
          </div>
        </div>
      </div>
      <transition name="modal">
        <div v-if="isModalOpen" class="modal-overlay" @click="closeModal">
          <img :src="imageUrl" class="modal-image" @click.stop />
          <button class="modal-close" @click.stop="closeModal">×</button>
        </div>
      </transition>
      <transition name="expand-collapse-transition">
        <div class="landmarks-container">
          <div class="landmarks" @click="toggleSightsList">
            <div class="landmarks-header">
              <svg
                class="landmarks-arrow"
                :class="{ 'arrow-rotated': showSightsList }"
                xmlns="http://www.w3.org/2000/svg"
                width="25"
                height="15"
                fill="none"
                viewBox="0 0 25 15"
              >
                <path
                  fill="#fff"
                  fill-opacity=".85"
                  d="M.382 11.643c-.24.227-.382.553-.382.92 0 .737.552 1.29 1.288 1.29.368 0 .708-.128.92-.368L13.052 2.408h-1.515l10.844 11.077c.227.24.566.368.92.368a1.26 1.26 0 0 0 1.289-1.29 1.25 1.25 0 0 0-.383-.92L13.25.425A1.288 1.288 0 0 0 12.302 0a1.32 1.32 0 0 0-.963.425L.382 11.643Z"
                />
              </svg>
              <span class="header-name">{{ t("sights") }}</span>

              <button
                v-if="showLangToggle"
                class="language-toggle"
                @click="toggleLanguageOptions"
                @click.stop
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="28"
                  height="28"
                  fill="none"
                  viewBox="0 0 28 28"
                >
                  <path
                    fill="#fff"
                    fill-rule="evenodd"
                    d="M0 14C0 6.27 6.27 0 14 0s14 6.27 14 14-6.27 14-14 14S0 21.73 0 14Zm21.03-2.678 1.294 3.536 1.284-3.547-.759.222c-.006-.012-.006-.245-.006-.263-.338-4.03-3.599-7.1-7.711-7.1a.558.558 0 0 0-.554.555c0 .303.25.554.554.554 3.488 0 6.265 2.579 6.603 5.985l.003.137.003.137-.712-.216ZM5.193 16.063a9.797 9.797 0 0 0 3.888-1.897 7.8 7.8 0 0 0 3.449 1.906.784.784 0 0 0 .186 0c.303.032.6-.094.78-.33a.798.798 0 0 0 .094-.819.851.851 0 0 0-.688-.487 5.887 5.887 0 0 1-2.541-1.399 11.906 11.906 0 0 0 3.151-4.907.797.797 0 0 0-.17-.712.857.857 0 0 0-.677-.328H9.701V6.068a.814.814 0 0 0-.424-.708.872.872 0 0 0-.847 0 .813.813 0 0 0-.423.708v1.038H5.042a.854.854 0 0 0-.734.41.793.793 0 0 0 0 .817.854.854 0 0 0 .734.41h6.43A11.292 11.292 0 0 1 9.166 11.9a11.17 11.17 0 0 1-1.338-1.89.833.833 0 0 0-.484-.47.874.874 0 0 0-.687.03.826.826 0 0 0-.437.511.793.793 0 0 0 .1.657 13 13 0 0 0 1.584 2.184 8 8 0 0 1-3.058 1.505.86.86 0 0 0-.574.3.801.801 0 0 0 .126 1.157c.176.138.4.202.625.18a.573.573 0 0 0 .17 0Zm15.164 6.617a.874.874 0 0 0 .646.016.838.838 0 0 0 .497-.424c.099-.2.11-.432.028-.64L17.7 12.12a.824.824 0 0 0-.31-.38.869.869 0 0 0-.954-.004.826.826 0 0 0-.312.375l-3.795 9.194a.796.796 0 0 0 .123.81.864.864 0 0 0 1.453-.205l.915-2.282h4.032l1.06 2.602a.832.832 0 0 0 .446.45Zm-3.497-8 1.33 3.313h-2.694l1.364-3.313Z"
                    clip-rule="evenodd"
                  />
                </svg>
              </button>

              <!-- тройка языковых иконок -->
              <div
                v-if="showLanguageOptions"
                class="language-options"
                @click.stop
              >
                <!-- RU -->
                <button
                  class="language-option"
                  :style="{ opacity: selectedLang === 'ru' ? 1 : 0.8 }"
                  @click="setLanguage('ru')"
                  v-html="icons.ru"
                />
                <!-- EN -->
                <button
                  class="language-option"
                  :style="{ opacity: selectedLang === 'en' ? 1 : 0.8 }"
                  @click="setLanguage('en')"
                  v-html="icons.en"
                />
                <!-- ZH -->
                <button
                  class="language-option"
                  :style="{ opacity: selectedLang === 'zh' ? 1 : 0.8 }"
                  @click="setLanguage('zh')"
                  v-html="icons.zh"
                />
              </div>
            </div>
          </div>
          <transition name="slide-fade">
            <div
              v-show="true"
              class="sights-wrapper"
              :style="{ maxHeight: showSightsList ? '500px' : '0px' }"
            >
              <div class="sights-alphabet">
                <span
                  v-for="letter in availableLetters"
                  :key="letter"
                  @click="selectLetter(letter)"
                >
                  {{ letter }}
                </span>
              </div>
              <div
                class="sights-grid scrollable-container"
                ref="scrollContainer"
              >
                <div
                  v-for="(group, letter) in groupedSights"
                  :key="letter"
                  class="sight-letter-group"
                >
                  <span :ref="'letter-' + letter" class="letter-anchor"></span>
                  <div
                    v-for="sight in group"
                    :key="sight.id"
                    class="sight-card"
                    :class="{
                      'selected-card': sight.id === selectedSightCardId,
                    }"
                    @click.stop="openSightCardDetails(sight.id)"
                  >
                    <div class="sight-thumbnail">
                      <img :src="sight.thumbnailUrl" />
                    </div>
                    <div class="sight-title">{{ sight.name }}</div>
                  </div>
                </div>
              </div>
            </div>
          </transition>
        </div>
      </transition>
    </div>
  </div>
</template>

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

import axios from "axios";

export default {
  name: "StopInfo",
  data() {
    return {
      isModalOpen: false,
      autoCloseTimer: null,
      articleInactivityTimer: null,
      sightsInactivityTimer: null,
      imageUrl: "",
      defaultImageUrl:
        "https://lh3.googleusercontent.com/gps-cs-s/AB5caB8lUwofb2NIg6n0-cEl8nIWsySAUc52KNj4XezuOdo-aeqTgQlD1kTVa5MaynL2Yg4ByoTYTKNTR7K59f7kjzU9yzpudstjRiT2F6M_ilxFYFpcvMZz6OwlRFF2MrsCPSwUa7vqew=s680-w680-h510",
      sightId: 17,
      manualSightId: null,
      nearestSightId: null,
      returnTimer: null,
      lastUserActivity: Date.now(),
      firstLoad: true,
      stopName: "",
      watermarkLU: "",
      watermarkRD: "",
      articles: [],
      selectedArticleId: null,
      selectedArticleBody: "",
      selectedSightArticleId: null,
      selectedSightArticleBody: "",
      sights: [],
      showSightsList: false,
      selectedLetter: null,
      selectedSightCardId: null,
      cardDetail: null,
      showTransfers: false,
      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"),
      },
      nextStopTransfers: null,
      stops: [],
      routeProgress: null,
      routeId: null,
      selectedLang: localStorage.getItem("selectedLangRight") || "ru",
      showLangToggle: true,
      showLanguageOptions: false,
      languageOptionsTimer: null,
      langRevertTimer: null,
      icons: {
        ru: `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 28 28">
  <path fill="#fff" d="M14 0C6.27 0 0 6.27 0 14s6.27 14 14 14 14-6.27 14-14S21.73 0 14 0Zm.117 19.57H11.62l-2.117-4.135H7.646v4.136H5.32V8.27h4.2c1.336 0 2.363.298 3.092.893.729.595 1.085 1.435 1.085 2.52 0 .77-.17 1.412-.502 1.931-.332.513-.84.928-1.517 1.23l2.444 4.62v.112l-.005-.006Zm9.391-3.855c0 1.237-.385 2.217-1.16 2.934-.776.718-1.832 1.08-3.174 1.08-1.341 0-2.368-.35-3.144-1.05-.776-.7-1.173-1.657-1.19-2.882V8.272h2.328v7.46c0 .741.175 1.278.53 1.616.356.339.846.508 1.47.508 1.307 0 1.972-.689 1.995-2.065V8.27h2.334v7.444h.011Z"/>
  <path fill="#fff" d="M9.513 10.156H7.641v3.389h1.878c.583 0 1.038-.152 1.36-.45.32-.297.478-.705.478-1.23s-.152-.95-.455-1.26c-.304-.31-.77-.46-1.394-.46l.005.01Z"/>
</svg>`,
        en: `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 28 28">
  <path fill="#fff" d="M14 0C6.27 0 0 6.27 0 14s6.27 14 14 14 14-6.27 14-14S21.73 0 14 0Zm-1.418 19.71H4.906V8.255h7.665v1.914H7.263v2.73h4.532v1.849H7.263v3.068h5.32v1.896Zm10.483 0h-2.363l-4.596-7.536v7.537h-2.363V8.254h2.363l4.602 7.554V8.254h2.351v11.457h.006Z"/>
</svg>`,
        zh: `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 28 28">
  <path fill="#fff" d="M6 11.89H3.67v2.196H6v-2.197Zm1.994 2.196h2.343v-2.197H7.994v2.197Zm13.079-2.392h-3.656a10.503 10.503 0 0 0 1.863 2.96c.735-.833 1.33-1.813 1.793-2.96Z"/>
  <path fill="#fff" fill-rule="evenodd" d="M14 28c7.732 0 14-6.268 14-14S21.732 0 14 0 0 6.268 0 14s6.268 14 14 14ZM6 7.875h1.994v2.132h4.324v6.586h-1.98v-.624H7.993v3.846H6.001V15.97H3.67v.686H1.75v-6.649H6V7.876Zm12.288 0h1.956v1.936h4.888v1.883h-1.864c-.632 1.694-1.466 3.113-2.512 4.293 1.206.885 2.674 1.545 4.425 1.938l.396.09-.292.281c-.333.322-.798.999-1.025 1.417l-.082.15-.166-.043c-1.94-.507-3.523-1.298-4.822-2.364-1.323 1.033-2.892 1.814-4.722 2.386l-.183.057-.08-.173c-.163-.348-.617-1.042-.902-1.387l-.218-.263.33-.088c1.714-.45 3.153-1.089 4.34-1.95-1.026-1.218-1.819-2.671-2.448-4.345h-1.834V9.812h4.815V7.875Z" clip-rule="evenodd"/>
</svg>`,
      },
      translations: {
        sights: { ru: "Достопримечательности", en: "Landmarks", zh: "景点" },
        back: { ru: "Вернуться назад", en: "Back", zh: "返回" },
      },
    };
  },
  computed: {
    availableLetters() {
      const letters = this.sights
        .map((s) => {
          if (!s.name || typeof s.name !== "string") {
            console.warn("Invalid sight object or missing name:", s);
            return null;
          }
          return s.name[0].toUpperCase();
        })
        .filter((l) => l !== null);
      return [...new Set(letters)].sort((a, b) => a.localeCompare(b, "ru"));
    },
    groupedSights() {
      const map = {};
      const validSights = this.sights.filter((sight) => {
        const isValid = sight.name && typeof sight.name === "string";
        if (!isValid) {
          console.warn("Skipping invalid sight in groupedSights:", sight);
        }
        return isValid;
      });
      const sorted = validSights.sort((a, b) =>
        a.name.localeCompare(b.name, "ru")
      );
      for (const sight of sorted) {
        const letter = sight.name[0].toUpperCase();
        if (!map[letter]) map[letter] = [];
        map[letter].push(sight);
      }
      return map;
    },
    filteredTransfers() {
      if (!this.nextStopTransfers) return {};
      return Object.fromEntries(
        Object.entries(this.nextStopTransfers).filter(([, value]) => value)
      );
    },
    showBackButton() {
      return this.sightId !== this.nearestSightId;
    },
  },
  methods: {
    t(key) {
      const dict = this.translations[key] || {};
      return dict[this.selectedLang] || dict.ru || key;
    },
    // показать 3 иконки
    toggleLanguageOptions() {
      this.showLangToggle = false;
      this.showLanguageOptions = true;
      this.startLanguageOptionsTimer();
    },

    // таймер 10 с
    startLanguageOptionsTimer() {
      clearTimeout(this.languageOptionsTimer);
      this.languageOptionsTimer = setTimeout(this.hideLanguageOptions, 10_000);
    },

    // скрыть 3 иконки, вернуть глобус
    hideLanguageOptions() {
      this.showLanguageOptions = false;
      this.showLangToggle = true;
    },

    // выбор языка
    setLanguage(lang) {
      if (this.selectedLang === lang) {
        this.hideLanguageOptions();
        this.resetLangRevertTimer();
        return;
      }
      this.selectedLang = lang;
      localStorage.setItem("selectedLangRight", lang);
      this.hideLanguageOptions();
      this.resetLangRevertTimer();

      // перезагрузить данные на новом языке
      this.fetchSightInfo();
      this.fetchArticles();
      this.fetchSights();
    },

    // добавить ?lang=… к URL-у, если язык не ru
    addLangParam(url) {
      if (this.selectedLang !== "ru") {
        return (
          url + (url.includes("?") ? "&" : "?") + "lang=" + this.selectedLang
        );
      }
      return url;
    },

    // таймер 5 минут с возврата на ru
    resetLangRevertTimer() {
      clearTimeout(this.langRevertTimer);
      this.langRevertTimer = setTimeout(() => {
        if (this.selectedLang !== "ru") this.setLanguage("ru");
      }, 300_000);
    },
    openModal() {
      const imageDiv = this.$el.querySelector(".img");
      if (imageDiv) {
        const bgImage = window.getComputedStyle(imageDiv).backgroundImage;
        this.imageUrl = bgImage.slice(5, bgImage.length - 2);
      }
      this.isModalOpen = true;
      this.autoCloseTimer = setTimeout(() => {
        this.closeModal();
      }, 30000);
    },
    closeModal() {
      this.isModalOpen = false;
      if (this.autoCloseTimer) {
        clearTimeout(this.autoCloseTimer);
        this.autoCloseTimer = null;
      }
    },
    async fetchSightInfo() {
      if (!this.sightId) {
        console.log("No sightId provided for fetchSightInfo");
        return;
      }
      const response = await axios.get(
        this.addLangParam(`${API_URL}/sight/${this.sightId}`)
      );
      this.stopName = response.data.name;
      if (response.data.watermark_lu) {
        this.watermarkLU = await this.getMediaBlobUrl(
          response.data.watermark_lu
        );
      } else {
        this.watermarkLU = "";
      }
      if (response.data.watermark_rd) {
        this.watermarkRD = await this.getMediaBlobUrl(
          response.data.watermark_rd
        );
      } else {
        this.watermarkRD = "";
      }
    },
    async fetchArticles() {
      if (!this.sightId) {
        console.warn("No sightId provided for fetchArticles");
        return;
      }
      const response = await axios.get(
        this.addLangParam(`${API_URL}/sight/${this.sightId}/article`)
      );
      this.articles = response.data;
      if (this.articles.length > 0) {
        this.selectArticle(this.articles[0].id);
        this.resetArticleInactivityTimer();
      }
    },
    async fetchSights() {
      // Prefer cached routeId, otherwise fetch context once
      let routeId = this.routeId;
      if (!routeId) {
        try {
          const geoRes = await axios.get(`${GEO_URL}/v1/geolocation/context`);
          routeId = geoRes.data.routeId;
          if (routeId && routeId !== this.routeId) {
            this.routeId = routeId;
          }
        } catch (error) {
          console.error("Failed to get routeId from context:", error);
          return;
        }
      }
      if (!routeId) {
        console.warn("Missing routeId — skipping fetchSights");
        return;
      }
      try {
        const sightsRes = await axios.get(
          this.addLangParam(`${API_URL}/route/${routeId}/sight`)
        );
        const rawSights = sightsRes.data;
        const detailedSights = await Promise.all(
          rawSights.map(async (sight) => {
            const detailRes = await axios.get(
              this.addLangParam(`${API_URL}/sight/${sight.id}`)
            );
            const thumbnailUrl = detailRes.data.thumbnail
              ? await this.getMediaBlobUrl(detailRes.data.thumbnail)
              : "";
            return {
              id: sight.id,
              name: detailRes.data.name,
              thumbnailUrl,
            };
          })
        );
        this.sights = detailedSights;
      } catch (error) {
        console.error("Error fetching sights:", error);
      }
    },
    async openSightCardDetails(id) {
      this.manualSightId = id;
      this.sightId = id;
      this.showSightsList = false;
      this.selectedSightCardId = null;
      this.cardDetail = null;
      this.resetReturnTimer();
      await this.fetchSightInfo();
      await this.fetchArticles();
    },
    async selectSightArticle(id) {
      this.selectedSightArticleId = id;
      const selected = this.cardDetail?.articles.find((a) => a.id === id);
      this.selectedSightArticleBody = selected ? selected.body : "";
      if (selected && selected.media && selected.media.length > 0) {
        try {
          this.cardDetail.imageUrl = await this.getMediaBlobUrl(
            selected.media[0].id
          );
        } catch {
          this.cardDetail.imageUrl = this.addLangParam(
            `${API_URL}/media/${selected.media[0].id}/download`
          );
        }
      }
    },
    hideSightUI() {
      this.showSightsList = false;
      this.selectedSightCardId = null;
      this.cardDetail = null;
    },
    toggleSightsList() {
      // переключаем видимость
      this.showSightsList = !this.showSightsList;

      // если список теперь скрыт — закрываем и карточку, сбрасываем таймер
      if (!this.showSightsList) {
        this.selectedSightCardId = null;
        this.cardDetail = null;
        if (this.sightsInactivityTimer) {
          clearTimeout(this.sightsInactivityTimer);
          this.sightsInactivityTimer = null;
        }
      } else {
        // список открыт — запускаем таймер неактивности
        this.resetSightsInactivityTimer();
      }
    },
    resetSightsInactivityTimer() {
      if (this.sightsInactivityTimer) clearTimeout(this.sightsInactivityTimer);

      // запускаем новый, если открыт список или карточка
      if (this.showSightsList || this.cardDetail) {
        this.sightsInactivityTimer = setTimeout(() => {
          this.hideSightUI(); // скрываем всё
          this.sightsInactivityTimer = null;
        }, 300_000); // 5 m
      }
    },
    resetArticleInactivityTimer() {
      if (this.articleInactivityTimer)
        clearTimeout(this.articleInactivityTimer);

      this.articleInactivityTimer = setTimeout(() => {
        if (
          this.articles.length > 0 &&
          this.selectedArticleId !== this.articles[0].id
        ) {
          this.selectArticle(this.articles[0].id);
        }
      }, 300_000); // 5 m
    },
    handleUserActivity() {
      this.lastUserActivity = Date.now();
      if (this.showSightsList || this.cardDetail)
        this.resetSightsInactivityTimer();
      this.resetArticleInactivityTimer();
      this.resetLangRevertTimer();
      if (this.returnTimer) this.resetReturnTimer();
    },
    selectArticle(id) {
      this.resetArticleInactivityTimer();
      this.selectedArticleId = id;
      const selected = this.articles.find((article) => article.id === id);
      this.selectedArticleBody = selected ? selected.body : "";
      this.fetchArticleMedia(id);
    },
    async fetchArticleMedia(articleId) {
      try {
        const response = await axios.get(
          this.addLangParam(`${API_URL}/article/${articleId}/media`)
        );
        if (response.data && response.data.length > 0) {
          const mediaId = response.data[0].id;
          try {
            this.imageUrl = await this.getMediaBlobUrl(mediaId);
          } catch {
            this.imageUrl = this.addLangParam(
              `${API_URL}/media/${mediaId}/download`
            );
          }
        } else {
          this.imageUrl = "";
        }
      } catch (error) {
        console.error("Error fetching article media:", error);
        this.imageUrl = "";
      }
    },

    async getMediaBlobUrl(mediaId) {
      try {
        const response = await axios.get(
          this.addLangParam(`${API_URL}/media/${mediaId}/download`),
          {
            responseType: "blob",
          }
        );
        return URL.createObjectURL(response.data);
      } catch (error) {
        console.error(
          `Failed to download media ${mediaId}:`,
          error?.response?.status,
          error?.response?.data || error.message
        );
        return this.addLangParam(`${API_URL}/media/${mediaId}/download`);
      }
    },
    async fetchGeolocationContext() {
      try {
        const response = await axios.get(
          this.addLangParam(`${GEO_URL}/v1/geolocation/context`)
        );
        this.routeProgress = response.data.routeProgress;
        const newRouteId = response.data.routeId;
        if (newRouteId && newRouteId !== this.routeId) {
          this.routeId = newRouteId;
        }
        if (this.routeId) {
          const stopsResponse = await axios.get(
            this.addLangParam(`${API_URL}/route/${this.routeId}/station`)
          );
          this.stops = stopsResponse.data;
        } else {
          this.stops = [];
        }
        let newSightId = response.data.nearestSightId;

        if (!newSightId) {
          if (!this.sights || this.sights.length === 0) {
            await this.fetchSights();
          }
          if (this.sights && this.sights.length > 0) {
            newSightId = this.sights[1].id;
          }
        }
        if (newSightId) {
          if (this.firstLoad) {
            this.nearestSightId = newSightId;
            this.sightId = newSightId;
            await this.fetchSightInfo();
            await this.fetchArticles();
            this.firstLoad = false;
            this.clearReturnTimer();
            return;
          }
          if (this.nearestSightId !== newSightId) {
            this.nearestSightId = newSightId;
          }
          if (!this.manualSightId) {
            if (this.sightId !== this.nearestSightId) {
              const userActive = Date.now() - this.lastUserActivity < 15_000; // 15-сек. окно
              if (userActive) {
                this.resetReturnTimer();
              } else {
                this.clearReturnTimer();
                this.sightId = this.nearestSightId;
                await this.fetchSightInfo();
                await this.fetchArticles();
              }
            } else {
              this.clearReturnTimer();
            }
          }
        }
        const nextStopId = response.data.routeProgress?.endStopId;
        if (nextStopId && this.stops) {
          const nextStop = this.stops.find((stop) => stop.id == nextStopId);
          if (nextStop && nextStop.transfers) {
            this.nextStopTransfers = nextStop.transfers;
          } else {
            this.nextStopTransfers = null;
          }
        }
      } catch (error) {
        console.error("Error fetching geolocation context:", error);
      }
    },
    resetReturnTimer() {
      this.clearReturnTimer();
      this.returnTimer = setTimeout(() => {
        this.returnToNearestSight();
      }, 90_000);
    },
    clearReturnTimer() {
      if (this.returnTimer) {
        clearTimeout(this.returnTimer);
        this.returnTimer = null;
      }
    },
    returnToNearestSight() {
      if (!this.nearestSightId) return;
      this.manualSightId = null;
      this.sightId = this.nearestSightId;
      this.clearReturnTimer();
      this.showSightsList = false;
      this.selectedSightCardId = null;
      this.cardDetail = null;
      this.fetchSightInfo();
      this.fetchArticles();
    },
    selectLetter(letter) {
      const anchorArr = this.$refs[`letter-${letter}`];
      const anchor = anchorArr ? anchorArr[0] : null;
      const container = this.$refs.scrollContainer;

      if (!anchor || !container) return;

      let target = anchor.nextElementSibling;
      if (!target || !target.classList.contains("sight-card")) {
        target = anchor;
      }

      const top = target.offsetTop;
      container.scrollTo({ top, behavior: "smooth" });
    },
    toggleTransfers() {
      console.log("Transfer toggle clicked");
      this.showTransfers = !this.showTransfers;
      // console.log("showTransfers:", this.showTransfers);

      if (!this.showTransfers) {
        return;
      }

      if (!this.stops || !this.routeProgress) {
        console.warn("Missing stops or routeProgress");
        return;
      }

      const nextStopId = this.routeProgress.endStopId;
      // console.log("Next stop ID from routeProgress:", nextStopId);
      // console.log("All stops:", this.stops);

      const nextStop = this.stops.find((stop) => stop.id === nextStopId);
      // console.log("Next stop object:", nextStop);

      if (nextStop && nextStop.transfers) {
        // console.log("Transfers at next stop:", nextStop.transfers);
        this.nextStopTransfers = nextStop.transfers;
      } else {
        // console.log("No transfers found at next stop");
        this.nextStopTransfers = null;
      }
    },
  },
  watch: {
    routeId(newVal, oldVal) {
      if (newVal && newVal !== oldVal) {
        // Refresh sights because routeId changed
        this.fetchSights();
      }
    },
  },
  async mounted() {
    await this.fetchSights();
    await this.fetchGeolocationContext();
    this.nearestSightId = this.sightId;
    this.geolocationInterval = setInterval(() => {
      this.fetchGeolocationContext();
    }, 1000);
    window.addEventListener("mousemove", this.handleUserActivity);
    window.addEventListener("touchstart", this.handleUserActivity, {
      passive: true,
    });
    window.addEventListener("keydown", this.handleUserActivity);
    window.addEventListener("click", this.handleUserActivity, true);
    // this.fetchSightInfo();
    // this.fetchArticles();
    this.resetLangRevertTimer();
  },
  unmounted() {
    if (this.sightsInactivityTimer) {
      clearTimeout(this.sightsInactivityTimer);
    }
    window.removeEventListener("mousemove", this.handleUserActivity);
    window.removeEventListener("touchstart", this.handleUserActivity, {
      passive: true,
    });
    window.removeEventListener("keydown", this.handleUserActivity);
    window.removeEventListener("click", this.handleUserActivity, true);
    if (this.autoCloseTimer) {
      clearTimeout(this.autoCloseTimer);
    }
    if (this.geolocationInterval) {
      clearInterval(this.geolocationInterval);
    }
  },
};
</script>
