// ============================================================================
//  ATHLETE DATA — generic, data-driven adapter
//  Detects athlete from hostname (<slug>-rowing.pages.dev) or ?id=,
//  builds a per-crew window.PB (same shape mitoma's playbook-app expects)
//  + window.ATHLETE identity. NO personal metrics, FACTS ONLY.
// ============================================================================

// ── Helper functions (verbatim from mitoma/playbook-data.jsx) ───────────────
const iso = (d) => {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
};
const parseISO = (s) => new Date(s + "T00:00:00+09:00");
const daysBetween = (a, b) => Math.round((parseISO(b) - parseISO(a)) / 86400000);

let PHASES = [];
const findPhase = (dateISO) => {
  return PHASES.find((p) => dateISO >= p.start && dateISO <= p.end);
};
const dayInPhase = (phase, dateISO) => daysBetween(phase.start, dateISO) + 1;

const weekDates = (dateISO) => {
  // Monday-Sunday week containing the given date
  const d = parseISO(dateISO);
  const day = (d.getDay() + 6) % 7; // 0 = Monday
  const monday = new Date(d);
  monday.setDate(d.getDate() - day);
  return Array.from({ length: 7 }, (_, i) => {
    const dd = new Date(monday);
    dd.setDate(monday.getDate() + i);
    return iso(dd);
  });
};

const fmtJp = (dateISO) => {
  const d = parseISO(dateISO);
  return `${d.getMonth() + 1}/${d.getDate()}`;
};
const weekdayJp = ["日", "月", "火", "水", "木", "金", "土"];
const weekdayEn = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];

// ── Slug → athlete map ──────────────────────────────────────────────────────
//  EN names are not sensitive. No emails anywhere.
const ATHLETES = {
  sakurama:     { jp: "櫻間 達也",    en: "Tatsuya SAKURAMA",  crew: "sakurama", state: "sakurama-state" },
  miyaguchi:    { jp: "宮口 大誠",    en: "Taisei MIYAGUCHI",  crew: "m2x-sr" },
  takeda:       { jp: "武田 匡弘",    en: "Masahiro TAKEDA",   crew: "m2x-sr" },
  tsushida:     { jp: "津志田 匠太郎", en: "Shotaro TSUSHIDA",  crew: "m4-" },
  "kishimoto-k":{ jp: "岸本 健吾",    en: "Kengo KISHIMOTO",   crew: "m4-" },
  ishimasa:     { jp: "石政 雄也",    en: "Yuya ISHIMASA",     crew: "m4-" },
  hirukawa:     { jp: "蛭川 暢之",    en: "Nobuyuki HIRUKAWA", crew: "m4-" },
  yonekawa:     { jp: "米川 志保",    en: "Shiho YONEKAWA",    crew: "w2", state: "w2-state" },
  takano:       { jp: "髙野 晃帆",    en: "Akiho TAKANO",      crew: "w2", state: "w2-state" },
  matsuda:      { jp: "松田 京子",    en: "Kyoko MATSUDA",     crew: "w4-" },
  iijima:       { jp: "飯島 佐和子",  en: "Sawako IIJIMA",     crew: "w4-" },
  suzuki:       { jp: "鈴木 伶奈",    en: "Rena SUZUKI",       crew: "w4-" },
  "kishimoto-y":{ jp: "岸本 唯佳",    en: "Yuka KISHIMOTO",    crew: "w4-" },
  yonezawa:     { jp: "米澤 知華",    en: "Chika YONEZAWA",    crew: "lw2x" },
  tomita:       { jp: "冨田 千愛",    en: "Chiaki TOMITA",     crew: "lw2x" },
};

function getSlug() {
  try {
    const id = new URLSearchParams(location.search).get("id");
    if (id && ATHLETES[id]) return id;
  } catch {}
  try {
    let h = location.hostname || "";
    h = h.replace(/\.pages\.dev$/, "");
    const seg = h.split(".").pop() || "";
    const slug = seg.replace(/-rowing$/, "");
    if (ATHLETES[slug]) return slug;
  } catch {}
  return "miyaguchi";
}

const slug = getSlug();
const A = ATHLETES[slug];

// ── Resolve crew / track / profile ──────────────────────────────────────────
const SQUAD = window.SQUAD;
const SQUAD_MENU = window.SQUAD_MENU;
const SQUAD_MENU_SET = window.SQUAD_MENU_SET;
const SQUAD_PROFILES = window.SQUAD_PROFILES;
const RRPG_COMP = window.RRPG_COMP;

const crew = SQUAD.crews.find((c) => c.id === A.crew);
const track = SQUAD.tracks.find((t) => t.id === crew.track);
const prof = SQUAD_PROFILES[A.jp] || {};
const compJP = (id) => SQUAD.competitions.find((c) => c.id === id) || {};

// ── CAMPAIGNS (race-date order) ─────────────────────────────────────────────
function roleOf(rank, cond) {
  let role =
    rank === 1 ? "PRIMARY ／ 本命" :
    rank === 2 ? "SECOND ／ 第2" :
    "TARGET";
  if (cond) role += " ／ 条件付き";
  return role;
}

// crew.races already in chronological (race-date) order in squad-data
const racesSorted = crew.races
  .map((r) => ({ ...r, comp: RRPG_COMP[r.c] }))
  .filter((r) => r.comp)
  .sort((a, b) => (a.comp.start < b.comp.start ? -1 : 1));

const CAMPAIGNS = racesSorted.map((r, i) => {
  const cj = compJP(r.c);
  const rc = RRPG_COMP[r.c];
  return {
    id: r.c,
    rank: i + 1,
    nameJp: cj.name,
    nameEn: rc.race.replace(/<br>/g, " "),
    where: (cj.flag || "") + " " + (cj.place || ""),
    whereEn: rc.where,
    dates: rc.date,
    datesEn: rc.date,
    role: roleOf(i + 1, r.cond),
    targetDate: rc.start,
    note: r.cond ? "結果により確定" : (track.note || ""),
  };
});

// ── DAY_MENU (from team menu set for this crew's track) ──────────────────────
const menuKey = SQUAD_MENU_SET[crew.track];
const menuSet = (menuKey && SQUAD_MENU[menuKey]) || { days: {} };
const DAY_MENU = {};
Object.keys(menuSet.days || {}).forEach((d) => {
  const x = menuSet.days[d];
  DAY_MENU[d] = { menu: x.m, key: !!x.key, race: !!x.race, tag: x.tag };
});

// ── PHASES (clean sequential, non-overlapping season arc) ───────────────────
// 1. Real camp blocks (apply to the WC3 senior group = all these crews)
const camps = [
  { id: "may",   label: "5月強化合宿",       labelEn: "MAY CAMP",         emoji: "🏋️", kind: "natl",   start: "2026-05-20", end: "2026-05-31", desc: "5月の強化合宿（高負荷の土台）。" },
  { id: "home1", label: "所属準備",           labelEn: "CLUB PREP",        emoji: "🚣", kind: "design", start: "2026-06-01", end: "2026-06-12", desc: "所属でのトレーニング。" },
  { id: "aigue", label: "エギュベレット合宿", labelEn: "AIGUEBELETTE CAMP", emoji: "🇫🇷", kind: "travel", start: "2026-06-13", end: "2026-06-25", desc: "仏エギュベレット強化合宿→ルツェルン派遣(6/12–30)。" },
];

// 2. A race phase for each race the crew actually does
const RACE_FLAG = { wc3: "🇨🇭", wch: "🇳🇱", asia: "🇯🇵" };
const racePhases = racesSorted.map((r) => {
  const cj = compJP(r.c);
  const rc = RRPG_COMP[r.c];
  const overseas = r.c === "wc3" || r.c === "wch";
  const kind = overseas ? "race-int" : "race-jp";
  let marker = "▲";
  let peak;
  if (r.c === "asia") marker = "◆";
  if (r.c === "wch") { marker = "★"; peak = 1; }
  let desc = rc.where + " ／ " + rc.date;
  if (r.cond) desc += "（結果により確定）";
  return {
    id: "race-" + r.c,
    label: cj.name,
    labelEn: rc.short,
    emoji: RACE_FLAG[r.c] || "🏁",
    kind,
    start: rc.start,
    end: rc.end,
    marker,
    peak,
    desc,
  };
});
// If no wch but crew races asia, give asia a ★ as the season-defining race
const hasWch = racesSorted.some((r) => r.c === "wch");
if (!hasWch) {
  const asiaPhase = racePhases.find((p) => p.id === "race-asia");
  if (asiaPhase) { asiaPhase.marker = "★"; asiaPhase.peak = 1; }
}

// 3. Sort camps + races by start date, then fill gaps
let blocks = [...camps, ...racePhases].sort((a, b) => (a.start < b.start ? -1 : 1));

const filled = [];
for (let i = 0; i < blocks.length; i++) {
  const b = blocks[i];
  // skip blocks fully contained in / overlapping the previous accepted block
  const prev = filled[filled.length - 1];
  if (prev && b.start <= prev.end) {
    // overlapping race inside a camp window — push start to after prev
    // (keeps it sequential; keep its real end if later)
    if (b.end > prev.end) {
      const ns = iso(new Date(parseISO(prev.end).getTime() + 86400000));
      filled.push({ ...b, start: ns });
    }
    // else fully contained: drop (its dates live inside the camp)
    continue;
  }
  if (prev) {
    const gap = daysBetween(prev.end, b.start);
    if (gap > 1) {
      const gapStart = iso(new Date(parseISO(prev.end).getTime() + 86400000));
      const gapEnd = iso(new Date(parseISO(b.start).getTime() - 86400000));
      filled.push({
        id: "fill-" + i,
        label: "所属・調整",
        labelEn: "CLUB / ADJUST",
        emoji: "⏱",
        kind: "design",
        start: gapStart,
        end: gapEnd,
        desc: "所属での調整期。",
      });
    }
  }
  filled.push(b);
}

// 4. Compute days / weight for each phase
PHASES = filled.map((p) => {
  const days = daysBetween(p.start, p.end) + 1;
  return { ...p, days, weight: days };
});

// 5. Season bounds
const SEASON_START = "2026-05-20";
const SEASON_END = PHASES.reduce((mx, p) => (p.end > mx ? p.end : mx), SEASON_START);

// ── QUOTES (verbatim from mitoma, generic motivational) ─────────────────────
const QUOTES = [
  { en: "EARN THE PEAK.", jp: "ピークは作るんじゃない、勝ち取るもの。" },
  { en: "3 STARTS · 3 FLAGS · 1 SUMMER.", jp: "3つのスタート、3つの旗、ひとつの夏。" },
  { en: "ROW Z1 IN Z1.", jp: "Z1は Z1で漕げ。軽い日は本気で軽く。" },
  { en: "RECOVERY IS THE WORK.", jp: "回復こそが、訓練。" },
  { en: "WIN THE WAIT.", jp: "待つことに勝て。" },
  { en: "ONE OAR. ONE GOAL.", jp: "一本のオール、ひとつのゴール。" },
  { en: "98 DAYS TO BURN.", jp: "燃やす日数、九十八。" },
  { en: "FROM TODA, TO THE WORLD.", jp: "戸田から、世界へ。" },
  { en: "TRUST THE PLAN. TRUST THE BODY.", jp: "計画を信じ、体を信じよ。" },
  { en: "THE LAKE REMEMBERS EVERY STROKE.", jp: "湖は、すべての一漕ぎを覚えている。" },
];

// ── window.ATHLETE (identity) ───────────────────────────────────────────────
const enParts = A.en.trim().split(/\s+/);
const given = (enParts[0] || "").toUpperCase();
const surname = (enParts.slice(1).join(" ") || "").toUpperCase();
const mark = (given[0] || "") + "·" + (surname[0] || "");
const myMember = (crew.members || []).find((m) => m.name === A.jp) || {};

window.ATHLETE = {
  slug,
  jp: A.jp,
  en: A.en,
  given,
  surname,
  mark,
  club: myMember.club || "",
  event: crew.event,
  squad: crew.squad,
  priority: !!crew.priority,
  trackFlow: track.flow,
  trackNote: track.note,
  stateUrl: A.state ? "https://rowing-rpg-shell.pages.dev/" + A.state : null,
  members: crew.members,
  prof,
  fileNo: slug.toUpperCase().replace("-", "") + "-2026/SUM",
};

// ── window.PB (same shape mitoma's playbook-app expects) ─────────────────────
window.PB = {
  PHASES, CAMPAIGNS, DAY_MENU, QUOTES,
  SEASON_START, SEASON_END,
  iso, parseISO, daysBetween, findPhase, dayInPhase,
  weekDates, fmtJp, weekdayJp, weekdayEn,
};
