<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/layout :: head('지식 검색')}"></head>
<body>
<nav th:replace="~{fragments/layout :: nav}"></nav>
<main class="container py-4">
  <div class="page-title">
    <h1>지식 검색</h1>
    <details class="explanation-details">
      <summary>도움말</summary>
      <p>문서는 검색 단위로 나누고 각 단위를 임베딩으로 변환합니다. 기술 태그는 접근 정책의 <code>TAG</code> 조건으로 사용되며, 검색 시 DB 보호 정책이 허용된 지식자료만 남깁니다. <code>Bearer Token</code>은 검증 세션에만 사용되고 검색이 끝나면 폐기됩니다.</p>
    </details>
  </div>

  <div class="alert alert-success" th:if="${message}" th:text="${message}"></div>
  <div class="alert alert-danger" th:if="${errorMessage}" th:text="${errorMessage}"></div>
  <div class="alert alert-warning" th:if="${runtimeError}">
    <strong th:text="${runtimeError.title()}">DB 준비가 필요합니다.</strong>
    <span th:text="${runtimeError.message()}">벡터 테이블을 확인하세요.</span>
  </div>

  <section class="content-band">
    <div class="section-heading">
      <div>
        <h2>지식자료 등록</h2>
        <p class="section-subtitle">같은 문서 ID로 저장하면 최신 내용으로 갱신됩니다.</p>
      </div>
      <span class="badge text-bg-secondary" th:text="${summary == null ? '저장소 확인 필요' : summary.chunkCount() + '개 검색 단위'}">0개 검색 단위</span>
    </div>
    <details class="explanation-details">
      <summary>분할·임베딩 설정 보기</summary>
      <ul>
        <li>문단을 우선 묶고 길이가 길면 문장·공백 기준으로 나눕니다.</li>
        <li><strong>로컬 임베딩(개발용)</strong>(내부 식별자 <code>DEMO-4D</code>)은 외부 API 없이 검색 흐름을 확인하는 4차원 처리 방식입니다. 운영 검색 품질을 위한 모델은 아닙니다.</li>
        <li><strong>AI</strong>는 <code>BACKOFFICE_AI_EMBEDDING_MODEL</code>과 API key가 설정된 OpenAI 호환 <code>/v1/embeddings</code>를 사용합니다.</li>
        <li>운영 환경에서는 자료 등록과 검색에 같은 임베딩 모델과 차원을 사용해야 합니다.</li>
      </ul>
    </details>
    <form method="post" action="/vector-knowledge/ingest" class="form-grid mt-3">
      <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
      <label>
        문서 ID
        <input class="form-control" name="documentId" placeholder="knowledge-security-001" required>
      </label>
      <label>
        문서 제목
        <input class="form-control" name="title" placeholder="VPD와 ORDS 권한 설계" required>
      </label>
      <label>
        원문 주소 (선택)
        <input class="form-control" name="sourceUri" placeholder="kb://security/vpd-ords">
      </label>
      <label>
        기술 태그 (쉼표 또는 공백)
        <input class="form-control" name="techTags" placeholder="SPRING_BOOT ORACLE_VPD" required>
        <span class="form-hint">태그는 대문자로 정규화됩니다. 예: <code>SPRING_BOOT</code>, <code>ORACLE_VPD</code></span>
      </label>
      <label>
        검색 단위 길이
        <input class="form-control" name="chunkSize" type="number" min="80" max="2000" value="600">
      </label>
      <label>
        임베딩 방식
        <select class="form-select" name="embeddingMode">
          <option value="DEMO">로컬 임베딩(개발용)</option>
          <option value="AI" th:disabled="${!aiEmbeddingConfigured}">AI 임베딩 (설정 필요)</option>
        </select>
      </label>
      <label class="span-2">
        문서 본문
        <textarea class="form-control" name="content" rows="8"
                  placeholder="문서 내용을 붙여 넣으세요. 빈 줄은 문단 경계로 사용됩니다." required></textarea>
      </label>
      <button class="btn rw-btn-primary" type="submit">지식자료 저장</button>
    </form>
    <div class="alert alert-info mt-3 mb-0" th:if="${ingestResult}">
      <strong th:text="${ingestResult.documentId()}">document</strong>
      <span th:text="${ingestResult.chunkCount() + '개 검색 단위 / ' + ingestResult.tagCount() + '개 태그 연결 / ' + ingestResult.embeddingModel()}">저장 완료</span>
    </div>
  </section>

  <section class="content-band">
    <div class="section-heading">
      <div>
        <h2>접근 정책 설정</h2>
        <p class="section-subtitle">역할별 기술 태그 행 접근 규칙은 행 접근 규칙 화면에서 관리합니다.</p>
      </div>
      <a class="btn btn-sm rw-btn-primary" href="/permissions">행 접근 규칙 열기</a>
    </div>
    <div class="macro-micro-grid">
      <div>
        <h3>백엔드 지식 접근 정책</h3>
        <p><code>ALLOW TAG SPRING_BOOT</code><br><code>ALLOW TAG ORACLE_VPD</code></p>
        <small class="text-muted">두 태그 중 하나가 붙은 검색 단위를 허용합니다.</small>
      </div>
      <div>
        <h3>ORDS 제외 정책</h3>
        <p><code>ALLOW TAG SPRING_BOOT</code><br><code>DENY TAG ORDS</code></p>
        <small class="text-muted">허용 후보 중 ORDS 태그 검색 단위를 다시 제외합니다.</small>
      </div>
    </div>
    <details class="explanation-details mt-3">
      <summary>접근 정책이 적용되는 방식</summary>
      <pre class="code-block">(ALLOW TAG A OR ALLOW TAG B)
AND NOT (DENY TAG C OR DENY TAG D)</pre>
      <p>허용 태그가 없거나 토큰 컨텍스트가 없으면 <code>1=0</code>으로 닫힙니다. 태그 권한은 행 접근 기준이고, 본문·임베딩 표시 보호는 컬럼 정책으로 별도 관리합니다.</p>
    </details>
  </section>

  <section class="content-band">
    <div class="section-heading">
      <div>
        <h2>권한 기반 지식 검색</h2>
        <p class="section-subtitle">검색 권한 주체에 대한 검증용 세션을 사용하고 완료 후 폐기합니다.</p>
      </div>
      <span class="badge" th:classappend="${summary != null && summary.vectorObjectRegistered()} ? ' text-bg-success' : ' text-bg-warning'"
            th:text="${summary != null && summary.vectorObjectRegistered()} ? '검색 API 연결됨' : '검색 API 설정 필요'">검색 API</span>
    </div>
    <details class="explanation-details">
      <summary>검색 처리 방식 보기</summary>
      <ol>
        <li>검색어를 같은 임베딩 방식으로 벡터화합니다.</li>
        <li>임시 Bearer Token으로 전용 ORDS Handler를 호출합니다.</li>
        <li>행 접근 정책이 TECH_TAG 권한에 맞지 않는 검색 단위를 먼저 제거합니다.</li>
        <li>남은 검색 단위를 관련도 순으로 반환합니다.</li>
      </ol>
    </details>
    <form hx-post="/vector-knowledge/search" hx-target="#vector-search-result" hx-swap="innerHTML" class="form-grid mt-3">
      <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
      <label>
        검색 권한 주체
        <select class="form-select" name="userId" required>
          <option th:each="user : ${users}" th:value="${user.userId()}" th:text="${user.username() + ' / ' + user.deptCode()}"></option>
        </select>
      </label>
      <label>
        결과 수
        <input class="form-control" name="limit" type="number" min="1" max="100" value="10">
      </label>
      <label>
        임베딩 방식
        <select class="form-select" name="embeddingMode">
          <option value="DEMO">로컬 임베딩(개발용)</option>
          <option value="AI" th:disabled="${!aiEmbeddingConfigured}">AI 임베딩</option>
        </select>
      </label>
      <label class="span-2">
        검색 질문
        <textarea class="form-control" name="query" rows="3" placeholder="예: Oracle VPD에서 ORDS 권한을 적용하는 방법" required></textarea>
      </label>
      <button class="btn rw-btn-primary" type="submit">검색 실행</button>
    </form>
    <section id="vector-search-result" class="mt-3" aria-live="polite">
      <div class="empty-result-guide">검색 권한에 따라 허용된 지식자료만 여기에 표시됩니다.</div>
    </section>
  </section>

  <section class="content-band">
    <details class="explanation-details">
      <summary>저장 현황 보기</summary>
      <div class="summary-grid mt-3">
        <div class="summary-tile"><span class="label">문서</span><strong th:text="${summary == null ? '-' : summary.documentCount()}">0</strong></div>
        <div class="summary-tile"><span class="label">검색 단위</span><strong th:text="${summary == null ? '-' : summary.chunkCount()}">0</strong></div>
        <div class="summary-tile"><span class="label">태그 연결</span><strong th:text="${summary == null ? '-' : summary.tagCount()}">0</strong></div>
      </div>
    </details>
  </section>
</main>
</body>
</html>
