// Тестовые данные планов КА. Детерминированная генерация (seeded RNG),
// чтобы при перезагрузке данные были стабильны.
(function () {
  function mulberry32(a) {
    return function () {
      a |= 0; a = (a + 0x6D2B79F5) | 0;
      let t = Math.imul(a ^ (a >>> 15), 1 | a);
      t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
      return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
    };
  }
  const rnd = mulberry32(20260529);
  const pick = (arr) => arr[Math.floor(rnd() * arr.length)];
  const randint = (a, b) => a + Math.floor(rnd() * (b - a + 1));

  const HOUR = 3600 * 1000;
  const DAY = 24 * HOUR;
  // "Сейчас" — фиксируем под текущую дату проекта.
  const NOW = new Date("2026-05-29T11:20:00Z").getTime();

  // Три типа по аппаратуре (все аппараты — ДЗЗ).
  const TYPES = {
    optical: { id: "optical", label: "Оптическая", short: "ОПТ" },
    radar: { id: "radar", label: "Радиолокационная", short: "РЛ" },
    combo: { id: "combo", label: "Комбинированная", short: "ОПТ+РЛ" },
  };

  // Программы/созвездия (название группы). Каждая группа тяготеет к своим типам.
  const GROUP_DEFS = [
    { id: "resurs", name: "Ресурс-ОП", code: "RSO", weights: { optical: 0.8, radar: 0.05, combo: 0.15 } },
    { id: "kanopus", name: "Канопус-В", code: "KNP", weights: { optical: 0.7, radar: 0.1, combo: 0.2 } },
    { id: "kondor", name: "Кондор-ФКА", code: "KND", weights: { optical: 0.05, radar: 0.85, combo: 0.1 } },
    { id: "obzor", name: "Обзор-Р", code: "OBZ", weights: { optical: 0.05, radar: 0.8, combo: 0.15 } },
    { id: "meteor", name: "Метеор-М", code: "MTR", weights: { optical: 0.55, radar: 0.15, combo: 0.3 } },
    { id: "aist", name: "Аист-2", code: "AST", weights: { optical: 0.6, radar: 0.1, combo: 0.3 } },
    { id: "smotr", name: "Смотр-Р", code: "SMT", weights: { optical: 0.1, radar: 0.55, combo: 0.35 } },
  ];

  function weightedType(weights) {
    const r = rnd();
    let acc = 0;
    for (const k of Object.keys(weights)) {
      acc += weights[k];
      if (r <= acc) return k;
    }
    return "optical";
  }

  // Виды РАБОТ внутри плана. У каждой работы — своя категория (kind).
  const WORK_KINDS = {
    shoot: { id: "shoot", label: "Съёмка" },
    downlink: { id: "downlink", label: "Сброс на НКПОР" },
    calib: { id: "calib", label: "Калибровка" },
    service: { id: "service", label: "Служебная операция" },
  };
  const WORK_KIND_ORDER = ["shoot", "downlink", "calib", "service"];
  // Подпись работы-съёмки зависит от аппаратуры КА.
  const SHOOT_LABEL = {
    optical: ["Панхром. съёмка", "Мультиспектр. съёмка", "Стереосъёмка", "Площадная съёмка"],
    radar: ["РСА съёмка", "Интерферометрия", "Прожекторный режим", "Сканирующий режим"],
    combo: ["Совмещ. съёмка", "РСА + панхром.", "Площадная съёмка", "Мониторинг ЧС"],
  };
  // Названия самих ПЛАНОВ (объемлющих интервалов).
  const PLAN_NAMES = ["Суточная программа", "Целевая программа", "Спецзадание", "Программа мониторинга", "Сеансовый план", "Программа ДЗЗ"];

  function genWorks(planStart, planEnd, scType, makeId) {
    const works = [];
    const span = planEnd - planStart;
    // Плотность работ ~ 1 на 4–9 часов плана.
    let cursor = planStart + randint(0, 2) * HOUR;
    let guard = 0;
    while (cursor < planEnd - 1 * HOUR && guard < 40) {
      guard++;
      const kind = pick(WORK_KIND_ORDER);
      let dur;
      if (kind === "shoot") dur = randint(20, 140) * 60 * 1000;        // 20м–2.3ч
      else if (kind === "downlink") dur = randint(8, 35) * 60 * 1000;  // сброс
      else if (kind === "calib") dur = randint(30, 90) * 60 * 1000;
      else dur = randint(10, 40) * 60 * 1000;                          // служебная
      const wStart = cursor;
      const wEnd = Math.min(planEnd, wStart + dur);
      if (wEnd <= wStart) break;
      const label = kind === "shoot" ? pick(SHOOT_LABEL[scType]) : WORK_KINDS[kind].label;
      works.push({ id: makeId(), kind, label, start: wStart, end: wEnd });
      // пауза между работами
      cursor = wEnd + randint(20, 180) * 60 * 1000;
    }
    return works;
  }

  // Генерация КА.
  const spacecraft = [];
  let scCounter = 0;
  for (const g of GROUP_DEFS) {
    const count = randint(8, 16); // суммарно ~80
    for (let i = 0; i < count; i++) {
      const type = weightedType(g.weights);
      scCounter++;
      const num = i + 1;
      spacecraft.push({
        id: `${g.id}-${num}`,
        name: `${g.name} №${num}`,
        short: `${g.code}-${String(num).padStart(2, "0")}`,
        groupId: g.id,
        type,
        orbit: pick(["ССО 510 км", "ССО 575 км", "ССО 700 км", "ССО 480 км"]),
      });
    }
  }

  // Видимый горизонт планирования: ~ -16 сут .. +30 сут от "сейчас".
  const RANGE_START = NOW - 16 * DAY;
  const RANGE_END = NOW + 30 * DAY;

  function statusFor(start, end) {
    if (end < NOW) return "executed";
    if (start <= NOW && NOW <= end) return "active";
    return "planned";
  }

  // Генерация ПЛАНОВ (объемлющих интервалов) с родословной (ревизии плана = потомки).
  // Каждый план содержит набор РАБОТ внутри своего интервала.
  const plans = [];
  let ivCounter = 0;
  let workCounter = 0;
  const makeWorkId = () => `W-${String(++workCounter).padStart(5, "0")}`;
  for (const sc of spacecraft) {
    // стартовая точка цепочки
    let cursor = RANGE_START + randint(0, 3) * DAY + randint(0, 20) * HOUR;
    let prevId = null;
    const nChains = randint(2, 4);
    for (let c = 0; c < nChains; c++) {
      // базовый план в цепочке
      const dur = randint(8, 60) * HOUR;
      const start = cursor;
      const end = start + dur;
      ivCounter++;
      const baseId = `PL-${String(ivCounter).padStart(4, "0")}`;
      const planName = pick(PLAN_NAMES);
      plans.push({
        id: baseId,
        scId: sc.id,
        start, end,
        title: planName,
        rev: 1,
        parentId: prevId,
        status: statusFor(start, end),
        author: pick(["ЦУП-1", "ЦУП-2", "ПЦ Москва", "ПЦ Дубна", "Авто-планировщик"]),
        works: genWorks(start, end, sc.type, makeWorkId),
      });
      prevId = baseId;

      // c вероятностью — ревизия, перекрывающая базовый план (создаёт пересечение)
      if (rnd() < 0.45) {
        const overlapStart = start + Math.floor(dur * (0.35 + rnd() * 0.4));
        const revDur = randint(10, 50) * HOUR;
        const revEnd = overlapStart + revDur;
        ivCounter++;
        const revId = `PL-${String(ivCounter).padStart(4, "0")}`;
        plans.push({
          id: revId,
          scId: sc.id,
          start: overlapStart,
          end: revEnd,
          title: planName,
          rev: 2,
          parentId: baseId,
          status: statusFor(overlapStart, revEnd),
          author: pick(["ЦУП-1", "ЦУП-2", "ПЦ Москва", "Авто-планировщик"]),
          works: genWorks(overlapStart, revEnd, sc.type, makeWorkId),
        });
        prevId = revId;
        cursor = revEnd + randint(4, 36) * HOUR;
      } else {
        cursor = end + randint(6, 48) * HOUR;
      }
      if (cursor > RANGE_END) break;
    }
  }

  // Индексы родословной: дети по родителю.
  const childrenOf = {};
  for (const iv of plans) {
    if (iv.parentId) {
      (childrenOf[iv.parentId] = childrenOf[iv.parentId] || []).push(iv.id);
    }
  }

  window.MissionData = {
    HOUR, DAY, NOW, RANGE_START, RANGE_END,
    TYPES, GROUP_DEFS, WORK_KINDS, WORK_KIND_ORDER,
    spacecraft, plans, childrenOf,
    typeOrder: ["optical", "radar", "combo"],
  };
})();
