import { t, type I18nKey, getLang } from "../i18n";
import type { RenderSpec, ViewRow } from "./types";
import { formatLongDate, formatRowTime, parseDateOnly } from "./format";

// shape-cards: day-grouped chronological cards. Same layout style as the
// existing /agenda timeline; works for any source mix.

export function renderCardsShape(host: HTMLElement, rows: ViewRow[], render: RenderSpec): void {
  host.innerHTML = "";
  const cfg = render.cards ?? {};
  const groupBy = cfg.group_by ?? "day";
  const sort = cfg.sort ?? "date_asc";

  const sorted = [...rows].sort((a, b) => {
    const aT = sortKey(a.event_date);
    const bT = sortKey(b.event_date);
    return sort === "date_asc" ? aT - bT : bT - aT;
  });

  if (groupBy === "none") {
    host.appendChild(renderCardList(sorted, "none"));
    return;
  }

  const groups = groupRows(sorted, groupBy);
  for (const [key, items] of groups) {
    const section = document.createElement("section");
    section.className = "views-cards-day";
    const heading = document.createElement("h2");
    heading.className = "views-cards-day-heading";
    heading.textContent = key;
    section.appendChild(heading);
    section.appendChild(renderCardList(items, groupBy));
    host.appendChild(section);
  }
}

function renderCardList(rows: ViewRow[], groupBy: "day" | "week" | "none"): HTMLElement {
  const ul = document.createElement("ul");
  ul.className = "views-cards-list";
  // The day-grouped heading already shows the date — only that mode lets the
  // per-row time slot stay blank for date-only sources.
  const dateAvailable = groupBy === "day";
  for (const row of rows) {
    const li = document.createElement("li");
    li.className = `views-card views-card--${row.kind}`;

    const head = document.createElement("div");
    head.className = "views-card-head";
    const kind = document.createElement("span");
    kind.className = "views-card-kind";
    kind.textContent = t(("views.kind." + row.kind) as I18nKey);
    head.appendChild(kind);
    const title = document.createElement("h3");
    title.className = "views-card-title";
    title.textContent = row.title;
    head.appendChild(title);
    li.appendChild(head);

    const meta = document.createElement("div");
    meta.className = "views-card-meta";
    const timeText = formatRowTime(row, { dateAvailable });
    if (timeText) {
      const time = document.createElement("span");
      time.textContent = timeText;
      meta.appendChild(time);
    }
    if (row.project_title) {
      const proj = document.createElement("span");
      proj.className = "views-card-project";
      proj.textContent = row.project_title;
      meta.appendChild(proj);
    }
    if (row.actor_name) {
      const actor = document.createElement("span");
      actor.className = "views-card-actor";
      actor.textContent = row.actor_name;
      meta.appendChild(actor);
    }
    li.appendChild(meta);

    if (row.subtitle) {
      const sub = document.createElement("p");
      sub.className = "views-card-subtitle";
      sub.textContent = row.subtitle;
      li.appendChild(sub);
    }
    ul.appendChild(li);
  }
  return ul;
}

function groupRows(rows: ViewRow[], groupBy: "day" | "week"): Array<[string, ViewRow[]]> {
  const map = new Map<string, ViewRow[]>();
  for (const row of rows) {
    const key = bucketKey(row.event_date, groupBy);
    const arr = map.get(key);
    if (arr) arr.push(row);
    else map.set(key, [row]);
  }
  return Array.from(map.entries());
}

function bucketKey(iso: string, groupBy: "day" | "week"): string {
  // Date-only inputs (deadlines) are anchored to UTC midnight so the bucket
  // matches the source day in every timezone — otherwise a UTC-X user would
  // see deadlines slip into the previous day.
  const dateOnly = parseDateOnly(iso);
  const d = dateOnly ?? new Date(iso);
  if (isNaN(d.getTime())) return iso;
  const lang = getLang() === "de" ? "de-DE" : "en-GB";
  if (groupBy === "week") {
    const monday = new Date(d);
    const day = monday.getDay() || 7; // Sunday=0 → 7
    monday.setDate(monday.getDate() - day + 1);
    const yearStart = new Date(Date.UTC(monday.getFullYear(), 0, 1));
    const weekNo = Math.ceil(((monday.getTime() - yearStart.getTime()) / 86400000 + yearStart.getDay() + 1) / 7);
    return `KW ${weekNo}, ${monday.getFullYear()}`;
  }
  if (dateOnly) return formatLongDate(iso);
  return d.toLocaleDateString(lang, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
}

function sortKey(iso: string): number {
  const dateOnly = parseDateOnly(iso);
  if (dateOnly) return dateOnly.getTime();
  return Date.parse(iso);
}
