package com.davos.assessment.legal;

import com.davos.assessment.project.Project;
import com.davos.assessment.project.ProjectAccessService;
import com.davos.assessment.user.AppUser;
import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class LegalService {
  private final ConsentLogRepository consentLogRepository;
  private final LegalDocumentRepository legalDocumentRepository;
  private final ProjectAccessService projectAccessService;
  private final String userAgreementVersion;
  private final String privacyPolicyVersion;
  private final String assessmentAuthorizationVersion;

  public LegalService(
      ConsentLogRepository consentLogRepository,
      LegalDocumentRepository legalDocumentRepository,
      ProjectAccessService projectAccessService,
      @Value("${app.legal.user-agreement-version:V1.0}") String userAgreementVersion,
      @Value("${app.legal.privacy-policy-version:V1.0}") String privacyPolicyVersion,
      @Value("${app.legal.assessment-authorization-version:V1.0}") String assessmentAuthorizationVersion) {
    this.consentLogRepository = consentLogRepository;
    this.legalDocumentRepository = legalDocumentRepository;
    this.projectAccessService = projectAccessService;
    this.userAgreementVersion = userAgreementVersion;
    this.privacyPolicyVersion = privacyPolicyVersion;
    this.assessmentAuthorizationVersion = assessmentAuthorizationVersion;
  }

  public LegalVersions versions() {
    return new LegalVersions(userAgreementVersion, privacyPolicyVersion, assessmentAuthorizationVersion);
  }

  public LegalBundle currentBundle() {
    return currentBundle(projectAccessService.currentProjectOrDefault());
  }

  public LegalBundle currentBundle(Project project) {
    return new LegalBundle(
        currentDocument(project, LegalDocumentType.USER_AGREEMENT),
        currentDocument(project, LegalDocumentType.PRIVACY_POLICY));
  }

  public LegalDocumentView currentDocument(LegalDocumentType type) {
    return currentDocument(projectAccessService.currentProjectOrDefault(), type);
  }

  public LegalDocumentView currentDocument(Project project, LegalDocumentType type) {
    try {
      LegalDocument doc = legalDocumentRepository.findByProjectAndDocType(project, type).orElseGet(() -> {
        LegalDocument item = new LegalDocument();
        item.setProject(project);
        item.setDocType(type);
        item.setVersion("V1.0");
        item.setTitle(type == LegalDocumentType.USER_AGREEMENT ? "用户协议" : "隐私条款");
        item.setContentMd(type == LegalDocumentType.USER_AGREEMENT
            ? "# 用户协议\n\n请在管理员后台完善用户协议内容。"
            : "# 隐私条款\n\n请在管理员后台完善隐私条款内容。");
        item.setUpdatedAt(Instant.now());
        return legalDocumentRepository.save(item);
      });
      return toView(doc);
    } catch (RuntimeException ex) {
      return new LegalDocumentView(
          type.name(),
          type == LegalDocumentType.USER_AGREEMENT ? "用户协议" : "隐私条款",
          "V1.0",
          type == LegalDocumentType.USER_AGREEMENT ? "# 用户协议\n\n内容暂未初始化。" : "# 隐私条款\n\n内容暂未初始化。",
          Instant.now().toString());
    }
  }

  public LegalDocumentView saveDocument(AppUser operator, LegalDocumentType type, String title, String version, String contentMd) {
    return saveDocument(projectAccessService.currentProjectOrDefault(), operator, type, title, version, contentMd);
  }

  public LegalDocumentView saveDocument(Project project, AppUser operator, LegalDocumentType type, String title, String version, String contentMd) {
    LegalDocument doc = legalDocumentRepository.findByProjectAndDocType(project, type).orElseGet(() -> {
      LegalDocument item = new LegalDocument();
      item.setProject(project);
      item.setDocType(type);
      return item;
    });
    doc.setTitle(title.trim());
    doc.setVersion(version.trim());
    doc.setContentMd(contentMd);
    doc.setUpdatedBy(operator);
    doc.setUpdatedAt(Instant.now());
    LegalDocument saved = legalDocumentRepository.save(doc);
    return toView(saved);
  }

  public List<ConsentRow> listConsentRows(String email) {
    return listConsentRows(projectAccessService.currentProjectOrDefault(), email);
  }

  public List<ConsentRow> listConsentRows(Project project, String email) {
    String keyword = email == null ? "" : email.trim();
    return java.util.stream.Stream.of(ConsentType.USER_AGREEMENT, ConsentType.PRIVACY_POLICY)
        .flatMap(type -> consentLogRepository.findConsentRows(project, type, keyword).stream())
        .sorted((a, b) -> b.getCreatedAt().compareTo(a.getCreatedAt()))
        .map(item -> new ConsentRow(
            item.getId(),
            item.getUser().getId(),
            item.getUser().getEmail(),
            item.getConsentType().name(),
            item.getConsentVersion(),
            item.isGranted(),
            item.getIpAddress(),
            item.getCreatedAt().toString()))
        .toList();
  }

  public void record(AppUser user, ConsentType type, String version, boolean granted, HttpServletRequest request) {
    record(projectAccessService.currentProjectOrDefault(), user, type, version, granted, request);
  }

  public void record(Project project, AppUser user, ConsentType type, String version, boolean granted, HttpServletRequest request) {
    ConsentLog log = new ConsentLog();
    log.setProject(project);
    log.setUser(user);
    log.setConsentType(type);
    log.setConsentVersion(version);
    log.setGranted(granted);
    log.setIpAddress(clientIp(request));
    log.setUserAgent(safe(request.getHeader("User-Agent")));
    log.setCreatedAt(Instant.now());
    consentLogRepository.save(log);
  }

  public void requireGranted(AppUser user, ConsentType type, String version) {
    requireGranted(projectAccessService.currentProjectOrDefault(), user, type, version);
  }

  public void requireGranted(Project project, AppUser user, ConsentType type, String version) {
    boolean ok = consentLogRepository.existsByProjectAndUserAndConsentTypeAndConsentVersionAndGrantedTrue(project, user, type, version);
    if (!ok) {
      throw new com.davos.assessment.common.ApiException(
          org.springframework.http.HttpStatus.BAD_REQUEST,
          "请先完成协议授权确认后再继续");
    }
  }

  private String clientIp(HttpServletRequest request) {
    String xff = request.getHeader("X-Forwarded-For");
    if (xff != null && !xff.isBlank()) return xff.split(",")[0].trim();
    return safe(request.getRemoteAddr());
  }

  private String safe(String value) {
    return value == null ? "" : value;
  }

  private LegalDocumentView toView(LegalDocument doc) {
    return new LegalDocumentView(
        doc.getDocType().name(),
        doc.getTitle(),
        doc.getVersion(),
        doc.getContentMd(),
        doc.getUpdatedAt().toString());
  }

  public record LegalVersions(String userAgreementVersion, String privacyPolicyVersion, String assessmentAuthorizationVersion) {}
  public record LegalDocumentView(String type, String title, String version, String contentMd, String updatedAt) {}
  public record LegalBundle(LegalDocumentView userAgreement, LegalDocumentView privacyPolicy) {}
  public record ConsentRow(Long id, Long userId, String email, String consentType, String version, boolean granted, String ipAddress, String createdAt) {}
}
