<!doctype html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <%- include('partials/favicon') %>
    <title>(회의록 기반) 업무 체크리스트 AI - NCue</title>
    <link rel="stylesheet" href="/public/styles.css" />
  </head>
  <body class="task-checklist-page">
    <div class="app-shell">
      <%- include('partials/nav', { activeMenu: 'ai-explore', adminMode: typeof adminMode !== 'undefined' ? adminMode : false }) %>
      <div class="content-area">
        <header class="topbar">
          <h1>(회의록 기반) 업무 체크리스트 AI</h1>
          <a class="top-action-link" href="/ai-explore">AI 목록</a>
        </header>
        <main class="container container-ai-full meeting-minutes-main">
          <a href="/ai-explore" class="prompts-back" aria-label="AI 탐색으로 돌아가기">← AI</a>
          <% var hasEmail = typeof meetingUserEmail !== 'undefined' && meetingUserEmail; %>
          <% if (!hasEmail) { %>
          <p class="chat-api-warning" style="margin-bottom: 16px">
            이메일 인증(OPS <code>PROD</code>) 또는 DEV에서 <strong>관리자 모드</strong>, SUPER(데모)에서는 별도 로그인 없이 이용할 수 있습니다.
          </p>
          <% } else { %>
          <p class="subtitle tcl-lead">
            <strong>회의록 AI</strong>에서 저장한 내용을 바탕으로 할 일이 모입니다. 회의록의 <strong>액션 아이템(번호별)</strong>과 <strong>회의 체크리스트</strong>가 모두 항목으로 반영됩니다. <strong>진행상황</strong> 또는 <strong>회의록</strong>을 바꿀 때마다 선택한 범위에서 자동으로 가져온 뒤 목록을 맞춥니다. 항목에 마우스를 올리면 해당 <strong>회의 제목·일자·요약</strong>을 볼 수 있습니다.
          </p>

          <section class="panel tcl-toolbar">
            <div class="tcl-toolbar-row">
              <label class="tcl-filter">
                <span class="tcl-filter-label">진행상황</span>
                <select id="tclFilter" class="mm-select">
                  <option value="all" selected>전체</option>
                  <option value="open">진행 중</option>
                  <option value="done">완료</option>
                </select>
              </label>
              <label class="tcl-filter">
                <span class="tcl-filter-label">회의록</span>
                <select id="tclMeetingPick" class="mm-select" title="목록 필터·가져오기 범위 (기본: 전체 회의)">
                  <option value="__all__" selected>전체 (모든 회의)</option>
                </select>
              </label>
            </div>
          </section>

          <section class="panel">
            <div class="tcl-sort-bar" role="group" aria-label="목록 정렬">
              <span class="tcl-sort-label">정렬</span>
              <button type="button" class="tcl-sort-btn" id="tclSortDate" data-sort="date">날짜순</button>
              <button type="button" class="tcl-sort-btn" id="tclSortAlpha" data-sort="alpha">글자순</button>
              <button type="button" class="tcl-sort-btn tcl-sort-btn-active" id="tclSortCompleted" data-sort="completed">완료여부순</button>
            </div>
            <h2 class="tcl-section-title">업무 체크리스트</h2>
            <p class="tcl-empty" id="tclEmpty" hidden>표시할 항목이 없습니다.</p>
            <ul class="tcl-list" id="tclList" role="list"></ul>
          </section>

          <div id="tclEditModal" class="tcl-modal" hidden>
            <div class="tcl-modal-backdrop" id="tclEditBackdrop"></div>
            <div class="tcl-modal-panel" role="dialog" aria-modal="true" aria-labelledby="tclEditModalTitle">
              <h3 id="tclEditModalTitle" class="tcl-modal-title">체크리스트 항목 수정</h3>
              <label class="tcl-modal-field">
                <span class="mm-field-label">제목</span>
                <input type="text" id="tclEditTitle" class="mm-input" maxlength="2000" />
              </label>
              <label class="tcl-modal-field">
                <span class="mm-field-label">내용</span>
                <textarea id="tclEditDetail" class="mm-textarea" rows="4" maxlength="8000" placeholder="할 일 제목에 대한 상세 내용"></textarea>
              </label>
              <div class="tcl-modal-actions">
                <button type="button" class="btn-ghost" id="tclEditCancel">취소</button>
                <button type="button" class="top-action" id="tclEditSave">저장</button>
              </div>
            </div>
          </div>

          <div id="tclCompleteModal" class="tcl-modal" hidden>
            <div class="tcl-modal-backdrop" id="tclCompleteBackdrop"></div>
            <div class="tcl-modal-panel" role="dialog" aria-modal="true" aria-labelledby="tclCompleteModalTitle">
              <h3 id="tclCompleteModalTitle" class="tcl-modal-title">완료 처리</h3>
              <p class="tcl-complete-preview" id="tclCompletePreview"></p>
              <label class="tcl-modal-field">
                <span class="mm-field-label">처리 내용</span>
                <textarea
                  id="tclCompleteNote"
                  class="mm-textarea"
                  rows="4"
                  maxlength="8000"
                  placeholder="어떻게 처리했는지 간단히 적어 주세요."
                ></textarea>
              </label>
              <div class="tcl-modal-actions">
                <button type="button" class="btn-ghost" id="tclCompleteCancel">취소</button>
                <button type="button" class="top-action" id="tclCompleteSave">저장</button>
              </div>
            </div>
          </div>
          <% } %>
        </main>
      </div>
    </div>
    <% if (hasEmail) { %>
    <script>
      (function () {
        var filterEl = document.getElementById('tclFilter');
        var meetingPick = document.getElementById('tclMeetingPick');
        var listEl = document.getElementById('tclList');
        var emptyEl = document.getElementById('tclEmpty');
        var editModal = document.getElementById('tclEditModal');
        var editTitle = document.getElementById('tclEditTitle');
        var editDetail = document.getElementById('tclEditDetail');
        var editingId = null;
        var completeModal = document.getElementById('tclCompleteModal');
        var completeNoteEl = document.getElementById('tclCompleteNote');
        var completePreviewEl = document.getElementById('tclCompletePreview');
        var completePendingId = null;
        var sortMode = 'completed';

        function api(path, opts) {
          return fetch(path, Object.assign({ credentials: 'same-origin' }, opts || {})).then(function (r) {
            return r.json().then(function (j) {
              if (!r.ok) throw new Error(j.error || r.statusText);
              return j;
            });
          });
        }

        function loadMeetingsDropdown() {
          var prev = meetingPick.value;
          return api('/api/meeting-minutes/meetings').then(function (d) {
            var list = d.meetings || [];
            meetingPick.innerHTML = '';
            var optAll = document.createElement('option');
            optAll.value = '__all__';
            optAll.textContent = '전체 (모든 회의)';
            meetingPick.appendChild(optAll);
            list.forEach(function (m) {
              var opt = document.createElement('option');
              opt.value = m.id;
              opt.textContent = (m.title || '제목 없음').slice(0, 80);
              meetingPick.appendChild(opt);
            });
            if (prev) {
              meetingPick.value = prev;
              if (meetingPick.value !== prev) meetingPick.value = '__all__';
            } else {
              meetingPick.value = '__all__';
            }
          });
        }

        function openEdit(it) {
          editingId = it.id;
          editTitle.value = it.title || '';
          editDetail.value = it.detail || '';
          editModal.hidden = false;
          editTitle.focus();
        }

        function closeEdit() {
          editingId = null;
          editModal.hidden = true;
        }

        function openCompleteModal(it) {
          completePendingId = it.id;
          completePreviewEl.textContent = it.title || '';
          // 이전에 저장한 처리 내용 유지(완료 취소 후 재완료 시에도 동일)
          completeNoteEl.value = it.completionNote ? String(it.completionNote) : '';
          completeModal.hidden = false;
          completeNoteEl.focus();
        }

        function closeCompleteModal() {
          completePendingId = null;
          completeModal.hidden = true;
        }

        function dateSortKey(it) {
          var s = it.meetingDate && String(it.meetingDate).slice(0, 10);
          if (!s || !/^\d{4}-\d{2}-\d{2}$/.test(s)) return '\uffff';
          return s;
        }

        function titleSortKey(it) {
          return (it.title || '').trim();
        }

        function sortItems(items, mode) {
          var arr = items.slice();
          if (mode === 'date') {
            arr.sort(function (a, b) {
              var d = dateSortKey(a).localeCompare(dateSortKey(b));
              if (d !== 0) return d;
              return titleSortKey(a).localeCompare(titleSortKey(b), 'ko');
            });
          } else if (mode === 'alpha') {
            arr.sort(function (a, b) {
              return titleSortKey(a).localeCompare(titleSortKey(b), 'ko');
            });
          } else {
            arr.sort(function (a, b) {
              var da = a.completed ? 0 : 1;
              var db = b.completed ? 0 : 1;
              if (da !== db) return da - db;
              var cmpD = dateSortKey(a).localeCompare(dateSortKey(b));
              if (cmpD !== 0) return cmpD;
              return titleSortKey(a).localeCompare(titleSortKey(b), 'ko');
            });
          }
          return arr;
        }

        function updateSortButtonsActive() {
          document.querySelectorAll('.tcl-sort-btn').forEach(function (btn) {
            var on = btn.getAttribute('data-sort') === sortMode;
            btn.classList.toggle('tcl-sort-btn-active', on);
            btn.setAttribute('aria-pressed', on ? 'true' : 'false');
          });
        }

        function renderItem(it) {
          var li = document.createElement('li');
          li.className = 'tcl-item' + (it.completed ? ' tcl-item-done' : '');
          li.dataset.id = it.id;

          var row = document.createElement('div');
          row.className = 'tcl-item-row';

          var cb = document.createElement('input');
          cb.type = 'checkbox';
          cb.className = 'tcl-checkbox';
          cb.checked = !!it.completed;
          cb.setAttribute('aria-label', '완료');
          cb.addEventListener('change', function () {
            if (!cb.checked) {
              api('/api/task-checklist/items/' + encodeURIComponent(it.id), {
                method: 'PATCH',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ completed: false })
              })
                .then(function () {
                  loadItems();
                })
                .catch(function (e) {
                  alert(e.message || '저장 실패');
                  cb.checked = !cb.checked;
                });
              return;
            }
            cb.checked = false;
            openCompleteModal(it);
          });

          var body = document.createElement('div');
          body.className = 'tcl-item-body';

          var hasMeetingMeta = it.meetingId && (it.meetingTitle || it.meetingDate || it.meetingSummary);

          if (hasMeetingMeta) {
            var wrap = document.createElement('div');
            wrap.className = 'tcl-tooltip-wrap';
            wrap.setAttribute('tabindex', '0');
            var tipId = 'tcl-tip-' + it.id;
            var titleEl = document.createElement('div');
            titleEl.className = 'tcl-item-title';
            titleEl.textContent = it.title || '';
            wrap.appendChild(titleEl);

            var pop = document.createElement('div');
            pop.className = 'tcl-popup';
            pop.id = tipId;
            pop.setAttribute('role', 'tooltip');
            wrap.setAttribute('aria-describedby', tipId);

            function addRow(label, text) {
              if (!text) return;
              var row = document.createElement('div');
              row.className = 'tcl-popup-block';
              var lb = document.createElement('div');
              lb.className = 'tcl-popup-label';
              lb.textContent = label;
              var val = document.createElement('div');
              val.className = 'tcl-popup-value';
              val.textContent = text;
              row.appendChild(lb);
              row.appendChild(val);
              pop.appendChild(row);
            }

            addRow('회의 제목', it.meetingTitle || '');
            addRow('회의 일자', it.meetingDate || '—');
            if (it.meetingSummary && String(it.meetingSummary).trim()) {
              addRow('회의 요약', String(it.meetingSummary).trim());
            }

            wrap.appendChild(pop);
            body.appendChild(wrap);
          } else {
            var titlePlain = document.createElement('div');
            titlePlain.className = 'tcl-item-title';
            titlePlain.textContent = it.title || '';
            body.appendChild(titlePlain);
          }

          var meta = [];
          if (it.assignee) meta.push('담당: ' + it.assignee);
          if (it.dueNote) meta.push('기한: ' + it.dueNote);
          if (it.detail) meta.push(it.detail);
          if (it.completionNote) {
            meta.push((it.completed ? '처리 내용: ' : '이전 완료 처리: ') + it.completionNote);
          }
          if (meta.length) {
            var sub = document.createElement('div');
            sub.className = 'tcl-item-meta';
            sub.textContent = meta.join(' · ');
            body.appendChild(sub);
          }

          var actions = document.createElement('div');
          actions.className = 'tcl-item-actions';

          var btnEdit = document.createElement('button');
          btnEdit.type = 'button';
          btnEdit.className = 'tcl-btn-outline';
          btnEdit.textContent = '수정';
          btnEdit.addEventListener('click', function () {
            openEdit(it);
          });

          var btnDel = document.createElement('button');
          btnDel.type = 'button';
          btnDel.className = 'tcl-btn-outline tcl-btn-outline-danger';
          btnDel.textContent = '삭제';
          btnDel.addEventListener('click', function () {
            if (!confirm('이 항목을 삭제할까요?')) return;
            api('/api/task-checklist/items/' + encodeURIComponent(it.id), { method: 'DELETE' })
              .then(loadItems)
              .catch(function (e) {
                alert(e.message || '삭제 실패');
              });
          });

          actions.appendChild(btnEdit);
          actions.appendChild(btnDel);

          row.appendChild(cb);
          row.appendChild(body);
          row.appendChild(actions);
          li.appendChild(row);
          return li;
        }

        function loadItems() {
          var v = filterEl.value;
          var parts = [];
          if (v === 'open') parts.push('completed=false');
          else if (v === 'done') parts.push('completed=true');
          var mid = meetingPick.value;
          if (mid && mid !== '__all__') parts.push('meetingId=' + encodeURIComponent(mid));
          var q = parts.length ? '?' + parts.join('&') : '';
          return api('/api/task-checklist/items' + q).then(function (d) {
            var items = sortItems(d.items || [], sortMode);
            listEl.innerHTML = '';
            emptyEl.hidden = items.length > 0;
            items.forEach(function (it) {
              listEl.appendChild(renderItem(it));
            });
          });
        }

        function importUrlsForScope() {
          var mid = meetingPick.value;
          return {
            checklist:
              mid === '__all__'
                ? '/api/task-checklist/import-all'
                : '/api/task-checklist/import/' + encodeURIComponent(mid),
            actions:
              mid === '__all__'
                ? '/api/task-checklist/import-all?mode=actions'
                : '/api/task-checklist/import/' + encodeURIComponent(mid) + '?mode=actions',
          };
        }

        /** 선택한 회의록 범위에서 체크리스트·액션 가져오기(병렬). 실패는 콘솔만. */
        function importChecklistAndActions() {
          var u = importUrlsForScope();
          return Promise.allSettled([
            api(u.checklist, { method: 'POST' }),
            api(u.actions, { method: 'POST' }),
          ]).then(function (results) {
            if (results[0].status === 'rejected') {
              console.warn('체크리스트 가져오기:', results[0].reason && results[0].reason.message);
            }
            if (results[1].status === 'rejected') {
              console.warn('액션 가져오기:', results[1].reason && results[1].reason.message);
            }
            return loadItems();
          });
        }

        filterEl.addEventListener('change', importChecklistAndActions);
        meetingPick.addEventListener('change', importChecklistAndActions);

        document.querySelectorAll('.tcl-sort-btn').forEach(function (btn) {
          btn.addEventListener('click', function () {
            var m = btn.getAttribute('data-sort');
            if (!m || m === sortMode) return;
            sortMode = m;
            updateSortButtonsActive();
            loadItems();
          });
        });
        updateSortButtonsActive();

        document.getElementById('tclEditSave').addEventListener('click', function () {
          if (!editingId) return;
          var title = editTitle.value.trim();
          if (!title) {
            alert('제목을 입력해 주세요.');
            return;
          }
          api('/api/task-checklist/items/' + encodeURIComponent(editingId), {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ title: title, detail: editDetail.value.trim() || null })
          })
            .then(function () {
              closeEdit();
              loadItems();
            })
            .catch(function (e) {
              alert(e.message || '저장 실패');
            });
        });

        document.getElementById('tclEditCancel').addEventListener('click', closeEdit);
        document.getElementById('tclEditBackdrop').addEventListener('click', closeEdit);

        document.getElementById('tclCompleteSave').addEventListener('click', function () {
          if (!completePendingId) return;
          var note = completeNoteEl.value.trim();
          if (!note) {
            alert('처리 내용을 입력해 주세요.');
            return;
          }
          api('/api/task-checklist/items/' + encodeURIComponent(completePendingId), {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ completed: true, completionNote: note })
          })
            .then(function () {
              closeCompleteModal();
              loadItems();
            })
            .catch(function (e) {
              alert(e.message || '저장 실패');
            });
        });
        document.getElementById('tclCompleteCancel').addEventListener('click', closeCompleteModal);
        document.getElementById('tclCompleteBackdrop').addEventListener('click', closeCompleteModal);

        document.addEventListener('keydown', function (e) {
          if (e.key !== 'Escape') return;
          if (!completeModal.hidden) {
            closeCompleteModal();
            e.preventDefault();
            return;
          }
          if (!editModal.hidden) closeEdit();
        });

        loadMeetingsDropdown().then(importChecklistAndActions);
      })();
    </script>
    <% } %>
  </body>
</html>
