package com.cloudhandson.ddsbackoffice.web;

import com.cloudhandson.ddsbackoffice.service.DdsQueryService;
import com.cloudhandson.ddsbackoffice.service.DdsVectorKnowledgeService;
import com.cloudhandson.vpdbackoffice.domain.vector.VectorIngestCommand;
import com.cloudhandson.vpdbackoffice.service.AppException;
import com.cloudhandson.vpdbackoffice.service.BearerTokenService;
import com.cloudhandson.vpdbackoffice.service.UserService;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.UUID;

@Controller
public class DdsVectorKnowledgeController {

  private final DdsVectorKnowledgeService service;
  private final DdsQueryService ddsQueryService;
  private final UserService userService;
  private final BearerTokenService bearerTokenService;

  public DdsVectorKnowledgeController(
      DdsVectorKnowledgeService service,
      DdsQueryService ddsQueryService, UserService userService, BearerTokenService bearerTokenService
  ) {
    this.service = service;
    this.ddsQueryService = ddsQueryService;
    this.userService = userService;
    this.bearerTokenService = bearerTokenService;
  }

  @GetMapping("/vector-knowledge")
  public String page(Model model) {
    populatePage(model);
    return "vector-knowledge";
  }

  @PostMapping("/vector-knowledge/ingest")
  public String ingest(
      @RequestParam(required = false, defaultValue = "") String documentId,
      @RequestParam String title,
      @RequestParam(required = false, defaultValue = "") String sourceUri,
      @RequestParam String content,
      @RequestParam String techTags,
      @RequestParam(defaultValue = "600") int chunkSize,
      @RequestParam(defaultValue = "DEMO") String embeddingMode,
      @RequestParam(defaultValue = "false") boolean replaceExisting,
      RedirectAttributes redirectAttributes
  ) {
    try {
      var result = service.ingest(new VectorIngestCommand(
          resolveDocumentId(documentId, replaceExisting), title, sourceUri, content, techTags, chunkSize, embeddingMode));
      redirectAttributes.addFlashAttribute("ingestResult", result);
      redirectAttributes.addFlashAttribute("message",
          "지식자료를 등록하고 검색 준비를 완료했습니다.");
    } catch (Exception exception) {
      redirectAttributes.addFlashAttribute("errorMessage", exception.getMessage());
    }
    return "redirect:/vector-knowledge";
  }

  private String resolveDocumentId(String documentId, boolean replaceExisting) {
    if (documentId == null || documentId.isBlank()) {
      return "knowledge-" + UUID.randomUUID();
    }
    if (!replaceExisting) {
      throw new AppException("기존 자료를 교체하려면 교체 확인을 선택하세요.");
    }
    return documentId.trim();
  }

  @PostMapping("/vector-knowledge/search")
  public String search(
      @RequestParam String userKey,
      @RequestParam String query,
      @RequestParam(defaultValue = "10") int limit,
      @RequestParam(defaultValue = "DEMO") String embeddingMode,
      Model model
  ) {
    try {
      model.addAttribute("searchResult", service.search(userKey, query, limit, embeddingMode));
    } catch (AppException | IllegalArgumentException exception) {
      model.addAttribute("errorMessage", exception.getMessage());
    }
    return "fragments/dds-vector-search-result :: result";
  }

  @PostMapping("/vector-knowledge/token-search")
  public String tokenSearch(
      @RequestParam String bearerToken,
      @RequestParam String query,
      @RequestParam(defaultValue = "10") int limit,
      @RequestParam(defaultValue = "DEMO") String embeddingMode,
      Model model
  ) {
    try {
      model.addAttribute("searchResult",
          service.searchByToken(bearerToken, query, limit, embeddingMode));
    } catch (AppException | IllegalArgumentException exception) {
      model.addAttribute("errorMessage", exception.getMessage());
    }
    return "fragments/dds-vector-search-result :: result";
  }

  @PostMapping("/vector-knowledge/user-search")
  public String userSearch(@RequestParam long userId, @RequestParam String query,
      @RequestParam(defaultValue = "10") int limit, @RequestParam(defaultValue = "DEMO") String embeddingMode,
      Model model) {
    var token = bearerTokenService.issueTemporaryToken(userId, "DDS 업무 사용자 검증");
    try { model.addAttribute("searchResult", service.searchByToken(token.plainToken(), query, limit, embeddingMode)); }
    finally { bearerTokenService.revokeToken(token.keyId(), "DDS 업무 사용자 검증 완료"); }
    return "fragments/dds-vector-search-result :: result";
  }

  private void populatePage(Model model) {
    try {
      model.addAttribute("summary", service.summary());
      model.addAttribute("aiEmbeddingConfigured", service.aiEmbeddingConfigured());
      model.addAttribute("tokenSearchAvailable", service.tokenSearchAvailable());
    } catch (DataAccessException exception) {
      model.addAttribute("summary", null);
      model.addAttribute("runtimeError", exception.getMessage());
      model.addAttribute("aiEmbeddingConfigured", false);
      model.addAttribute("tokenSearchAvailable", false);
    }
    model.addAttribute("ddsUsers", ddsQueryService.users());
    model.addAttribute("appUsers", userService.findAll().stream().filter(user -> "Y".equals(user.activeYn())).toList());
    model.addAttribute("ddsVectorObject", ddsQueryService.vectorObject());
  }
}
