<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" language="java" %>
<%@ page import="org.springframework.web.util.HtmlUtils" %>
<%@ page import="com.pandoli365.bibimbap.data.UnityFeedSourceData" %>
<%@ page import="com.pandoli365.bibimbap.data.UnityFeedItemData" %>
<%@ page import="java.util.Collections" %>
<%@ page import="java.util.List" %>
<%
    String ctx = request.getContextPath();
    List<UnityFeedSourceData> sources = Collections.emptyList();
    Object sourcesAttr = request.getAttribute("sources");
    if (sourcesAttr instanceof List<?>) { sources = (List<UnityFeedSourceData>) sourcesAttr; }
    List<UnityFeedItemData> unackItems = Collections.emptyList();
    Object unackItemsAttr = request.getAttribute("unackItems");
    if (unackItemsAttr instanceof List<?>) { unackItems = (List<UnityFeedItemData>) unackItemsAttr; }
    Object unackCountAttr = request.getAttribute("unackCount");
    String unackCount = unackCountAttr == null ? "0" : String.valueOf(unackCountAttr);
    String csrfToken = (String) request.getAttribute("csrfToken");
    String csrfTokenHtml = HtmlUtils.htmlEscape(csrfToken == null ? "" : csrfToken);
%>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="_csrf" content="<%= csrfTokenHtml %>">
    <jsp:include page="/WEB-INF/views/theme-init.jsp"/>
    <title>Unity 피드 관리 | bibimbap</title>
    <style>
      html {
        color-scheme: light;
        --surface: #faf8f5;
        --card-bg: #fff;
        --text: #1a1a1a;
        --text-muted: #5c5c5c;
        --accent: #e8a54b;
        --accent-soft: rgba(232, 165, 75, 0.16);
        --border: rgba(0, 0, 0, 0.08);
        --shadow: rgba(0, 0, 0, 0.06);
        --field-bg: #fff;
        --button-text: #1a1a1a;
        --danger: #c83c3c;
      }
      html[data-theme="dark"] {
        color-scheme: dark;
        --surface: #121212;
        --card-bg: #1e1e1e;
        --text: #ece8e1;
        --text-muted: #a39e96;
        --border: rgba(255, 255, 255, 0.1);
        --shadow: rgba(0, 0, 0, 0.35);
        --field-bg: #181818;
        --button-text: #1a1a1a;
        --danger: #ef7878;
      }
      body {
        margin: 0;
        min-height: 100vh;
        font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans KR", sans-serif;
        background: var(--surface);
        color: var(--text);
      }
      .admin-page {
        max-width: 78rem;
        margin: 0 auto;
        padding: 1.5rem max(1rem, env(safe-area-inset-left)) 3rem max(1rem, env(safe-area-inset-right));
      }
      .admin-hero { margin-bottom: 1.5rem; }
      .admin-hero__eyebrow {
        margin: 0 0 0.35rem;
        color: var(--accent);
        font-size: 0.75rem;
        font-weight: 900;
      }
      .admin-hero h1 { margin: 0; font-size: 1.9rem; line-height: 1.2; }
      .admin-hero p { margin: 0.45rem 0 0; color: var(--text-muted); line-height: 1.6; }
      .admin-section {
        margin-bottom: 2rem;
        padding: 1.25rem;
        border: 1px solid var(--border);
        border-radius: 12px;
        background: var(--card-bg);
        box-shadow: 0 2px 8px var(--shadow);
      }
      .admin-section h2 { margin: 0 0 1rem; font-size: 1.15rem; }
      .admin-section__head {
        display: flex;
        align-items: center;
        gap: 0.6rem;
        margin: 0 0 1rem;
      }
      .admin-section__head h2 { margin: 0; }
      .admin-form-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
        gap: 0.9rem;
      }
      .admin-field { display: grid; gap: 0.375rem; }
      .admin-field--full { grid-column: 1 / -1; }
      .admin-field label { font-size: 0.8125rem; font-weight: 700; color: var(--text); }
      .admin-field input {
        box-sizing: border-box;
        height: 3rem;
        padding: 0.7rem 0.875rem;
        border: 1px solid var(--border);
        border-radius: 12px;
        background: var(--field-bg);
        color: var(--text);
        font: inherit;
        font-size: 1rem;
      }
      .admin-form-actions { margin-top: 1rem; display: flex; gap: 0.5rem; flex-wrap: wrap; }
      .admin-table-wrap { overflow-x: auto; }
      .admin-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
      .admin-table th, .admin-table td {
        padding: 0.65rem 0.5rem;
        border-bottom: 1px solid var(--border);
        text-align: left;
        vertical-align: top;
      }
      .admin-table th {
        color: var(--text-muted);
        font-size: 0.8125rem;
        font-weight: 800;
        white-space: nowrap;
      }
      .admin-table td a { color: var(--accent); word-break: break-all; }
      .admin-actions { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
      .admin-btn {
        min-height: 2.25rem;
        padding: 0 0.85rem;
        border: 1px solid var(--border);
        border-radius: 10px;
        background: var(--card-bg);
        color: var(--text);
        font: inherit;
        font-size: 0.8125rem;
        font-weight: 800;
        cursor: pointer;
      }
      .admin-btn:hover { border-color: rgba(232, 165, 75, 0.45); }
      .admin-btn--primary { border-color: transparent; background: var(--accent); color: var(--button-text); }
      .admin-btn--danger { border-color: rgba(200, 60, 60, 0.45); color: var(--danger); }
      .admin-muted { color: var(--text-muted); font-size: 0.8125rem; }
      .admin-error { color: var(--danger); font-size: 0.8125rem; }
      .admin-status {
        display: inline-flex;
        align-items: center;
        padding: 0.15rem 0.55rem;
        border-radius: 999px;
        background: var(--accent-soft);
        color: var(--accent);
        font-size: 0.75rem;
        font-weight: 800;
      }
      .admin-badge {
        display: inline-flex;
        align-items: center;
        min-width: 1.5rem;
        justify-content: center;
        padding: 0.1rem 0.5rem;
        border-radius: 999px;
        background: var(--danger);
        color: #fff;
        font-size: 0.75rem;
        font-weight: 900;
      }
    </style>
</head>
<body>
    <jsp:include page="/WEB-INF/views/header.jsp"/>
    <main class="admin-page">
        <section class="admin-hero">
            <p class="admin-hero__eyebrow">UNITY FEED ADMIN</p>
            <h1>Unity 피드 관리</h1>
            <p>Unity 관련 외부 피드 소스를 등록하고 폴링하여 미확인 항목을 검토합니다. 피드 URL 은 등록 시 SSRF 안전성을 검증합니다.</p>
        </section>

        <section class="admin-section">
            <h2>신규 피드 소스 등록</h2>
            <form id="source-create-form" autocomplete="off">
                <input type="hidden" name="_csrf" value="<%= csrfTokenHtml %>" />
                <div class="admin-form-grid">
                    <div class="admin-field">
                        <label for="src-name">이름 (필수)</label>
                        <input type="text" id="src-name" name="name" maxlength="120" placeholder="피드 이름" required />
                    </div>
                    <div class="admin-field admin-field--full">
                        <label for="src-url">피드 URL (필수)</label>
                        <input type="url" id="src-url" name="feedUrl" maxlength="2048" placeholder="https://example.com/feed.xml" required />
                    </div>
                </div>
                <div class="admin-form-actions">
                    <button class="admin-btn admin-btn--primary" type="submit" data-action="create">피드 등록</button>
                    <button class="admin-btn" type="button" data-action="poll">지금 폴링</button>
                </div>
            </form>
        </section>

        <section class="admin-section">
            <h2>피드 소스 목록</h2>
            <div class="admin-table-wrap">
                <table class="admin-table">
                    <thead>
                        <tr>
                            <th scope="col">이름</th>
                            <th scope="col">피드 URL</th>
                            <th scope="col">활성</th>
                            <th scope="col">최근 오류</th>
                            <th scope="col">액션</th>
                        </tr>
                    </thead>
                    <tbody>
                        <% if (sources.isEmpty()) { %>
                            <tr>
                                <td colspan="5"><span class="admin-muted">등록된 피드 소스가 없습니다.</span></td>
                            </tr>
                        <% } else {
                            for (UnityFeedSourceData src : sources) {
                                boolean srcActive = Boolean.TRUE.equals(src.getIsActive());
                                boolean hasError = src.getLastError() != null && !src.getLastError().isBlank();
                        %>
                            <tr>
                                <td><%= HtmlUtils.htmlEscape(src.getName() == null ? "" : src.getName()) %></td>
                                <td><%= HtmlUtils.htmlEscape(src.getFeedUrl() == null ? "" : src.getFeedUrl()) %></td>
                                <td>
                                    <% if (srcActive) { %><span class="admin-status">활성</span><% } else { %><span class="admin-muted">비활성</span><% } %>
                                </td>
                                <td>
                                    <% if (hasError) { %>
                                        <span class="admin-error"><%= HtmlUtils.htmlEscape(src.getLastError()) %></span>
                                    <% } else { %><span class="admin-muted">-</span><% } %>
                                </td>
                                <td>
                                    <div class="admin-actions">
                                        <button class="admin-btn" type="button"
                                                data-action="toggle"
                                                data-src-id="<%= src.getId() %>">
                                            <%= srcActive ? "비활성화" : "활성화" %>
                                        </button>
                                        <button class="admin-btn admin-btn--danger" type="button"
                                                data-action="delete"
                                                data-src-id="<%= src.getId() %>">삭제</button>
                                    </div>
                                </td>
                            </tr>
                        <%      }
                           } %>
                    </tbody>
                </table>
            </div>
        </section>

        <section class="admin-section">
            <div class="admin-section__head">
                <h2>미확인 항목</h2>
                <span class="admin-badge"><%= HtmlUtils.htmlEscape(unackCount) %></span>
            </div>
            <div class="admin-table-wrap">
                <table class="admin-table">
                    <thead>
                        <tr>
                            <th scope="col">제목</th>
                            <th scope="col">소스</th>
                            <th scope="col">감지 시각</th>
                            <th scope="col">액션</th>
                        </tr>
                    </thead>
                    <tbody>
                        <% if (unackItems.isEmpty()) { %>
                            <tr>
                                <td colspan="4"><span class="admin-muted">미확인 항목이 없습니다.</span></td>
                            </tr>
                        <% } else {
                            for (UnityFeedItemData item : unackItems) {
                                String itemDetectedAt = item.getDetectedAt() == null ? "" : String.valueOf(item.getDetectedAt());
                        %>
                            <tr>
                                <td>
                                    <a href="<%= HtmlUtils.htmlEscape(item.getLinkUrl() == null ? "" : item.getLinkUrl()) %>"
                                       target="_blank" rel="nofollow noopener"><%= HtmlUtils.htmlEscape(item.getTitle() == null ? "" : item.getTitle()) %></a>
                                </td>
                                <td><%= HtmlUtils.htmlEscape(item.getSourceName() == null ? "" : item.getSourceName()) %></td>
                                <td><%= HtmlUtils.htmlEscape(itemDetectedAt) %></td>
                                <td>
                                    <button class="admin-btn" type="button"
                                            data-action="ack"
                                            data-item-id="<%= item.getId() %>">확인</button>
                                </td>
                            </tr>
                        <%      }
                           } %>
                    </tbody>
                </table>
            </div>
        </section>
    </main>
    <jsp:include page="/WEB-INF/views/footer.jsp"/>
    <script>
(function () {
  var meta = document.querySelector('meta[name="_csrf"]');
  var CSRF_TOKEN = meta ? meta.getAttribute('content') : '';
  var BASE = '/admin/unity-feeds';

  function notify(message) {
    if (window.BibimbapModal && typeof window.BibimbapModal.alert === 'function') {
      window.BibimbapModal.alert({ title: 'Unity 피드 관리', message: message });
      return;
    }
    alert(message);
  }

  function post(url, params) {
    var options = {
      method: 'POST',
      headers: {
        'X-CSRF-Token': CSRF_TOKEN,
        'Accept': 'application/json'
      }
    };
    if (!params) {
      params = new URLSearchParams();
    }
    params.set('_csrf', CSRF_TOKEN);
    options.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
    options.body = params.toString();
    return fetch(url, options);
  }

  function handleResultWithMessage(res, okMessage) {
    res.json().then(function (data) {
      var message = (data && data.message) ? data.message : null;
      if (res.ok) {
        notify(okMessage || message || '처리되었습니다.');
        window.location.reload();
        return;
      }
      notify(message || ('요청을 처리하지 못했습니다. (상태 ' + res.status + ')'));
    }).catch(function () {
      if (res.ok) {
        window.location.reload();
        return;
      }
      notify('요청을 처리하지 못했습니다. (상태 ' + res.status + ')');
    });
  }

  function reloadOnOk(res) {
    if (res.ok) {
      window.location.reload();
      return;
    }
    res.json().then(function (data) {
      notify((data && data.message) ? data.message : ('요청을 처리하지 못했습니다. (상태 ' + res.status + ')'));
    }).catch(function () {
      notify('요청을 처리하지 못했습니다. (상태 ' + res.status + ')');
    });
  }

  function handleError() {
    notify('요청 중 오류가 발생했습니다.');
  }

  function createSource() {
    var name = (document.getElementById('src-name').value || '').trim();
    var url = (document.getElementById('src-url').value || '').trim();
    if (!name || !url) {
      notify('이름과 피드 URL 을 입력해 주세요.');
      return;
    }
    var params = new URLSearchParams();
    params.set('name', name);
    params.set('feedUrl', url);
    post(BASE, params).then(reloadOnOk).catch(handleError);
  }

  function pollNow() {
    post(BASE + '/poll').then(function (res) {
      res.json().then(function (data) {
        if (res.ok) {
          var count = (data && typeof data.newCount === 'number') ? data.newCount : 0;
          notify('폴링 완료: 신규 ' + count + '건');
          window.location.reload();
          return;
        }
        notify((data && data.message) ? data.message : ('폴링에 실패했습니다. (상태 ' + res.status + ')'));
      }).catch(function () {
        if (res.ok) {
          window.location.reload();
          return;
        }
        notify('폴링에 실패했습니다. (상태 ' + res.status + ')');
      });
    }).catch(handleError);
  }

  function toggleSource(id) {
    post(BASE + '/' + encodeURIComponent(id) + '/toggle').then(reloadOnOk).catch(handleError);
  }

  function removeSource(id) {
    if (!window.confirm('이 피드 소스를 삭제하시겠습니까?')) {
      return;
    }
    post(BASE + '/' + encodeURIComponent(id) + '/delete').then(reloadOnOk).catch(handleError);
  }

  function ackItem(itemId) {
    post(BASE + '/items/' + encodeURIComponent(itemId) + '/ack').then(reloadOnOk).catch(handleError);
  }

  var form = document.getElementById('source-create-form');
  if (form) {
    form.addEventListener('submit', function (ev) {
      ev.preventDefault();
      createSource();
    });
  }

  document.addEventListener('click', function (ev) {
    var btn = ev.target.closest('[data-action]');
    if (!btn) {
      return;
    }
    var action = btn.getAttribute('data-action');
    if (action === 'poll') {
      ev.preventDefault();
      pollNow();
      return;
    }
    var srcId = btn.getAttribute('data-src-id');
    var itemId = btn.getAttribute('data-item-id');
    if (action === 'toggle' && srcId) {
      toggleSource(srcId);
    } else if (action === 'delete' && srcId) {
      removeSource(srcId);
    } else if (action === 'ack' && itemId) {
      ackItem(itemId);
    }
  });
})();
    </script>
</body>
</html>
