// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.k8s.operator.cluster;

import com.google.gerrit.k8s.operator.gerrit.Gerrit;
import com.google.gerrit.k8s.operator.gerrit.ServiceDependentResource;
import com.google.gerrit.k8s.operator.receiver.Receiver;
import com.google.gerrit.k8s.operator.receiver.ReceiverServiceDependentResource;
import io.fabric8.kubernetes.api.model.networking.v1.HTTPIngressPath;
import io.fabric8.kubernetes.api.model.networking.v1.HTTPIngressPathBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.IngressBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.IngressRule;
import io.fabric8.kubernetes.api.model.networking.v1.IngressRuleBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.IngressTLS;
import io.fabric8.kubernetes.api.model.networking.v1.IngressTLSBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.ServiceBackendPort;
import io.fabric8.kubernetes.api.model.networking.v1.ServiceBackendPortBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@KubernetesDependent(labelSelector = "app.kubernetes.io/component=gerrit-ingress")
public class GerritIngress extends CRUDKubernetesDependentResource<Ingress, GerritCluster> {
  public static final String INGRESS_NAME = "gerrit-ingress";

  public GerritIngress() {
    super(Ingress.class);
  }

  @Override
  protected Ingress desired(GerritCluster gerritCluster, Context<GerritCluster> context) {
    List<Gerrit> gerrits =
        client
            .resources(Gerrit.class)
            .inNamespace(gerritCluster.getMetadata().getNamespace())
            .list()
            .getItems()
            .stream()
            .filter(gerrit -> GerritCluster.isMemberPartOfCluster(gerrit.getSpec(), gerritCluster))
            .collect(Collectors.toList());

    List<Receiver> receivers =
        client
            .resources(Receiver.class)
            .inNamespace(gerritCluster.getMetadata().getNamespace())
            .list()
            .getItems()
            .stream()
            .filter(r -> GerritCluster.isMemberPartOfCluster(r.getSpec(), gerritCluster))
            .collect(Collectors.toList());

    List<String> hosts = new ArrayList<>();
    List<IngressRule> ingressRules = new ArrayList<>();
    for (Receiver receiver : receivers) {
      ingressRules.add(getReceiverIngressRule(gerritCluster, receiver));
      hosts.add(getFullHostname(receiver.getMetadata().getName(), gerritCluster));
    }

    ingressRules.addAll(getGerritIngressRules(gerritCluster, gerrits));
    for (Gerrit gerrit : gerrits) {
      hosts.add(getFullHostname(gerrit.getMetadata().getName(), gerritCluster));
    }

    Ingress gerritIngress =
        new IngressBuilder()
            .withNewMetadata()
            .withName("gerrit-ingress")
            .withNamespace(gerritCluster.getMetadata().getNamespace())
            .withLabels(gerritCluster.getLabels("gerrit-ingress", this.getClass().getSimpleName()))
            .withAnnotations(gerritCluster.getSpec().getIngress().getAnnotations())
            .endMetadata()
            .withNewSpec()
            .withTls(getIngressTLS(gerritCluster, hosts))
            .withRules(ingressRules)
            .endSpec()
            .build();

    return gerritIngress;
  }

  private IngressTLS getIngressTLS(GerritCluster gerritCluster, List<String> hosts) {
    if (gerritCluster.getSpec().getIngress().getTls().isEnabled()) {
      return new IngressTLSBuilder()
          .withHosts(hosts)
          .withSecretName(gerritCluster.getSpec().getIngress().getTls().getSecret())
          .build();
    }
    return new IngressTLS();
  }

  private List<IngressRule> getGerritIngressRules(
      GerritCluster gerritCluster, List<Gerrit> gerrits) {
    List<IngressRule> ingressRules = new ArrayList<>();

    for (Gerrit gerrit : gerrits) {
      String gerritSvcName = ServiceDependentResource.getName(gerrit);
      ingressRules.add(
          new IngressRuleBuilder()
              .withHost(getFullHostname(gerritSvcName, gerritCluster))
              .withNewHttp()
              .withPaths(getGerritHTTPIngressPath(gerritSvcName))
              .endHttp()
              .build());
    }

    return ingressRules;
  }

  private IngressRule getReceiverIngressRule(GerritCluster gerritCluster, Receiver receiver) {
    return new IngressRuleBuilder()
        .withHost(getFullHostname(receiver.getMetadata().getName(), gerritCluster))
        .withNewHttp()
        .withPaths(getReceiverIngressPaths(ReceiverServiceDependentResource.getName(receiver)))
        .endHttp()
        .build();
  }

  public HTTPIngressPath getGerritHTTPIngressPath(String svcName) {
    ServiceBackendPort port =
        new ServiceBackendPortBuilder().withName(ServiceDependentResource.HTTP_PORT_NAME).build();

    return new HTTPIngressPathBuilder()
        .withPathType("Prefix")
        .withPath("/")
        .withNewBackend()
        .withNewService()
        .withName(svcName)
        .withPort(port)
        .endService()
        .endBackend()
        .build();
  }

  public List<HTTPIngressPath> getReceiverIngressPaths(String svcName) {
    List<HTTPIngressPath> paths = new ArrayList<>();
    ServiceBackendPort port =
        new ServiceBackendPortBuilder()
            .withName(ReceiverServiceDependentResource.HTTP_PORT_NAME)
            .build();

    for (String path : Set.of("/a/projects", "/new", "/git")) {
      paths.add(
          new HTTPIngressPathBuilder()
              .withPathType("Prefix")
              .withPath(path)
              .withNewBackend()
              .withNewService()
              .withName(svcName)
              .withPort(port)
              .endService()
              .endBackend()
              .build());
    }
    return paths;
  }

  public static String getFullHostname(String svcName, GerritCluster gerritCluster) {
    return String.format("%s.%s", svcName, gerritCluster.getSpec().getIngress().getHost());
  }
}
