// Partitura — standalone data.
// Day "вчера" 2026-05-17, 08:00 → now (14:35). All times are minutes-since-midnight.

const PT_DAY = "2026-05-17";
const PT_NOW_MIN = 14 * 60 + 35; // 14:35

// Helpers
const HM = (h, m = 0) => h * 60 + m;
const fmtHM = (mins) => {
  const h = Math.floor(mins / 60) % 24;
  const m = Math.floor(mins) % 60;
  return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
};
const fmtHMS = (mins) => {
  const total = mins * 60;
  const h = Math.floor(total / 3600) % 24;
  const m = Math.floor((total % 3600) / 60);
  const s = Math.floor(total % 60);
  return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
};

// Agents — reuse the TEAM constant from data.jsx (already on window)
// Each agent's day broken into SEQUENTIAL segments. No overlap.
// segment = { start, end, state: "in-progress"|"blocked"|"review"|"testing"|"research"|"planning",
//             seq, title, module }

const PT_AGENT_SEGMENTS = {
  lev: [
    { start: HM(8,15),  end: HM(9, 0),  state: "planning",    seq: 51, title: "Описать модуль уведомлений в KALK",     module: "kalk" },
    { start: HM(9, 0),  end: HM(10,30), state: "planning",    seq: 52, title: "ТЗ на интеграцию с 1С",                  module: "integrations" },
    { start: HM(10,30), end: HM(10,45), state: "blocked",     seq: 52, title: "ТЗ на интеграцию с 1С (жду Максима)",   module: "integrations" },
    { start: HM(10,45), end: HM(11,30), state: "planning",    seq: 52, title: "ТЗ на интеграцию с 1С",                  module: "integrations" },
    { start: HM(11,30), end: HM(12, 0), state: "planning",    seq: 53, title: "Декомпозиция эпика «Личный кабинет»",   module: "auth" },
    { start: HM(12,30), end: HM(13,45), state: "planning",    seq: 54, title: "Review архитектуры миграции БД",        module: "migrations" },
    { start: HM(13,45), end: PT_NOW_MIN,state: "planning",    seq: 55, title: "Постановка PB-56..58 (KALK v2)",        module: "kalk" },
  ],
  kostya: [
    { start: HM(8,20),  end: HM(10, 0), state: "in-progress", seq: 47, title: "Аналитика заказов: фильтр по статусу", module: "orders" },
    { start: HM(10, 0), end: HM(10,15), state: "blocked",     seq: 47, title: "Аналитика заказов (жду Лёва)",          module: "orders" },
    { start: HM(10,15), end: HM(11,45), state: "in-progress", seq: 47, title: "Аналитика заказов: фильтр по статусу", module: "orders" },
    { start: HM(12,30), end: HM(14, 0), state: "in-progress", seq: 49, title: "Ребрендинг Print-X в коде сайта",        module: "seo" },
    { start: HM(14, 0), end: HM(14,15), state: "blocked",     seq: 49, title: "Ребрендинг Print-X (конфликт стилей)",  module: "seo" },
    { start: HM(14,15), end: PT_NOW_MIN,state: "in-progress", seq: 49, title: "Ребрендинг Print-X в коде сайта",        module: "seo" },
  ],
  roma: [
    { start: HM(9,30),  end: HM(10, 0), state: "review",      seq: 46, title: "Review: миграция БД на v3",              module: "migrations" },
    { start: HM(10, 0), end: HM(10,30), state: "review",      seq: 48, title: "Review: SEO meta-теги",                   module: "seo" },
    { start: HM(11, 0), end: HM(11,45), state: "review",      seq: 45, title: "Review: Onboarding wizard",               module: "kalk" },
    { start: HM(12, 0), end: HM(12,45), state: "review",      seq: 47, title: "Review: фильтр аналитики заказов",        module: "orders" },
    { start: HM(13,30), end: HM(14,10), state: "review",      seq: 50, title: "Review: каталог А4-референсов",           module: "seo" },
  ],
  timur: [
    { start: HM(9, 0),  end: HM(10,30), state: "testing",     seq: 44, title: "E2E: Telegram-бот подсчёт стоимости",     module: "tg-bot" },
    { start: HM(11, 0), end: HM(12,15), state: "testing",     seq: 45, title: "E2E: Onboarding wizard",                  module: "kalk" },
    { start: HM(13, 0), end: PT_NOW_MIN,state: "testing",     seq: 47, title: "E2E: фильтр аналитики заказов",            module: "orders" },
  ],
  semyon: [
    { start: HM(8,30),  end: HM(11, 0), state: "research",    seq: 50, title: "Подобрать референсы для каталога A4",     module: "seo" },
    { start: HM(11, 0), end: HM(11,30), state: "blocked",     seq: 50, title: "Подобрать референсы (rate-limit Pinterest)", module: "seo" },
    { start: HM(11,30), end: HM(13,48), state: "research",    seq: 50, title: "Подобрать референсы для каталога A4",     module: "seo" },
    // 13:48 — watcher offline (no segments after)
  ],
  viktor: [
    { start: HM(9,15),  end: HM(9,45),  state: "planning",    seq: 46, title: "Разбор алерта по PB-46",                  module: "watchdog" },
    { start: HM(10,30), end: HM(11, 0), state: "planning",    seq: 48, title: "Разбор алерта по PB-48",                  module: "watchdog" },
    { start: HM(12,30), end: HM(13,30), state: "planning",    seq: 52, title: "Сверка с архитектурой",                   module: "integrations" },
    { start: HM(13,50), end: PT_NOW_MIN,state: "planning",    seq: 55, title: "Разбор алертов за смену",                 module: "watchdog" },
  ],
};

// Events — one stream, classified by kind. Plotted on the agent's track.
// kinds: new_task, state_change, assigned, label, comment, commit, alert
const PT_EVENTS = [
  // Lev events
  { t: HM(8,15),  agent: "lev",    kind: "new_task",    seq: 51, text: "создал PB-51 «Описать модуль уведомлений в KALK»" },
  { t: HM(8,17),  agent: "lev",    kind: "label",       seq: 51, text: "ставит лейбл for-architect" },
  { t: HM(8,52),  agent: "lev",    kind: "comment",     seq: 51, text: "первый драфт ТЗ готов" },
  { t: HM(9, 2),  agent: "lev",    kind: "new_task",    seq: 52, text: "создал PB-52 «ТЗ на интеграцию с 1С»" },
  { t: HM(10,30), agent: "lev",    kind: "state_change",seq: 52, text: "PB-52 Todo → Blocked (жду ответа Максима)" },
  { t: HM(10,45), agent: "lev",    kind: "state_change",seq: 52, text: "PB-52 Blocked → In Progress" },
  { t: HM(11,20), agent: "lev",    kind: "comment",     seq: 52, text: "схема интеграции 1С v2, на review" },
  { t: HM(11,30), agent: "lev",    kind: "new_task",    seq: 53, text: "создал PB-53 «Эпик: Личный кабинет»" },
  { t: HM(13,12), agent: "lev",    kind: "comment",     seq: 54, text: "архитектура миграции одобрена" },
  { t: HM(13,45), agent: "lev",    kind: "new_task",    seq: 55, text: "создал PB-55 «KALK v2 — постановка»" },
  { t: HM(14,18), agent: "lev",    kind: "label",       seq: 56, text: "ставит for-coder на PB-56" },

  // Kostya events
  { t: HM(8,20),  agent: "kostya", kind: "assigned",    seq: 47, text: "взял PB-47 в работу" },
  { t: HM(8,21),  agent: "kostya", kind: "state_change",seq: 47, text: "PB-47 Todo → In Progress" },
  { t: HM(8,52),  agent: "kostya", kind: "commit",      seq: 47, text: "feat(orders): фильтр-чипы (черновик)" },
  { t: HM(9,38),  agent: "kostya", kind: "commit",      seq: 47, text: "wip: useFilterStore" },
  { t: HM(10, 0), agent: "kostya", kind: "state_change",seq: 47, text: "PB-47 In Progress → Blocked" },
  { t: HM(10, 1), agent: "kostya", kind: "comment",     seq: 47, text: "@lev уточни schema для FilterState" },
  { t: HM(10,15), agent: "kostya", kind: "state_change",seq: 47, text: "PB-47 Blocked → In Progress" },
  { t: HM(10,42), agent: "kostya", kind: "commit",      seq: 47, text: "feat: filter state shape per @lev" },
  { t: HM(11,30), agent: "kostya", kind: "commit",      seq: 47, text: "tests: фильтрация по статусам" },
  { t: HM(11,45), agent: "kostya", kind: "label",       seq: 47, text: "ставит for-reviewer" },
  { t: HM(11,45), agent: "kostya", kind: "state_change",seq: 47, text: "PB-47 In Progress → Review" },
  { t: HM(12,30), agent: "kostya", kind: "assigned",    seq: 49, text: "взял PB-49 в работу" },
  { t: HM(12,33), agent: "kostya", kind: "commit",      seq: 49, text: "chore: grep Print-X across repo" },
  { t: HM(13,18), agent: "kostya", kind: "comment",     seq: 49, text: "progress: правлю Footer.tsx, осталось header" },
  { t: HM(13,42), agent: "kostya", kind: "commit",      seq: 49, text: "fix(seo): заменил title-теги" },
  { t: HM(14, 0), agent: "kostya", kind: "state_change",seq: 49, text: "PB-49 In Progress → Blocked" },
  { t: HM(14, 8), agent: "kostya", kind: "alert", sev: "warning", seq: 49, ruleName: "stuck_blocked_15min",
    text: "правило сработало: задача висит в Blocked > 15 мин" },
  { t: HM(14,15), agent: "kostya", kind: "state_change",seq: 49, text: "PB-49 Blocked → In Progress" },

  // Roma events
  { t: HM(9,28),  agent: "roma",   kind: "assigned",    seq: 46, text: "взял PB-46 на ревью" },
  { t: HM(9,55),  agent: "roma",   kind: "comment",     seq: 46, text: "approved — переименуй migrate_v3.py → migrations/003_v3.py" },
  { t: HM(9,57),  agent: "roma",   kind: "state_change",seq: 46, text: "PB-46 Review → Done" },
  { t: HM(10, 0), agent: "roma",   kind: "assigned",    seq: 48, text: "взял PB-48 на ревью" },
  { t: HM(10,28), agent: "roma",   kind: "state_change",seq: 48, text: "PB-48 Review → Done" },
  { t: HM(11, 0), agent: "roma",   kind: "assigned",    seq: 45, text: "взял PB-45 на ревью" },
  { t: HM(11,32), agent: "roma",   kind: "comment",     seq: 45, text: "LGTM, переименуй handleSubmit2" },
  { t: HM(11,44), agent: "roma",   kind: "state_change",seq: 45, text: "PB-45 Review → Done" },
  { t: HM(12, 0), agent: "roma",   kind: "assigned",    seq: 47, text: "взял PB-47 на ревью" },
  { t: HM(12,42), agent: "roma",   kind: "comment",     seq: 47, text: "approved" },
  { t: HM(12,44), agent: "roma",   kind: "state_change",seq: 47, text: "PB-47 Review → Done" },
  { t: HM(13,30), agent: "roma",   kind: "assigned",    seq: 50, text: "взял PB-50 на ревью" },
  { t: HM(14, 8), agent: "roma",   kind: "state_change",seq: 50, text: "PB-50 Review → Done" },

  // Timur events
  { t: HM(9, 0),  agent: "timur",  kind: "assigned",    seq: 44, text: "тестирует PB-44" },
  { t: HM(9,18),  agent: "timur",  kind: "comment",     seq: 44, text: "happy-path ок" },
  { t: HM(10,12), agent: "timur",  kind: "comment",     seq: 44, text: "edge: пустая корзина — падает" },
  { t: HM(10,28), agent: "timur",  kind: "label",       seq: 44, text: "ставит tested" },
  { t: HM(11,10), agent: "timur",  kind: "comment",     seq: 45, text: "happy-path ок" },
  { t: HM(12,13), agent: "timur",  kind: "label",       seq: 45, text: "ставит tested" },
  { t: HM(13,22), agent: "timur",  kind: "comment",     seq: 47, text: "playwright spec написан" },

  // Semyon events
  { t: HM(8,30),  agent: "semyon", kind: "assigned",    seq: 50, text: "начал PB-50 — поиск референсов" },
  { t: HM(9,18),  agent: "semyon", kind: "comment",     seq: 50, text: "10 ссылок на printio собрал" },
  { t: HM(10,40), agent: "semyon", kind: "comment",     seq: 50, text: "ещё 6 ссылок c Behance" },
  { t: HM(11, 0), agent: "semyon", kind: "state_change",seq: 50, text: "PB-50 In Progress → Blocked" },
  { t: HM(11, 2), agent: "semyon", kind: "comment",     seq: 50, text: "Pinterest 429 rate-limit, жду 30 мин" },
  { t: HM(11,30), agent: "semyon", kind: "state_change",seq: 50, text: "PB-50 Blocked → In Progress" },
  { t: HM(12,15), agent: "semyon", kind: "comment",     seq: 50, text: "перешёл к Pinterest, 8 досок" },
  { t: HM(13,30), agent: "semyon", kind: "comment",     seq: 50, text: "сборка отчёта" },
  { t: HM(13,48), agent: "semyon", kind: "alert", sev: "critical", seq: 50, ruleName: "watcher_heartbeat_missing",
    text: "правило сработало: watcher Семёна молчит > 5 мин" },

  // Viktor events
  { t: HM(9,15),  agent: "viktor", kind: "assigned",    seq: 46, text: "разбирает алерт по PB-46" },
  { t: HM(9,44),  agent: "viktor", kind: "comment",     seq: 46, text: "выяснил: Рома уложился, false-positive" },
  { t: HM(10,30), agent: "viktor", kind: "assigned",    seq: 48, text: "разбирает алерт по PB-48" },
  { t: HM(12,30), agent: "viktor", kind: "comment",     seq: 52, text: "согласовал с Лёвом схему 1С" },
  { t: HM(13,15), agent: "viktor", kind: "alert", sev: "info", seq: 46, ruleName: "reviewer_pickup_within_1h",
    text: "правило сработало: info — на грани SLA" },
  { t: HM(14, 5), agent: "viktor", kind: "comment",     seq: 55, text: "разбираю warning по Косте" },
];

// Modules — derive set from segments
function ptModulesList() {
  const s = new Set();
  Object.values(PT_AGENT_SEGMENTS).forEach((segs) => segs.forEach((sg) => s.add(sg.module)));
  return Array.from(s);
}

// Watcher offline windows (for grey "offline" zones)
const PT_OFFLINE = {
  semyon: [{ start: HM(13, 48), end: PT_NOW_MIN }],
};

// Module color palette
const MODULE_COLORS = {
  orders:       "#a78bfa",
  kalk:         "#ec4899",
  "tg-bot":     "#60a5fa",
  seo:          "#34d399",
  auth:         "#fb923c",
  watchdog:     "#f472b6",
  integrations: "#22d3ee",
  migrations:   "#facc15",
  notifications:"#f59e0b",
  spec:         "#a3e635",
  docs:         "#94a3b8",
  scaffold:     "#cbd5e1",
};
function moduleColor(m) { return MODULE_COLORS[m] || "#a1a1aa"; }

// State / segment styling — driven by CSS variables so themes can override.
const STATE_STYLES = {
  "in-progress": { label: "В работе",       color: "var(--st-coding-color)",   bg: "var(--st-coding-bg)",   border: "var(--st-coding-border)" },
  "review":      { label: "Ревью",          color: "var(--st-review-color)",   bg: "var(--st-review-bg)",   border: "var(--st-review-border)" },
  "testing":     { label: "Тестинг",        color: "var(--st-testing-color)",  bg: "var(--st-testing-bg)",  border: "var(--st-testing-border)" },
  "research":    { label: "Разведка",       color: "var(--st-research-color)", bg: "var(--st-research-bg)", border: "var(--st-research-border)" },
  "planning":    { label: "Постановка",     color: "var(--st-planning-color)", bg: "var(--st-planning-bg)", border: "var(--st-planning-border)" },
  "blocked":     { label: "Заблокировано",  color: "var(--st-blocked-color)",  bg: "transparent",            border: "var(--st-blocked-border)", hatch: true },
};

// ---------------------------------------------------------------------------
// History / aggregates (used by period views: week/month/year)
// ---------------------------------------------------------------------------
function _hash(s) { let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0; return Math.abs(h); }
function _rng(seed) { return () => { seed = (seed * 9301 + 49297) % 233280; return seed / 233280; }; }

// Generate synthetic per-day history for an agent over the last N days.
// Returns array indexed by daysAgo (0 = today, N-1 = oldest), each entry has minutes per state.
function genHistory(agentId, days) {
  const r = _rng(_hash(agentId));
  const out = [];
  const states = ["planning", "in-progress", "review", "testing", "research", "blocked"];
  // Today is partial — use today's actual segments to seed the first entry where possible
  const todaySegs = PT_AGENT_SEGMENTS[agentId] || [];
  const todayByState = {};
  todaySegs.forEach(s => { todayByState[s.state] = (todayByState[s.state] || 0) + (s.end - s.start); });

  for (let d = 0; d < days; d++) {
    let entry;
    if (d === 0) {
      // today's actual breakdown
      entry = { ...todayByState };
    } else {
      // synthetic but with agent-stable shape — pick a "profile" by role weights
      const a = (window.teamById || (() => null))(agentId);
      const role = a?.role || "coder";
      entry = {};
      const intensity = 0.55 + 0.45 * r();
      const isWeekend = ((new Date().getDay() - d + 7) % 7) >= 5;
      const mult = isWeekend ? 0.25 + r() * 0.3 : intensity;
      if (role === "architect" || role === "workflow-lead") {
        entry.planning = Math.round((180 + r() * 240) * mult);
        entry["in-progress"] = Math.round((30 + r() * 60) * mult);
      } else if (role === "reviewer") {
        entry.review = Math.round((120 + r() * 180) * mult);
        entry.planning = Math.round((20 + r() * 40) * mult);
      } else if (role === "tester") {
        entry.testing = Math.round((180 + r() * 200) * mult);
      } else if (role === "scout") {
        entry.research = Math.round((140 + r() * 220) * mult);
      } else {
        entry["in-progress"] = Math.round((240 + r() * 240) * mult);
        entry.review = Math.round((20 + r() * 30) * mult);
      }
      if (r() > 0.75) entry.blocked = Math.round(r() * 45);
    }
    let total = 0;
    states.forEach(s => { total += entry[s] || 0; });
    entry.total = total;
    out.push(entry);
  }
  return out;
}

// Aggregate one history array over a period (e.g. 7 → week summary, 30 → month).
function aggregateHistory(history) {
  const acc = { planning: 0, "in-progress": 0, review: 0, testing: 0, research: 0, blocked: 0, total: 0 };
  history.forEach(h => {
    Object.keys(acc).forEach(k => { acc[k] += h[k] || 0; });
  });
  return acc;
}

// Group history into N-day buckets (e.g. for year mode, group 365 days into 52 weeks).
function bucketHistory(history, bucketSize) {
  const buckets = [];
  for (let i = 0; i < history.length; i += bucketSize) {
    const slice = history.slice(i, i + bucketSize);
    buckets.push(aggregateHistory(slice));
  }
  return buckets;
}

// Synthetic per-day event counts (alerts, total events) per agent.
function genEventCounts(agentId, days) {
  const r = _rng(_hash(agentId + "_events"));
  return Array.from({ length: days }, () => ({
    events: Math.round(40 + r() * 80),
    alerts: r() > 0.85 ? Math.round(1 + r() * 2) : 0,
  }));
}

// Period descriptors
const PERIODS = [
  { id: "day",   label: "День",   days: 1   },
  { id: "week",  label: "Неделя", days: 7   },
  { id: "month", label: "Месяц",  days: 30  },
  { id: "year",  label: "Год",    days: 365, bucket: 7 }, // bucketed to weeks
];
function periodDef(id) { return PERIODS.find(p => p.id === id) || PERIODS[0]; }

Object.assign(window, {
  PT_DAY, PT_NOW_MIN, HM, fmtHM, fmtHMS,
  PT_AGENT_SEGMENTS, PT_EVENTS, PT_OFFLINE,
  ptModulesList, MODULE_COLORS, moduleColor, STATE_STYLES,
  genHistory, aggregateHistory, bucketHistory, genEventCounts,
  PERIODS, periodDef,
});
