package com.cloudhandson.vpdbackoffice.service;

import com.cloudhandson.vpdbackoffice.config.CatalogProperties;
import com.cloudhandson.vpdbackoffice.domain.structured.StructuredDataTable;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import org.springframework.stereotype.Service;

@Service
public class EnvironmentDataCatalog implements DataCatalog {
  private static final Pattern NAME = Pattern.compile("[A-Z][A-Z0-9_$#]{0,127}");
  private static final Pattern KEY = Pattern.compile("[a-z][a-z0-9-]{0,63}");
  private final String owner;
  private final List<StructuredDataTable> objects;

  public EnvironmentDataCatalog(CatalogProperties properties, ObjectMapper mapper) {
    owner = requireName(properties.owner());
    objects = parse(properties.objects(), mapper);
  }

  @Override public String owner() { return owner; }
  @Override public List<StructuredDataTable> objects() { return objects; }
  @Override public StructuredDataTable require(String key) {
    return objects.stream().filter(item -> item.key().equals(key)).findFirst()
        .orElseThrow(() -> new AppException("선택할 수 없는 카탈로그 객체입니다."));
  }

  private List<StructuredDataTable> parse(String raw, ObjectMapper mapper) {
    if (raw == null || raw.isBlank()) {
      throw new IllegalStateException("BACKOFFICE_CATALOG_OBJECTS 설정을 확인하세요.");
    }
    try {
      List<StructuredDataTable> values = mapper.readValue(raw, new TypeReference<>() {});
      if (values.isEmpty() || values.stream().map(StructuredDataTable::key).distinct().count() != values.size()) throw new IllegalArgumentException();
      values.forEach(this::validate);
      return List.copyOf(values);
    } catch (Exception exception) {
      throw new IllegalStateException("BACKOFFICE_CATALOG_OBJECTS 설정을 확인하세요.", exception);
    }
  }
  private void validate(StructuredDataTable value) {
    if (value == null || value.key() == null || !KEY.matcher(value.key()).matches()
        || !NAME.matcher(value.tableName().toUpperCase(Locale.ROOT)).matches()
        || !("TABLE".equalsIgnoreCase(value.objectType()) || "VIEW".equalsIgnoreCase(value.objectType()))) throw new IllegalArgumentException();
  }
  private String requireName(String value) {
    String normalized = value == null ? "" : value.trim().toUpperCase(Locale.ROOT);
    if (!NAME.matcher(normalized).matches()) throw new IllegalStateException("BACKOFFICE_CATALOG_OWNER 설정을 확인하세요.");
    return normalized;
  }
}
