package com.cloudhandson.vpdbackoffice.domain.operation;

import com.cloudhandson.vpdbackoffice.domain.masking.MaskingPolicyStatus;
import java.util.List;

/**
 * Page-level health summary computed from the same DB-backed rows shown in
 * operation-status.html. It intentionally does not hide the row-level evidence:
 * the summary is only a triage layer for operators.
 */
public record OperationHealthSummary(
    int protectedObjectCount,
    int rowPolicyOkCount,
    int rowPolicyWarnCount,
    int rowPolicyErrorCount,
    int missingHandlerCount,
    int missingPolicyCount,
    int invalidFunctionCount,
    int unverifiedCount,
    int maskingPolicyCount,
    int maskingAppliedCount,
    int maskingInactiveExpectedCount,
    int maskingMismatchCount
) {

  public static OperationHealthSummary from(
      List<OperationStatusRow> rows,
      List<MaskingPolicyStatus> maskingStatuses
  ) {
    int rowPolicyOk = 0;
    int rowPolicyWarn = 0;
    int rowPolicyError = 0;
    int missingHandler = 0;
    int missingPolicy = 0;
    int invalidFunction = 0;
    int unverified = 0;

    for (OperationStatusRow row : rows) {
      switch (row.healthLevel()) {
        case "OK" -> rowPolicyOk++;
        case "ERROR" -> rowPolicyError++;
        default -> rowPolicyWarn++;
      }
      if (row.handlerId() == null) {
        missingHandler++;
      }
      if (row.policyNames() == null || row.policyNames().isBlank()) {
        missingPolicy++;
      }
      if (row.functionStatus() != null && !"VALID".equalsIgnoreCase(row.functionStatus())) {
        invalidFunction++;
      }
      if (row.lastProbeStatus() == null || row.lastProbeStatus().isBlank()) {
        unverified++;
      }
    }

    int maskingApplied = 0;
    int maskingInactive = 0;
    int maskingMismatch = 0;
    for (MaskingPolicyStatus status : maskingStatuses) {
      if (status.applied()) {
        maskingApplied++;
      } else if (status.inactiveAsExpected()) {
        maskingInactive++;
      } else {
        maskingMismatch++;
      }
    }

    return new OperationHealthSummary(
        rows.size(),
        rowPolicyOk,
        rowPolicyWarn,
        rowPolicyError,
        missingHandler,
        missingPolicy,
        invalidFunction,
        unverified,
        maskingStatuses.size(),
        maskingApplied,
        maskingInactive,
        maskingMismatch
    );
  }

  public String overallLevel() {
    if (rowPolicyErrorCount > 0 || invalidFunctionCount > 0 || maskingMismatchCount > 0) {
      return "ERROR";
    }
    if (rowPolicyWarnCount > 0 || missingHandlerCount > 0 || missingPolicyCount > 0
        || unverifiedCount > 0) {
      return "WARN";
    }
    return "OK";
  }

  public String overallLabel() {
    return switch (overallLevel()) {
      case "ERROR" -> "조치 필요";
      case "WARN" -> "확인 필요";
      default -> "정상";
    };
  }

  public String overallBadgeClass() {
    return switch (overallLevel()) {
      case "ERROR" -> "text-bg-danger";
      case "WARN" -> "text-bg-warning";
      default -> "text-bg-success";
    };
  }

  public String rowPolicySummary() {
    return "정상 " + rowPolicyOkCount + " · 확인 " + rowPolicyWarnCount + " · 오류 " + rowPolicyErrorCount;
  }

  public String maskingSummary() {
    return "적용 " + maskingAppliedCount + " · 미적용 정상 " + maskingInactiveExpectedCount
        + " · 불일치 " + maskingMismatchCount;
  }

  public String primaryAction() {
    if (invalidFunctionCount > 0) {
      return "컴파일 오류가 있는 VPD Filter를 먼저 확인하세요.";
    }
    if (maskingMismatchCount > 0) {
      return "컬럼 마스킹 화면에서 DB ASO 정책 동기화를 확인하세요.";
    }
    if (missingPolicyCount > 0) {
      return "보호 상태에서 행 접근 정책(VPD)을 적용하세요.";
    }
    if (missingHandlerCount > 0) {
      return "조회 대상 또는 조회 연동에서 ORDS handler를 확인하세요.";
    }
    if (unverifiedCount > 0) {
      return "접근 검증을 실행해 실제 결과를 확인하세요.";
    }
    return "현재 요약 기준으로 즉시 조치할 항목은 없습니다.";
  }
}
