/* TargiApp — harmonogram: kalendarz tygodniowy (kolumny = dni), karty = osoby z rolą/godzinami/notatką.
   Drag&drop kart między dniami + przeciąganie z listy zespołu + dropdown "Dodaj osobę".
   Przełączanie tygodni, filtrowanie (rola + osoba) i sortowanie kart. */

// ---- helpers dat / tygodnia ----
const MONTHS_SHORT = ["sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru"];
function isoDate(d) {
  return d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
}
function mondayOf(dateStr) {
  const d = new Date(dateStr); const off = (d.getDay() + 6) % 7;
  d.setHours(0, 0, 0, 0); d.setDate(d.getDate() - off); return d;
}
function addDays(date, n) { const d = new Date(date); d.setDate(d.getDate() + n); return d; }

function AssignCard({ a, onEdit, onCardDrop }) {
  const store = useStore();
  const p = store.personById(a.personId);
  const r = store.roleOf(a.role);
  const [edge, setEdge] = useState(null); // 'top' | 'bottom' — wskaźnik miejsca wstawienia
  return (
    <div
      className={"acard" + (edge ? " edge-" + edge : "")}
      style={{ borderLeftColor: r.color }}
      draggable
      onDragStart={(e) => {
        e.dataTransfer.setData("text/assignment", String(a.id));
        e.dataTransfer.effectAllowed = "move";
        e.currentTarget.classList.add("dragging");
      }}
      onDragEnd={(e) => e.currentTarget.classList.remove("dragging")}
      onDragOver={(e) => {
        e.preventDefault();
        const rect = e.currentTarget.getBoundingClientRect();
        setEdge(e.clientY < rect.top + rect.height / 2 ? "top" : "bottom");
      }}
      onDragLeave={() => setEdge(null)}
      onDrop={(e) => {
        e.preventDefault(); e.stopPropagation();
        const before = edge !== "bottom";
        setEdge(null);
        onCardDrop(e, a, before);
      }}
      onClick={() => onEdit(a)}
    >
      <button className="acard-x" title="Usuń z dnia" onClick={(e) => { e.stopPropagation(); store.removeAssignment(a.id); }}>✕</button>
      <div className="acard-top">
        <Avatar name={store.fullName(p)} size={30} color={r.color} />
        <div className="acard-name">{store.fullName(p)}</div>
      </div>
      <div className="acard-meta">
        <RoleChip roleKey={a.role} />
        <span className="acard-hours">{a.from}–{a.to}</span>
      </div>
      {a.note ? <div className="acard-note">{a.note}</div> : null}
    </div>
  );
}

function AddPersonDropdown({ date }) {
  const store = useStore();
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return;
    function onDoc(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  const available = store.state.people
    .filter((p) => store.fullName(p).toLowerCase().includes(q.toLowerCase()))
    .sort((a, b) => store.fullName(a).localeCompare(store.fullName(b)));

  return (
    <div className="add-row" ref={ref}>
      <button className="add-btn" onClick={() => { setOpen((o) => !o); setQ(""); }}>+ Dodaj osobę</button>
      {open ? (
        <div className="dropdown">
          <div className="dd-search">
            <span>🔍</span>
            <input autoFocus placeholder="Szukaj osoby…" value={q} onChange={(e) => setQ(e.target.value)} />
          </div>
          <div className="dd-list">
            {available.map((p) => (
              <div key={p.id} className="dd-item" onClick={() => { store.addAssignment(p.id, date); setOpen(false); }}>
                <Avatar name={store.fullName(p)} size={26} />
                <span className="dd-name">{store.fullName(p)}</span>
              </div>
            ))}
            {!available.length ? <div className="dd-empty">Brak dostępnych osób</div> : null}
          </div>
        </div>
      ) : null}
    </div>
  );
}

function DayColumn({ day, onEdit, roleFilter, personQuery, sortBy, setSortBy }) {
  const store = useStore();
  const [over, setOver] = useState(false);
  const roleOrder = store.ROLES.map((r) => r.key);
  const q = personQuery.trim().toLowerCase();

  let items = store.assignmentsForDay(day.date)
    .filter((a) => roleFilter.has(a.role))
    .filter((a) => !q || store.fullName(store.personById(a.personId)).toLowerCase().includes(q));

  if (sortBy !== "reczna") {
    items = items.slice().sort((a, b) => {
      if (sortBy === "rola") return roleOrder.indexOf(a.role) - roleOrder.indexOf(b.role) || (a.from || "").localeCompare(b.from || "");
      if (sortBy === "nazwisko") {
        const pa = store.personById(a.personId), pb = store.personById(b.personId);
        return (pa.lastName || "").localeCompare(pb.lastName || "");
      }
      return (a.from || "").localeCompare(b.from || ""); // godzina
    });
  }
  // w trybie "reczna" zostaje kolejność wg pozycji (z assignmentsForDay)

  function onDrop(e) {
    e.preventDefault(); setOver(false);
    const aId = e.dataTransfer.getData("text/assignment");
    const pId = e.dataTransfer.getData("text/person");
    if (aId) store.moveAssignment(Number(aId), day.date);
    else if (pId) store.addAssignment(Number(pId), day.date);
  }

  // upuszczenie na konkretną kartę = ustawienie kolejności (przełącza na tryb ręczny)
  function onCardDrop(e, target, before) {
    const aId = e.dataTransfer.getData("text/assignment");
    const pId = e.dataTransfer.getData("text/person");
    if (aId) {
      const draggedId = Number(aId);
      if (draggedId === target.id) return;
      const dragged = store.state.assignments.find((x) => x.id === draggedId);
      if (dragged && dragged.date !== day.date) store.moveAssignment(draggedId, day.date);
      store.reorderAssignment(draggedId, target.id, before);
      setSortBy("reczna");
    } else if (pId) {
      Promise.resolve(store.addAssignment(Number(pId), day.date)).then((created) => {
        if (created) { store.reorderAssignment(created.id, target.id, before); setSortBy("reczna"); }
      });
    }
  }

  const cls = "daycol"
    + (over ? " drop" : "")
    + (day.isFair ? " fair" : "")
    + (day.weekend ? " weekend" : "")
    + (!day.isFair && !items.length ? " dim" : "");

  const user = store.currentUser();

  return (
    <div className={cls}
      onDragOver={(e) => { e.preventDefault(); setOver(true); }}
      onDragLeave={() => setOver(false)}
      onDrop={onDrop}>
      <div className="daycol-head">
        <span className="daycol-count">{items.length} os.</span>
        <div className="daycol-day">{day.dow} {day.dom}</div>
        <div className="daycol-date">{day.monthName}</div>
        {user && user.isAdmin ? (
          <div className="daycol-fair-admin">
            <button className={"fair-toggle" + (day.isFair ? " on" : "")} onClick={() => store.toggleFairDay(day.date)}>
              {day.isFair ? "dzień targowy" : "+ oznacz jako targowy"}
            </button>
            {day.isFair ? (
              <input className="fair-label-input" value={day.fairLabel || ""} placeholder="etykieta (np. Montaż, Dzień 1)"
                onChange={(e) => store.setFairDayLabel(day.date, e.target.value)} />
            ) : null}
          </div>
        ) : (day.isFair ? <span className="daycol-tag">{day.fairLabel || "Targi"}</span> : null)}
      </div>
      <div className="daycol-body">
        {items.map((a) => <AssignCard key={a.id} a={a} onEdit={onEdit} onCardDrop={onCardDrop} />)}
        {!items.length ? <div className="daycol-empty">Przeciągnij osobę tutaj<br />lub dodaj poniżej</div> : null}
        <AddPersonDropdown date={day.date} />
      </div>
    </div>
  );
}

function Roster() {
  const store = useStore();
  const [q, setQ] = useState("");
  const [sort, setSort] = useState("alfa");
  let people = store.state.people.filter((p) => store.fullName(p).toLowerCase().includes(q.toLowerCase()));
  people = people.sort((a, b) =>
    sort === "dni"
      ? store.daysForPerson(b.id).size - store.daysForPerson(a.id).size || store.fullName(a).localeCompare(store.fullName(b))
      : store.fullName(a).localeCompare(store.fullName(b))
  );

  return (
    <aside className="roster">
      <div className="roster-head">
        <div className="roster-title">Zespół · {store.state.people.length}</div>
        <div className="roster-sub">Przeciągnij osobę na wybrany dzień</div>
      </div>
      <div className="roster-search">
        <span>🔍</span>
        <input placeholder="Szukaj…" value={q} onChange={(e) => setQ(e.target.value)} />
      </div>
      <div style={{ display: "flex", gap: 6, padding: "4px 12px 2px" }}>
        <button className={"filter-chip" + (sort === "alfa" ? "" : " off")} onClick={() => setSort("alfa")}>A–Z</button>
        <button className={"filter-chip" + (sort === "dni" ? "" : " off")} onClick={() => setSort("dni")}>wg dni</button>
      </div>
      <div className="roster-list">
        {people.map((p) => {
          const cnt = store.daysForPerson(p.id).size;
          return (
            <div key={p.id} className="roster-item" draggable
              onDragStart={(e) => { e.dataTransfer.setData("text/person", String(p.id)); e.dataTransfer.effectAllowed = "copy"; }}>
              <Avatar name={store.fullName(p)} size={30} />
              <div style={{ minWidth: 0 }}>
                <div className="ri-name">{store.fullName(p)}</div>
                <div className="ri-meta">{p.isAdmin ? "Administrator" : "Pracownik"}</div>
              </div>
              {cnt ? <span className="ri-count" title="Dni na targach">{cnt}</span> : null}
            </div>
          );
        })}
      </div>
    </aside>
  );
}

function EditModal({ a, onClose }) {
  const store = useStore();
  const p = store.personById(a.personId);
  const [role, setRole] = useState(a.role);
  const [from, setFrom] = useState(a.from);
  const [to, setTo] = useState(a.to);
  const [note, setNote] = useState(a.note);

  function save() { store.updateAssignment(a.id, { role, from, to, note }); onClose(); }

  return (
    <div className="overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal">
        <div className="modal-head">
          <Avatar name={store.fullName(p)} size={34} color={store.roleOf(role).color} />
          <div>
            <div className="modal-title">{store.fullName(p)}</div>
            <div className="card-sub">{fmtDayLong(a.date)}</div>
          </div>
          <button className="modal-x" onClick={onClose}>✕</button>
        </div>
        <div className="modal-body">
          <div className="field">
            <label>Rola na stoisku</label>
            <div className="role-picker">
              {store.ROLES.map((r) => (
                <button key={r.key} className={"role-opt" + (role === r.key ? " on" : "")} onClick={() => setRole(r.key)}>
                  <span className="swatch" style={{ background: r.color }}></span>{r.label}
                </button>
              ))}
            </div>
          </div>
          <div className="field-row">
            <div className="field"><label>Od</label><input type="time" value={from} onChange={(e) => setFrom(e.target.value)} /></div>
            <div className="field"><label>Do</label><input type="time" value={to} onChange={(e) => setTo(e.target.value)} /></div>
          </div>
          <div className="field">
            <label>Notatka / zadanie</label>
            <textarea placeholder="np. recepcja stoiska, prezentacja produktu o 14:00…" value={note} onChange={(e) => setNote(e.target.value)}></textarea>
          </div>
        </div>
        <div className="modal-actions">
          <button className="btn danger" onClick={() => { store.removeAssignment(a.id); onClose(); }}>Usuń przydział</button>
          <button className="btn" onClick={onClose}>Anuluj</button>
          <button className="btn primary" onClick={save}>Zapisz</button>
        </div>
      </div>
    </div>
  );
}

function Toolbar({ weekStart, setWeekStart, weekDays, fairWeekStart, roleFilter, setRoleFilter, sortBy, setSortBy, search, setSearch }) {
  const store = useStore();
  const last = weekDays[6];
  const label = weekDays[0].dom + " " + weekDays[0].monthName.split(" ")[0] + " – " + last.dom + " " + last.monthName;
  function toggleRole(k) {
    setRoleFilter((prev) => {
      const next = new Set(prev);
      if (next.has(k)) next.delete(k); else next.add(k);
      return next;
    });
  }
  const allOn = roleFilter.size === store.ROLES.length;

  return (
    <div className="sched-toolbar">
      <div className="week-nav">
        <button className="week-arrow" title="Poprzedni tydzień" onClick={() => setWeekStart(addDays(weekStart, -7))}>‹</button>
        <div className="week-label"><small>Tydzień</small>{label}</div>
        <button className="week-arrow" title="Następny tydzień" onClick={() => setWeekStart(addDays(weekStart, 7))}>›</button>
        <button className="btn ghost" style={{ marginLeft: 4 }} onClick={() => setWeekStart(new Date(fairWeekStart))}>📅 Tydzień targów</button>
      </div>

      <div className="toolbar-spacer"></div>

      <div className="filter-group">
        <span className="toolbar-label">Role</span>
        {store.ROLES.map((r) => (
          <button key={r.key} className={"filter-chip" + (roleFilter.has(r.key) ? "" : " off")} onClick={() => toggleRole(r.key)}>
            <span className="swatch" style={{ background: r.color }}></span>{r.short}
          </button>
        ))}
        <button className="filter-chip" style={{ borderStyle: allOn ? "solid" : "dashed" }}
          onClick={() => setRoleFilter(new Set(store.ROLES.map((r) => r.key)))}>{allOn ? "Wszystkie" : "Pokaż wszystkie"}</button>
      </div>

      <div className="toolbar-sep"></div>

      <select className="sort-select" value={sortBy} onChange={(e) => setSortBy(e.target.value)}>
        <option value="reczna">Kolejność: ręczna (drag)</option>
        <option value="godzina">Sortuj: godzina</option>
        <option value="rola">Sortuj: rola</option>
        <option value="nazwisko">Sortuj: nazwisko</option>
      </select>

      <div className="toolbar-search">
        <span>🔍</span>
        <input placeholder="Filtruj osobę…" value={search} onChange={(e) => setSearch(e.target.value)} />
      </div>
    </div>
  );
}

function SchedulePage() {
  const store = useStore();
  const user = store.currentUser();
  const [editing, setEditing] = useState(null);
  const days0 = (store.state.fair.days && store.state.fair.days[0]) ? store.state.fair.days[0].date : isoDate(new Date());
  const fairWeekStart = mondayOf(days0);
  const [weekStart, setWeekStart] = useState(() => mondayOf(days0));
  const [roleFilter, setRoleFilter] = useState(() => new Set(store.ROLES.map((r) => r.key)));
  const [sortBy, setSortBy] = useState("reczna");
  const [search, setSearch] = useState("");

  // liczone inline (reaguje na zmiany dni targowych przez admina)
  const fairMap = {};
  (store.state.fair.days || []).forEach((d) => (fairMap[d.date] = d.label));

  const dow = ["niedz.", "pon.", "wt.", "śr.", "czw.", "pt.", "sob."];
  const weekDays = [];
  for (let i = 0; i < 7; i++) {
    const d = addDays(weekStart, i);
    const ds = isoDate(d);
    weekDays.push({
      date: ds, dow: dow[d.getDay()], dom: d.getDate(),
      monthName: MONTHS_SHORT[d.getMonth()] + " " + d.getFullYear(),
      weekend: d.getDay() === 0 || d.getDay() === 6,
      isFair: Object.prototype.hasOwnProperty.call(fairMap, ds),
      fairLabel: fairMap[ds] || "",
    });
  }

  const fairDaysCount = (store.state.fair.days || []).length;
  const total = store.state.assignments.length;
  const peopleOnFair = new Set(store.state.assignments.map((a) => a.personId)).size;

  return (
    <div>
      <div className="page-head">
        <div>
          {user.isAdmin
            ? <input className="fair-name-input" value={store.state.fair.name} placeholder="Nazwa targów" onChange={(e) => store.setFairName(e.target.value)} />
            : <div className="page-title">{store.state.fair.name}</div>}
          <div className="page-sub">📍 {store.state.fair.venue} · {fairDaysCount} dni targowych · {peopleOnFair} osób w grafiku · {total} przydziałów</div>
        </div>
      </div>

      <Toolbar
        weekStart={weekStart} setWeekStart={setWeekStart} weekDays={weekDays} fairWeekStart={fairWeekStart}
        roleFilter={roleFilter} setRoleFilter={setRoleFilter} sortBy={sortBy} setSortBy={setSortBy}
        search={search} setSearch={setSearch} />

      <div className="sched-layout">
        <Roster />
        <div className="board">
          {weekDays.map((day) => (
            <DayColumn key={day.date} day={day} onEdit={setEditing} roleFilter={roleFilter} personQuery={search} sortBy={sortBy} setSortBy={setSortBy} />
          ))}
        </div>
      </div>
      {editing ? <EditModal a={editing} onClose={() => setEditing(null)} /> : null}
    </div>
  );
}
Object.assign(window, { SchedulePage });
