<script setup>
import {ref, computed, onMounted, watch} from 'vue';
import {useAuthStore} from '@/stores/Auth';
import {useMapPrintStore} from '@/stores/MapPrint';
import {useDisplayMapStore} from '@/stores/DisplayMap';
import {useRouter} from 'vue-router';
import Flatpickr from 'vue-flatpickr-component';
import 'flatpickr/dist/flatpickr.css';
import {Russian} from 'flatpickr/dist/l10n/ru.js';

const authStore = useAuthStore();
const displayMap = useDisplayMapStore();
const printStore = useMapPrintStore();
const router = useRouter();
let objectManager;
let polylineCollection;
const rawPoints = ref([])
const editingPlan = ref(null);
const isSaving = ref(false);


const holidayDates = [
  '2025-01-01',
  '2025-01-07',
  '2025-03-08',
  '2025-05-01',
  '2025-05-02',
  '2025-05-08',
  '2025-05-09',
  '2025-06-12',
  '2025-06-13',
  '2025-11-03',
  '2025-11-04',
  '2025-12-31',
];

const fpConfig = {
  dateFormat: 'Y-m-d',
  altInput: true,
  altFormat: 'd.m.Y',
  locale: {
    ...Russian,
    firstDayOfWeek: 1,
  },
  disable: [
    (date) => date.getDay() === 0 || date.getDay() === 6,
    ...holidayDates.map((d) => new Date(d)),
  ],
};

const selectedPoint = ref(null);
const showModal = ref(false);
const form = ref({
  point_id: null,
  day: '',
  timeStart: '',
  timeEnd: '',
  subgroup_manager_id: '', // ← здесь
  counter_id: '',
});
const subgroupManagers = ref([]);
const counters = ref([]);
const formError = ref('');
const selectedManagerId = ref(null);
const selectedDate = ref('');

// Список подписей (месяц/год) по расписанию
const signatures = ref([]);
// Множество строк "YYYY-M" подписанных периодов
const signedPeriods = computed(() => {
  if (!selectedRequestId.value) return new Set();
  return new Set(
      signatures.value
          .filter(s => s.request_id === selectedRequestId.value)
          .map(s => `${s.year}-${s.month}`)
  );
});

// Проверка подписи для месяца из даты
function isSigned(dateStr) {
  const d = new Date(dateStr);
  const key = `${d.getFullYear()}-${d.getMonth() + 1}`;
  return signedPeriods.value.has(key);
}

// вычисляемая: текущая роль пользователя
const isSubgroupManagerRole = computed(() => {
  return authStore.user?.role?.name === 'Менеджер подгруппы';
});

// Открываем модалку (редактируем или создаём новый назначенный план)
function openAssignModal(point) {
  formError.value = '';
  editingPlan.value = null; // по умолчанию считаем, что создаём новый

  // пытаемся найти существующий план по текущей заявке (если редактируем)
  const plan = point.plans.find(
      p => Number(p.request_id) === Number(selectedRequestId.value)
  );
  if (plan) {
    // --- РЕДАКТИРУЕМ СУЩЕСТВУЮЩИЙ ПЛАН ---
    editingPlan.value = plan;
    form.value = {
      point_id: plan.point_id,
      schedule_id: plan.schedule_id,
      day: plan.day.split('T')[0],
      timeStart: toTimeStr(plan.timeStart),
      timeEnd: toTimeStr(plan.timeEnd),
      subgroup_manager_id: plan.subgroup_manager_id,
      counter_id: plan.counter_id,
      comment: plan.comment || '',
    };
  } else {
    // --- СОЗДАЁМ НОВЫЙ ---
    // Всегда устанавливаем текущую точку
    form.value.point_id = point.id;
    form.value.schedule_id = 1;
    form.value.day = new Date().toISOString().slice(0, 10);
    form.value.timeStart = '';
    form.value.timeEnd = '';
    form.value.comment = '';

    // Если залогинен «Менеджер подгруппы» — сразу ставим его
    if (isSubgroupManagerRole.value) {
      form.value.subgroup_manager_id = authStore.user.id;
    } else {
      // иначе сбрасываем селект — админ/регионал сможет выбрать
      form.value.subgroup_manager_id = '';
    }
    form.value.counter_id = '';
  }

  showModal.value = true;
}

const updateEndTime = () => {
  const [hours, minutes] = form.value.timeStart.split(':').map(Number);
  const durationHours = form.value.timeStart === '18:00' ? 2 : 4;
  const newHours = (hours + durationHours) % 24;
  form.value.timeEnd = `${String(newHours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
};

const saveAssignment = async () => {
  if (isSaving.value) return;
  isSaving.value = true;
  formError.value = ''; // сбрасываем старые ошибки
  if (isSigned(form.value.day)) {
    formError.value = 'Нельзя назначать работы за подписанный месяц.';
    isSaving.value = false;
    return;
  }
  const payload = {
    ...form.value,
    request_id: Number(selectedRequestId.value),
  };
  try {
    let result;
    if (editingPlan.value) {
      // редактируем существующий
      result = await authStore.updatePointPlan(editingPlan.value.id, payload);
    } else {
      // создаём новый
      result = await authStore.savePointPlan(payload);
    }

    if (result.error) {
      if (result.error.status === 409) {
        formError.value = result.error.data?.error || 'Учетчик уже занят в это время.';
      } else {
        formError.value = result.error.data?.error || 'Ошибка при назначении работ';
      }
      isSaving.value = false;
      return;
    }

    showModal.value = false;
    alert('Работы успешно назначены');
    await refreshPoints();

  } catch (err) {
    console.error(err);
    formError.value = 'Ошибка при отправке данных';
  } finally {
    isSaving.value = false;   // Снимаем блокировку в любом случае!
  }
};

const period = ref('summer');

const summerTimes = ['08:00', '13:00'];
const winterTimes = ['09:00', '14:00'];

const timeOptions = computed(() => {
  return period.value === 'summer' ? summerTimes : winterTimes;
});
// Права: теперь подгруппа или учетчик
const canAssignWork = computed(() =>
    authStore.hasPermission('create-point-plans')
);

const allPoints = ref([]);
const selectedDistrictId = ref(null);
const selectedCategory = ref(null);
const selectedFrequency = ref(null);

const selectedRequestId = ref(null); // фильтр по заявке
const requestsList = ref([]);

const frequencyLabels = {
  1: 'Ежемесячно',
  2: 'Ежеквартально',
};

const formatDate = (dateStr) => {
  const date = new Date(dateStr);
  return date.toLocaleDateString('ru-RU');
};

const districtOptions = computed(() => {
  const set = new Map();
  rawPoints.value.forEach((p) => {
    if (p.district) set.set(p.district.id, p.district);
  });
  return Array.from(set.values()).sort((a, b) => a.name.localeCompare(b.name, 'ru'));
});

const uniqueCategories = computed(() => {
  // Строим полный список категорий по «сырым» данным
  const set = new Set();
  rawPoints.value.forEach((p) => {
    if (!p.road_category || p.road_category.length === 0) {
      set.add('Без категории');
    } else {
      (Array.isArray(p.road_category) ? p.road_category : [p.road_category])
          .forEach((cat) => set.add(cat));
    }
  });
  return Array.from(set).sort();
});

function toTimeStr(val) {
  if (!val) return '';
  if (val.length === 5) return val; // "08:00"
  // если ISO: "2025-06-14T08:00:00.000000Z"
  const t = val.match(/T(\d{2}:\d{2})/);
  return t ? t[1] : val.slice(11, 16); // "08:00"
}

const sortedPoints = computed(() => {
  return allPoints.value.filter((point) => {
    const categories = Array.isArray(point.road_category)
        ? point.road_category
        : typeof point.road_category === 'string'
            ? [point.road_category]
            : [];

    const hasNoCategory = !point.road_category || categories.length === 0;

    const matchesDistrict = !selectedDistrictId.value || point.district_id === selectedDistrictId.value;

    const matchesCategory =
        selectedCategory.value === null ||
        (selectedCategory.value === 'Без категории' && hasNoCategory) ||
        categories.includes(selectedCategory.value);

    const matchesFreq =
        !selectedFrequency.value || Number(point.monitoring_freq) === Number(selectedFrequency.value);

    const matchesRequest = !selectedRequestId.value
        // если у точки есть связь requests — тоже ок
        || (point.requests && point.requests.some(r => r.id === selectedRequestId.value))
        // но в первую очередь смотрим на plans (они всегда подгружаются)
        || point.plans.some(pl => pl.request_id === selectedRequestId.value);

    // Фильтр по менеджеру подгруппы
    if (selectedManagerId.value) {
      // ищем хотя бы один PLAN, назначенный этому менеджеру
      const belongsToMgr = point.plans.some(pl =>
          pl.subgroup_manager_id === selectedManagerId.value
          // и, если выбрана заявка, только внутри неё
          && (!selectedRequestId.value || pl.request_id === selectedRequestId.value)
      );
      if (!belongsToMgr) {
        return false;
      }
    }

    // Фильтр по дате работ
    if (selectedDate.value) {
      const onDate = point.plans.some(
          pl => pl.day.split('T')[0] === selectedDate.value
      );
      if (!onDate) return false;
    }

    return matchesDistrict && matchesCategory && matchesFreq && matchesRequest;
  });
});

watch([selectedRequestId, selectedManagerId, selectedDate], () => {
  allPoints.value.forEach(p => {
    objectManager.objects.setObjectProperties(p.id, {
      balloonContent: buildBalloonContent(p)
    });
  });
});

const filteredCount = computed(() => sortedPoints.value.length);

const scheduledCount = computed(() => {
  // если ни заявка, ни месяц не выбраны — ничего не считаем
  if (!selectedRequestId.value) return 0

  return sortedPoints.value.reduce((sum, p) => {
    // для каждой точки считаем планы, которые соответствуют фильтрам
    const cnt = p.plans.filter(pl => {
      return !(selectedRequestId.value && pl.request_id !== selectedRequestId.value);


    }).length
    return sum + cnt
  }, 0)
})
const saveMapToPDF = () => {

  printStore.setPoints(sortedPoints.value);
  window.open('/map-print-live', '_blank');
};

const visiblePointsCount = computed(() => {
  return sortedPoints.value.filter(
      (p) =>
          (p.latitude && p.longitude) ||
          (p.geojson &&
              ((typeof p.geojson === 'string' && p.geojson.includes('LineString')) ||
                  (typeof p.geojson === 'object' &&
                      p.geojson.features?.some((f) => f.geometry?.type === 'LineString')))),
  ).length;
});

watch(
    () => printStore.needRefreshMap,
    async (newVal) => {
      if (newVal) {
        console.log('♻️ Обновляем карту после удаления плана');
        await refreshPoints();
        printStore.resetMapRefresh(); // ❗ Обязательно сбрасываем флаг
      }
    }
);
watch(sortedPoints, pts => {
  printStore.setPoints(pts);
}, {immediate: true});

function paintPoints(pts) {
  if (!objectManager || !polylineCollection) return;
  const visibleIds = new Set(pts.map(p => Number(p.id)));
  objectManager.setFilter(feature => visibleIds.has(Number(feature.id)));
  const now = new Date();

  pts.forEach(p => {
    // 1) Базовый цвет по наличию работы и частоте
    const freq = Number(p.monitoring_freq);
    const hasWork = p.plans.some(pl =>
        Number(pl.request_id) === Number(selectedRequestId.value)
    );
    let preset = hasWork
        ? (freq === 1
            ? 'islands#greenStretchyIcon'
            : 'islands#darkGreenStretchyIcon')
        : (freq === 1
            ? 'islands#greyStretchyIcon'
            : 'islands#blackStretchyIcon');

    // 2) Ищем именно тот план, который задан фильтрами (заявка + месяц)
    const plan = p.plans.find(pl =>
        Number(pl.request_id) === Number(selectedRequestId.value)
    );

    if (plan) {
      // 3) Переопределяем цвет на жёлтый, если есть замечания
      if (plan.comment?.trim()) {
        preset = 'islands#yellowStretchyIcon';
      }
      // 4) Или на красный, если дата прошла и не выполнено
      else if (new Date(plan.day) < now && !plan.isWorkedOut) {
        preset = 'islands#redStretchyIcon';
      }
    }

    objectManager.objects.setObjectOptions(p.id, {preset});
  });

  // 1.3) Линии
  polylineCollection.removeAll();
  pts.forEach(p => {
    if (p.geojson) {
      const geo = typeof p.geojson === 'string' ? JSON.parse(p.geojson) : p.geojson;
      geo.features.forEach(f => {
        if (f.geometry.type === 'LineString') {
          polylineCollection.add(new ymaps.Polyline(f.geometry.coordinates));
        }
      });
    }
  });
}


function initMap() {
  ymaps.ready(async () => {
    window.myMap = new ymaps.Map('map', {
      center: [51.768199, 55.096955],
      zoom: 7,
      controls: ['zoomControl'],
      balloonMaxWidth: 300,      // максимальная ширина балуна
      balloonMinWidth: 200,      // минимальная ширина балуна
      balloonAutoPan: true,
    });
    // слой для линий
    polylineCollection = new ymaps.GeoObjectCollection(
        {}, // опции всего коллекции
        {strokeWidth: 2, strokeColor: '#FF0000', strokeOpacity: 1}
    );
    window.myMap.geoObjects.add(polylineCollection);
    // 1) Создаём ObjectManager и включаем кластеризацию
    objectManager = new ymaps.ObjectManager({
      clusterize: true,
      gridSize: 64,
    });

    // 2) Опционально задаём стиль кластеров
    objectManager.objects.options.set({
      preset: 'islands#greyStretchyIcon',         // базовый серый стиль
    });
    objectManager.clusters.options.set({
      preset: 'islands#orangeClusterIcons',
      // можно переопределять размер / цвет и т.д.
    });

    // 3) Добавляем все точки как один большой GeoJSON
    const features = allPoints.value.map(p => ({
      type: 'Feature',
      id: p.id,
      geometry: {
        type: 'Point',
        coordinates: [+p.latitude, +p.longitude],
      },
      properties: {
        hintContent: `${p.record_number} ${p.name}`,
        balloonContent: buildBalloonContent(p),
        pointData: p,
        iconContent: p.record_number
      }
    }));

    objectManager.add({type: 'FeatureCollection', features});

    window.myMap.geoObjects.add(objectManager);
    paintPoints(sortedPoints.value);
  });
}

watch(selectedDistrictId, newId => {
  // отключаем/включаем кластеризацию
  objectManager?.options.set('clusterize', newId == null);
  // и перезагружаем данные
  loadPoints(newId);
});

function redrawPoints() {
  if (!objectManager || !polylineCollection) return;
  // очистим старое
  objectManager.removeAll();
  polylineCollection.removeAll();

  // добавим новые точки
  const featureCollection = {
    type: 'FeatureCollection',
    features: allPoints.value.map(p => ({
      type: 'Feature',
      id: p.id,
      geometry: {type: 'Point', coordinates: [+p.latitude, +p.longitude]},
      properties: {
        hintContent: `${p.record_number} ${p.name}`,
        balloonContent: buildBalloonContent(p),
        iconContent: p.record_number,
      }
    }))
  };
  objectManager.add(featureCollection);

  // добавим линии (geojson есть только при фильтре по району)
  allPoints.value.forEach(p => {
    if (!p.geojson) return;
    const geo = typeof p.geojson === 'string'
        ? JSON.parse(p.geojson)
        : p.geojson;
    geo.features
        .filter(f => f.geometry?.type === 'LineString')
        .forEach(f => polylineCollection.add(
            new ymaps.Polyline(f.geometry.coordinates)
        ));
  });
  // применим подсветку
  paintPoints(sortedPoints.value);
}

async function loadPoints(districtId = null) {
  const {points, error} = await authStore.fetchPointsForMap(districtId);
  if (error) {
    console.error('Ошибка загрузки точек', error);
    return;
  }
  allPoints.value = points;
  if (districtId === null) {
    rawPoints.value = points;
  }
  redrawPoints();
}

onMounted(async () => {
  printStore.setPoints([]);       // сбрасываем подборку для печати
  await loadPoints();             // ① загружаем только «маркерные» данные
  initMap();                      // ② инициализируем карту

  const {response: usersResp, error: usersErr} = await authStore.getUsers();
  if (usersErr) {
    console.error('Не удалось получить список пользователей', usersErr);
  } else {
    // usersResp.data — это объект, где ключи = названия ролей, а значения — массивы users
    const byRole = usersResp.data;

    // если в вашем API есть ключ "Менеджер подгруппы":
    subgroupManagers.value = byRole['Менеджер подгруппы'] || [];

    // если есть ключ "Учетчик" – вот его:
    counters.value = byRole['Учетчик'] || [];

  }

  const {data: ctrData, error: ctrErr} = await authStore.getCounters();
  if (ctrErr) {
    console.error('Не удалось загрузить учётчиков', ctrErr);
  } else {
    counters.value = ctrData;
  }

  const {response: reqR, error} = await authStore.getRequests();

  if (reqR) {
    requestsList.value = reqR.data;
  } else {
    console.error(error);
  }
  document.body.addEventListener('click', e => {
    if (!e.target.classList.contains('assign-btn')) return
    const id = Number(e.target.dataset.id)
    const point = allPoints.value.find(p => p.id === id)
    if (point) openAssignModal(point)
  })

});

// при смене заявки подгружаем периоды
watch(
    () => selectedRequestId.value,
    async (newReq) => {
      if (!newReq) {
        signatures.value = [];
        return;
      }
      // вызываем метод из стора
      const {response, error} = await authStore.getSignedPeriods(newReq);
      if (error) {
        console.error('Не удалось загрузить подписанные месяцы:', error);
        signatures.value = [];
      } else {
        // вот здесь используем именно response.data.signed_periods
        signatures.value = response.data.signed_periods;
      }
    },
    {immediate: true}
);

function buildBalloonContent(p) {
  // Ищем план именно под текущий фильтр-заявку
  const plan = p.plans.find(pl =>
      Number(pl.request_id) === Number(selectedRequestId.value)
  );
  let html = `
    <strong>${p.record_number} ${p.name}</strong><br>
    ${p.district.name}, ${p.district.region.name}
  `;

  if (plan) {
    // Дата
    const [ymd] = plan.day.split('T');
    const start = toTimeStr(plan.timeStart);
    const end = toTimeStr(plan.timeEnd);
    html += `<div>📅 Дата: ${formatDate(ymd)}</div>`;
    // Время
    html += `<div>⏰ Время: ${start} – ${end}</div>`;
    // Менеджер подгруппы
    const mgr = subgroupManagers.value.find(u => u.id === plan.subgroup_manager_id);
    if (mgr) {
      html += `<div>👤 Менеджер: ${mgr.last_name} ${mgr.first_name}</div>`;
    }
    // Учётчик
    const ctr = counters.value?.find(c => c.id === plan.counter_id);
    if (ctr) {
      html += `<div>🔧 Учётчик: ${ctr.last_name} ${ctr.first_name} </div>`;
    }
  }

  // Кнопка назначения/редактирования
  if (canAssignWork.value && selectedRequestId.value) {
    const btnText = plan ? 'Редактировать' : 'Назначить';
    html += `
      <div class="mt-2">
        <button
          class="btn btn-primary btn-sm assign-btn"
          data-id="${p.id}"
        >${btnText}</button>
      </div>
    `;
  }

  return html;
}

watch(selectedRequestId, () => {
  // для каждого point в allPoints обновляем его balloonContent
  allPoints.value.forEach(p => {
    const newContent = buildBalloonContent(p);
    objectManager.objects.setObjectProperties(p.id, {
      balloonContent: newContent
    });
  });
});

const refreshPoints = async () => {
  const {response} = await authStore.getPointForMap();
  if (response) {
    allPoints.value = response.data.points;
    objectManager.removeAll();
    const features = allPoints.value.map(p => ({
      type: 'Feature',
      id: p.id,
      geometry: {type: 'Point', coordinates: [+p.latitude, +p.longitude]},
      properties: {
        balloonContent: buildBalloonContent(p),
        pointData: p,
      }
    }));
    objectManager.add({type: 'FeatureCollection', features});
  }
};
watch(sortedPoints, pts => {
  paintPoints(pts);
}, {immediate: true});


</script>

<template>
  <div class="container-fluid mx-auto my-4">
    <div class="row">
      <h4>Карта</h4>

      <div class="row g-3 mb-3 align-items-end">
        <div class="col-6 col-md-2">
          <select class="form-select" v-model="selectedDistrictId">
            <option :value="null">Все районы</option>
            <option v-for="district in districtOptions" :key="district.id" :value="district.id">
              {{ district.name }}
            </option>
          </select>
        </div>
        <div class="col-6 col-md-2">
          <select class="form-select" v-model="selectedCategory">
            <option :value="null">Все категории</option>
            <option v-for="cat in uniqueCategories" :key="cat" :value="cat">
              {{ cat }}
            </option>
          </select>
        </div>
        <div class="col-6 col-md-2">
          <select class="form-select" v-model="selectedFrequency">
            <option :value="null">Все частоты</option>
            <option :value="1">Ежемесячно</option>
            <option :value="2">Ежеквартально</option>
          </select>
        </div>

        <!-- Фильтр по менеджеру подгруппы -->
        <div class="col-6 col-md-2">
          <select v-model="selectedManagerId" class="form-select">
            <option :value="null">Все менеджеры подгруппы</option>
            <option
                v-for="mgr in subgroupManagers"
                :key="mgr.id"
                :value="mgr.id"
            >
              {{ mgr.last_name }} {{ mgr.first_name }}
            </option>
          </select>
        </div>

        <!-- Фильтр по дате работ -->
        <div class="col-6 col-md-2 position-relative">
          <Flatpickr
              v-model="selectedDate"
              :config="fpConfig"
              class="form-control pe-5"
              placeholder="Дата"
          />
          <!-- Кнопка сброса в углу поля -->
          <button
              type="button"
              class="btn btn-sm btn-outline-secondary position-absolute top-50 end-0 translate-middle-y me-2"
              @click="selectedDate = null"
              v-if="selectedDate"
              title="Сбросить дату"
          >
            &times;
          </button>
        </div>

        <div class="col-6 col-md-2">
          <select class="form-select" v-model="selectedRequestId">
            <option :value="null">Все заявки</option>
            <option v-for="r in requestsList" :key="r.id" :value="r.id">{{ r.name }}</option>
          </select>
        </div>

        <!-- эта колонка видна только на md+ -->
        <div class="col-12 col-md-auto ms-auto d-none d-md-block">
          <button class="btn btn-primary w-100" @click="saveMapToPDF">
            Сохранить в PDF
          </button>
        </div>
      </div>

      <p class="mb-2 text-muted">
        Отображается ПУИДД: <strong>{{ visiblePointsCount }}</strong>
        <span v-if="selectedRequestId">
          &nbsp;|&nbsp;Запланировано работ: {{ scheduledCount }}
        </span>
      </p>
      <div id="map" style="width: 100%; height: 80vh; background-color: #eee; border: 1px solid #ccc"></div>
    </div>
    <Teleport to="body">
      <div v-if="showModal" class="modal-backdrop">
        <div class="modal-content">
          <h5>Назначить работы на: {{ selectedPoint?.name }}</h5>

          <div class="mb-2">
            <label>Дата:</label>
            <Flatpickr v-model="form.day" :config="fpConfig" class="form-control"/>
          </div>

          <div class="mb-2">
            <label>Период:</label>
            <br/>
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="radio" id="summer" value="summer" v-model="period"/>
              <label class="form-check-label" for="summer">Летний</label>
            </div>
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="radio" id="winter" value="winter" v-model="period"/>
              <label class="form-check-label" for="winter">Зимний</label>
            </div>
          </div>

          <div class="mb-2">
            <label>Время начала:</label>
            <select v-model="form.timeStart" @change="updateEndTime" class="form-control">
              <option disabled value="">Выберите время</option>
              <option v-for="time in timeOptions" :key="time" :value="time">{{ time }}</option>
            </select>
          </div>

          <div class="mb-2">
            <label>Время окончания:</label>
            <input v-model="form.timeEnd" type="time" class="form-control" disabled/>
          </div>

          <!-- Селект «Ответственный (менеджер подгруппы)» -->
          <div class="mb-2">
            <label>Ответственный (менеджер подгруппы):</label>
            <select
                v-model="form.subgroup_manager_id"
                class="form-control"
                :disabled="isSubgroupManagerRole"
            >
              <option disabled value="">Выберите менеджера</option>
              <option
                  v-for="u in subgroupManagers"
                  :key="u.id"
                  :value="u.id"
              >
                {{ u.last_name }} {{ u.first_name }} {{ u.middle_name }}
              </option>
            </select>
            <!-- Пояснение, что роль «Менеджер подгруппы» не может поменять ответственного -->
            <small class="text-muted" v-if="isSubgroupManagerRole">
              (Нельзя менять ― текущий пользователь уже выбран)
            </small>
          </div>

          <div class="mb-2">
            <label>Исполнитель (учётчик):</label>
            <select v-model="form.counter_id" class="form-control">
              <option :value="null">Выберите учётчика</option>
              <option v-for="c in counters" :key="c.id" :value="c.id">
                {{ c.last_name }} {{ c.first_name }} {{ c.middle_name }}
              </option>
            </select>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-secondary" @click="showModal = false">Отмена</button>
            <button class="btn btn-primary" @click="saveAssignment" :disabled="isSaving"><span v-if="isSaving"
                                                                                               class="spinner-border spinner-border-sm me-2"></span>Сохранить
            </button>
          </div>
          <div v-if="formError" class="text-danger mb-2">
            {{ formError }}
          </div>
        </div>
      </div>
    </Teleport>
  </div>
</template>

<style scoped>
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 10px;
  width: 400px;
}

@media print {
  body * {
    display: none !important;
  }

  body.print-mode #map-container,
  body.print-mode #map-container * {
    display: block !important;
    visibility: visible !important;
  }

  body.print-mode .print-heading {
    display: block !important;
  }

  body.print-mode #map-container {
    position: absolute;
    top: 20mm;
    left: 10mm;
    width: 277mm;
    height: 180mm;
  }
}
</style>
