// Luna · 数据层 —— June 2026 整月计划（唯一真相源，三视图都读它）
// 月初一次排好，月/周/日只是同一份计划的三个缩放层级。

// —— 类别 → 配色（§9）——
const CATS = {
  content: { id: 'content', name: '内容', color: '#6FCBB2' },
  care:    { id: 'care',    name: '护理', color: '#FF9EC4' },
  sport:   { id: 'sport',   name: '运动', color: '#FFB877' },
  event:   { id: 'event',   name: '活动', color: '#A98EE8' },
  errand:  { id: 'errand',  name: '跑腿', color: '#6FB4FF' },
  runway:  { id: 'runway',  name: '台步', color: '#56B6E6' },
  life:    { id: 'life',    name: '生活', color: '#F4C24E' },
};

// —— 频道日（给一天定性，降 switch cost）——
const CHANNELS = {
  focus:    { id: 'focus',    name: '深度',  sub: '写作沉浸', tint: '#CDEBE0', glow: '#6FCBB2' },
  convert:  { id: 'convert',  name: '转化',  sub: '出图发布', tint: '#D6E8FF', glow: '#6FB4FF' },
  outside:  { id: 'outside',  name: '外出',  sub: '出门攒一起', tint: '#E7DFFB', glow: '#A98EE8' },
  overflow: { id: 'overflow', name: '溢出',  sub: '收尾补漏', tint: '#FDEFCB', glow: '#F4C24E' },
  recovery: { id: 'recovery', name: '恢复',  sub: '留白慢下来', tint: '#FAE3EF', glow: '#FF9EC4' },
};

// —— 主线 threads（本月 2–4 条主轴）——
const THREADS = {
  T1: { id: 'T1', name: '内容双线推进', color: '#6FCBB2' },
  T2: { id: 'T2', name: '个人护理落地', color: '#FF9EC4' },
  T3: { id: 'T3', name: '立住生活节奏', color: '#F4C24E' },
};

// June 2026：1号=周一，5号=周五=今天
const TODAY = 5;
const NOW_MIN = 15 * 60 + 20; // 15:20 当下时间（分钟）
const WEEKDAYS = ['一', '二', '三', '四', '五', '六', '日'];

// 每天默认频道（按 dow，少量覆盖做出节奏变化）
function channelFor(d, dow) {
  // dow: 0=周一 … 6=周日
  const base = ['focus', 'focus', 'convert', 'outside', 'focus', 'outside', 'recovery'][dow];
  const override = {
    2: 'overflow',   // 周二补一次溢出
    13: 'recovery',  // 多给一个恢复
    20: 'overflow',
    27: 'recovery',
  };
  return override[d] || base;
}

// 低频愿望/护理按周撒入（§4.1 wishlist 被推进）
const SEEDED = {
  4:  [{ t: '医美面诊', cat: 'care' }],
  8:  [{ t: '见朋友 · 午茶', cat: 'event' }],
  11: [{ t: '染发', cat: 'care' }],
  15: [{ t: '探店 · 新咖啡馆', cat: 'event' }],
  18: [{ t: '拍写真', cat: 'event' }],
  22: [{ t: '成都周边 · 短途', cat: 'event' }],
  25: [{ t: '猫咪丰容采购', cat: 'errand' }],
  29: [{ t: '医美 · 复诊', cat: 'care' }],
};

// 各频道的关键事模板（周/月视图用，2–3 件，不铺钟点）
function keyItemsFor(d, dow, channel) {
  const k = [];
  const seed = SEEDED[d] || [];
  if (channel === 'focus') {
    k.push({ t: '公众号长文', cat: 'content', type: 'task' });
    if (dow === 0 || dow === 4) k.push({ t: '小红书选题', cat: 'content', type: 'task' });
    if (d % 2 === 0) k.push({ t: '台步练习', cat: 'runway', type: 'event' });
  } else if (channel === 'convert') {
    k.push({ t: '拍摄 · 出图', cat: 'content', type: 'task' });
    k.push({ t: '小红书发布', cat: 'content', type: 'task' });
  } else if (channel === 'outside') {
    k.push(...seed.map(s => ({ ...s, type: 'event' })));
    k.push({ t: '咖啡馆办公', cat: 'content', type: 'task' });
    if (k.length < 2) k.push({ t: '采买 · 跑腿', cat: 'errand', type: 'task' });
  } else if (channel === 'overflow') {
    k.push({ t: '内容收尾', cat: 'content', type: 'task' });
    k.push({ t: '家务整理', cat: 'life', type: 'task' });
  } else if (channel === 'recovery') {
    k.push({ t: '散步', cat: 'sport', type: 'task' });
    if (seed.length) k.push(...seed.map(s => ({ ...s, type: 'event' })));
    else k.push({ t: '看书 · 猫咪丰容', cat: 'life', type: 'task' });
  }
  // 把未归入的 seed 也并进来（如周末活动）
  seed.forEach(s => { if (!k.find(x => x.t === s.t)) k.unshift({ ...s, type: 'event' }); });
  return k.slice(0, 3);
}

// 主线归属：内容→T1，护理→T2，生活/运动→T3
function threadsOf(items) {
  const set = new Set();
  items.forEach(i => {
    if (i.cat === 'content' || i.cat === 'runway') set.add('T1');
    else if (i.cat === 'care') set.add('T2');
    else if (i.cat === 'life' || i.cat === 'sport') set.add('T3');
  });
  return [...set];
}

// 构建整月
const MONTH = [];
for (let d = 1; d <= 30; d++) {
  const dow = (d - 1) % 7; // 1号=周一=0
  const channel = channelFor(d, dow);
  const key = keyItemsFor(d, dow, channel);
  MONTH.push({
    d, dow, channel,
    weekday: WEEKDAYS[dow],
    key,
    threads: threadsOf(key),
    rest: channel === 'recovery',
  });
}

// 把月按周切（周一起，首周前面补空位）
const WEEKS = [];
{
  let cur = [];
  const firstDow = MONTH[0].dow; // 0
  for (let i = 0; i < firstDow; i++) cur.push(null);
  MONTH.forEach(day => {
    cur.push(day);
    if (cur.length === 7) { WEEKS.push(cur); cur = []; }
  });
  if (cur.length) { while (cur.length < 7) cur.push(null); WEEKS.push(cur); }
}
const WEEK_OF = {}; // 某天 → 周索引
WEEKS.forEach((w, wi) => w.forEach(day => { if (day) WEEK_OF[day.d] = wi; }));

// —— 作息骨架（展示底，每天一样，渲染时合并）——
const SPINE = [
  { time: '7:30',  min: 450,  title: '起床 · 慢启动', cat: 'life', kind: 'spine' },
  { time: '12:30', min: 750,  title: '午餐', cat: 'life', kind: 'spine' },
  { time: '19:00', min: 1140, title: '晚餐', cat: 'life', kind: 'spine' },
  { time: '22:30', min: 1350, title: '睡前收口', cat: 'life', kind: 'spine' },
];

// 把一天摊开成「时刻流」（日视图：呼吸景深用）
function buildDay(d) {
  const day = MONTH[d - 1];
  if (!day) return [];
  // 给关键事安排大致弹性时间（不是死点）
  const slots = [];
  const placed = [...day.key];
  // 上午一件、午后一两件、傍晚一件
  const times = [
    { time: '9:30',  min: 570 },
    { time: '14:00', min: 840 },
    { time: '16:30', min: 990 },
    { time: '20:30', min: 1230 },
  ];
  placed.forEach((it, i) => {
    const slot = times[Math.min(i, times.length - 1)];
    slots.push({ ...slot, title: it.t, cat: it.cat, kind: it.type === 'event' ? 'event' : 'task' });
  });
  // 合并作息骨架
  const all = [...SPINE.map(s => ({ ...s })), ...slots];
  all.sort((a, b) => a.min - b.min);
  // 标记完成 / 当下（仅今天有意义）
  const isToday = d === TODAY;
  all.forEach(m => {
    m.done = isToday ? m.min < NOW_MIN - 20 : false;
    m.now = false;
  });
  if (isToday) {
    // 找最接近当下、还没过去太久的那件作为「此刻」
    let nowIdx = all.findIndex(m => m.min >= NOW_MIN);
    if (nowIdx === -1) nowIdx = all.length - 1;
    // 取前一个更像「正在进行」
    const cand = nowIdx > 0 && all[nowIdx].min - NOW_MIN > 60 ? nowIdx - 1 : nowIdx;
    all[cand].now = true;
    all[cand].done = false;
  } else {
    // 非今天：聚焦到接近午后的代表性一刻，画面更平衡
    let mid = 0, best = 1e9;
    all.forEach((m, i) => { if (m.kind !== 'spine') { const dd = Math.abs(m.min - 870); if (dd < best) { best = dd; mid = i; } } });
    all[mid].now = true;
  }
  return all;
}

Object.assign(window, {
  CATS, CHANNELS, THREADS, MONTH, WEEKS, WEEK_OF, SPINE,
  TODAY, NOW_MIN, WEEKDAYS, buildDay,
});
