## GitLab Runner Operator (via OLM) + Runner Instance
## Works with common/Makefile Windows wrapper

include common/Makefile

# Namespaces
GITLAB_RUNNER_OPERATOR_NS := $(GITLAB_RUNNER_OPERATOR_NAMESPACE)
GITLAB_RUNNER_INSTANCES_NS := $(GITLAB_RUNNER_INSTANCES_NAMESPACE)

# Manifests
MANIFESTS_DIR := gitlab-runner/manifests
NAMESPACES_MANIFEST := $(MANIFESTS_DIR)/gitlab-runner-namespaces.yaml
OPERATOR_MANIFEST := $(MANIFESTS_DIR)/gitlab-runner-operator.yaml
RUNNER_MANIFEST := $(MANIFESTS_DIR)/gitlab-runner-instance.yaml
CONFIG_MANIFEST := $(MANIFESTS_DIR)/gitlab-runner-config.yaml
SERVICE_MANIFEST := $(MANIFESTS_DIR)/gitlab-runner-service.yaml

# Resources
RUNNER_SECRET_NAME := gitlab-runner-token
SUBSCRIPTION_NAME := gitlab-runner-operator
OPERATORGROUP_NAME := gitlab-runner-operator

# Registry Pull Secret (Deploy Token + Reflector)
REGISTRY_SECRET_NAME := gitlab-registry-key
REGISTRY_URL := registry.gitlab.com
# Источник секрета (храним там же где оператор GitLab)
REGISTRY_SOURCE_NS := $(GITLAB_RUNNER_OPERATOR_NS)
# Регулярные выражения для автоматической доставки во все нужные окружения
REGISTRY_REFLECT_TO := stage-.*,pre-.*,prod-.*,tech-.*

.PHONY: gitlab-runner-help
gitlab-runner-help:
	@echo ""
	@echo "$(COLOR_BOLD)GitLab Runner Commands:$(COLOR_RESET)"
	@echo "  make gitlab-runner-olm-install       - Install GitLab Runner Operator (via OLM)"
	@echo "  make gitlab-runner-update-operator    - Update GitLab Runner Operator (re-apply subscription)"
	@echo "  make gitlab-runner-uninstall-operator - Uninstall operator (keeps instances)"
	@echo ""
	@echo "  make gitlab-runner-create-secret      - Create runner token secret (interactive)"
	@echo "  make gitlab-runner-update-secret      - Update runner token secret (interactive)"
	@echo "  make gitlab-runner-delete-secret      - Delete runner token secret"
	@echo "  make gitlab-runner-get-secret         - Get runner token secret info"
	@echo ""
	@echo "  make gitlab-registry-create-secret    - Create MASTER registry pull secret (with Reflector)"
	@echo "  make gitlab-registry-delete-secret    - Delete MASTER registry pull secret"
	@echo ""
	@echo "$(COLOR_BOLD)GitLab Runner RBAC Commands:$(COLOR_RESET)"
	@echo "  make gitlab-runner-apply-rbac        - Apply RBAC for PostgreSQL secrets access"
	@echo "  make gitlab-runner-check-rbac        - Check current RBAC permissions"
	@echo ""
	@echo "$(COLOR_BOLD)GitLab Runner Instance Commands:$(COLOR_RESET)"
	@echo "  make gitlab-runner-create-instance    - Create runner instance + Service"
	@echo "  make gitlab-runner-update-instance    - Update runner instance + Service"
	@echo "  make gitlab-runner-delete-instance    - Delete runner instance + Service (keeps operator)"
	@echo ""
	@echo "  make gitlab-runner-status             - Check GitLab Runner status"
	@echo "  make gitlab-runner-uninstall          - Uninstall operator and instances"
	@echo ""

# -------------------------------------------------------------------
# Operator (via OLM)
# -------------------------------------------------------------------

.PHONY: gitlab-runner-olm-install
gitlab-runner-olm-install:
	$(call print_info,Applying namespaces...)
	@$(KUBECTL) apply -f $(NAMESPACES_MANIFEST)
	$(call print_info,Applying GitLab Runner Operator (OLM) manifest...)
	@$(KUBECTL) apply -f $(OPERATOR_MANIFEST)
	$(call print_info,Waiting for CSV to become Succeeded (best-effort)...)
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) get subscription,installplan,csv 2>/dev/null || true
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) wait --for=condition=Succeeded csv --all --timeout=10m 2>/dev/null || true
	$(call print_success,Operator manifest applied.)

.PHONY: gitlab-runner-update-operator
gitlab-runner-update-operator:
	$(call print_info,Updating GitLab Runner Operator (re-apply OLM manifest)...)
	@$(KUBECTL) apply -f $(OPERATOR_MANIFEST)
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) get subscription,installplan,csv 2>/dev/null || true
	$(call print_success,Operator manifest updated.)

.PHONY: gitlab-runner-uninstall-operator
gitlab-runner-uninstall-operator:
	$(call print_warning,Uninstalling operator Subscription/OperatorGroup (instances will remain)...)
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) delete subscription $(SUBSCRIPTION_NAME) --ignore-not-found=true || true
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) delete operatorgroup $(OPERATORGROUP_NAME) --ignore-not-found=true || true
	$(call print_success,Operator uninstall requested.)

# -------------------------------------------------------------------
# Secret (runner token)
# -------------------------------------------------------------------

.PHONY: gitlab-runner-create-secret
gitlab-runner-create-secret:
	@$(MAKE) gitlab-runner-update-secret

.PHONY: gitlab-runner-update-secret
gitlab-runner-update-secret:
	$(call print_info,Creating/updating secret $(RUNNER_SECRET_NAME) in $(GITLAB_RUNNER_INSTANCES_NS)...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$ErrorActionPreference = 'Stop'; \
	  $$curDir = [System.IO.Directory]::GetCurrentDirectory(); \
	  $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); \
	  $$env:KUBECONFIG = $$kubeconfig; \
	  $$t = Read-Host 'Enter GitLab runner token (glrt-...)'; \
	  if ([string]::IsNullOrWhiteSpace($$t)) { throw 'Token is empty'; } \
	  kubectl -n $(GITLAB_RUNNER_INSTANCES_NS) create secret generic $(RUNNER_SECRET_NAME) \
	    --from-literal=runner-registration-token=$$t \
	    --dry-run=client -o yaml | kubectl apply -f -"
else
	@read -r -p "Enter GitLab runner token (glrt-...): " t; \
	  test -n "$$t"; \
	  $(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) create secret generic $(RUNNER_SECRET_NAME) \
	    --from-literal=runner-registration-token=$$t \
	    --dry-run=client -o yaml | $(KUBECTL) apply -f -
endif
	$(call print_success,Secret created/updated.)

.PHONY: gitlab-runner-delete-secret
gitlab-runner-delete-secret:
	$(call print_warning,Deleting secret $(RUNNER_SECRET_NAME) from $(GITLAB_RUNNER_INSTANCES_NS)...)
	@$(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) delete secret $(RUNNER_SECRET_NAME) --ignore-not-found=true || true
	$(call print_success,Secret deleted (if existed).)

.PHONY: gitlab-runner-get-secret
gitlab-runner-get-secret:
	@$(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) get secret $(RUNNER_SECRET_NAME) -o yaml 2>/dev/null || true

# -------------------------------------------------------------------
# Registry Pull Secret (Deploy Token + Reflector)
# -------------------------------------------------------------------

.PHONY: gitlab-registry-create-secret
gitlab-registry-create-secret:
	$(call print_info,Creating MASTER registry secret in $(REGISTRY_SOURCE_NS)...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$ErrorActionPreference = 'Stop'; \
	  $$curDir = [System.IO.Directory]::GetCurrentDirectory(); \
	  $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); \
	  $$u = Read-Host 'Enter GitLab Deploy Token Username'; \
	  $$p = Read-Host 'Enter GitLab Deploy Token Password' -AsSecureString; \
	  $$p_ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($$p); \
	  $$p_plain = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($$p_ptr); \
	  if ([string]::IsNullOrWhiteSpace($$u) -or [string]::IsNullOrWhiteSpace($$p_plain)) { throw 'User or Password empty'; } \
	  $$yaml = kubectl --kubeconfig=\"$$kubeconfig\" create secret docker-registry $(REGISTRY_SECRET_NAME) \
	    --docker-server=$(REGISTRY_URL) \
	    --docker-username=$$u \
	    --docker-password=$$p_plain \
	    --namespace $(REGISTRY_SOURCE_NS) \
	    --dry-run=client -o yaml; \
	  $$lines = $$yaml -split \"\r?\n\"; \
	  $$newYaml = @(); \
	  foreach ($$line in $$lines) { \
	    $$newYaml += $$line; \
	    if ($$line -match '^metadata:') { \
	      $$newYaml += \"  annotations:\"; \
	      $$newYaml += \"    reflector.v1.k8s.emberstack.com/reflection-allowed: 'true'\"; \
	      $$newYaml += \"    reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: '$(REGISTRY_REFLECT_TO)'\"; \
	      $$newYaml += \"    reflector.v1.k8s.emberstack.com/reflection-auto-enabled: 'true'\"; \
	      $$newYaml += \"    reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: '$(REGISTRY_REFLECT_TO)'\"; \
	    } \
	  } \
	  $$newYaml -join \"`n\" | kubectl --kubeconfig=\"$$kubeconfig\" apply -f -"
else
	@read -r -p "Enter GitLab Deploy Token Username: " u; \
	  read -rs -p "Enter GitLab Deploy Token Password: " p; \
	  echo ""; \
	  $(KUBECTL) create secret docker-registry $(REGISTRY_SECRET_NAME) \
	    --docker-server=$(REGISTRY_URL) \
	    --docker-username="$$u" \
	    --docker-password="$$p" \
	    --namespace "$(REGISTRY_SOURCE_NS)" \
	    --dry-run=client -o yaml > registry-secret.yaml; \
	  sed -i '/metadata:/a \  annotations:\n    reflector.v1.k8s.emberstack.com/reflection-allowed: "true"\n    reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "$(REGISTRY_REFLECT_TO)"\n    reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"\n    reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "$(REGISTRY_REFLECT_TO)"' registry-secret.yaml; \
	  $(KUBECTL) apply -f registry-secret.yaml; \
	  rm registry-secret.yaml
endif
	$(call print_success,Master registry secret created. Reflector will sync it automatically.)

.PHONY: gitlab-registry-delete-secret
gitlab-registry-delete-secret:
	$(call print_warning,Deleting MASTER registry secret from $(REGISTRY_SOURCE_NS)...)
	@$(KUBECTL) -n $(REGISTRY_SOURCE_NS) delete secret $(REGISTRY_SECRET_NAME) --ignore-not-found=true || true
	$(call print_success,Master secret deleted. Reflector will remove copies.)

# -------------------------------------------------------------------
# RBAC for PostgreSQL secrets access
# -------------------------------------------------------------------

.PHONY: gitlab-runner-apply-rbac
gitlab-runner-apply-rbac:
	$(call print_info,Applying RBAC for GitLab Runner to access PostgreSQL secrets...)
	@$(KUBECTL) apply -f $(MANIFESTS_DIR)/gitlab-runner-rbac.yaml
	$(call print_success,RBAC applied successfully.)
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) GitLab Runner can now read PostgreSQL secrets for migrations."
	@echo "Run 'make gitlab-runner-check-rbac' to verify permissions."

.PHONY: gitlab-runner-check-rbac
gitlab-runner-check-rbac:
	$(call print_info,Checking GitLab Runner RBAC permissions...)
	@echo ""
	@echo "$(COLOR_BOLD)ServiceAccount:$(COLOR_RESET)"
	@$(KUBECTL) -n tech-gitlab-runner-instances get serviceaccount gitlab-runner-app-sa 2>/dev/null || echo "ServiceAccount not found"
	@echo ""
	@echo "$(COLOR_BOLD)Checking permissions to read secrets in tech-postgres-databases:$(COLOR_RESET)"
	@$(KUBECTL) auth can-i get secrets --as=system:serviceaccount:tech-gitlab-runner-instances:gitlab-runner-app-sa -n tech-postgres-databases
	@echo ""
	@echo "$(COLOR_BOLD)RoleBindings in tech-postgres-databases:$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl get rolebindings -n tech-postgres-databases 2>$$null | Select-String 'gitlab-runner'; if ($$LASTEXITCODE -ne 0) { Write-Host 'No gitlab-runner RoleBindings found' }"
else
	@$(KUBECTL) get rolebindings -n tech-postgres-databases 2>/dev/null | grep gitlab-runner || echo "No gitlab-runner RoleBindings found"
endif
	@echo ""

# -------------------------------------------------------------------
# Runner instance + Service
# -------------------------------------------------------------------

.PHONY: gitlab-runner-create-instance
gitlab-runner-create-instance:
	$(call print_info,Creating Runner instance + ConfigMap + Service...)
	@$(KUBECTL) apply -f $(CONFIG_MANIFEST)
	@$(KUBECTL) apply -f $(RUNNER_MANIFEST)
	@$(KUBECTL) apply -f $(SERVICE_MANIFEST)
	$(call print_success,Instance applied.)

.PHONY: gitlab-runner-update-instance
gitlab-runner-update-instance:
	$(call print_info,Updating Runner instance + ConfigMap + Service...)
	@$(KUBECTL) apply -f $(CONFIG_MANIFEST)
	@$(KUBECTL) apply -f $(RUNNER_MANIFEST)
	@$(KUBECTL) apply -f $(SERVICE_MANIFEST)
	$(call print_success,Instance updated.)

.PHONY: gitlab-runner-delete-instance
gitlab-runner-delete-instance:
	$(call print_warning,Deleting Runner instance + ConfigMap + Service (operator will remain)...)
	@$(KUBECTL) delete -f $(SERVICE_MANIFEST) --ignore-not-found=true || true
	@$(KUBECTL) delete -f $(RUNNER_MANIFEST) --ignore-not-found=true || true
	@$(KUBECTL) delete -f $(CONFIG_MANIFEST) --ignore-not-found=true || true
	$(call print_success,Instance deleted (if existed).)

# -------------------------------------------------------------------
# Status + Full uninstall
# -------------------------------------------------------------------

.PHONY: gitlab-runner-status
gitlab-runner-status:
	@echo ""
	@echo "$(COLOR_BOLD)=== Operator (OLM): subscription/csv/installplan ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) get subscription,installplan,csv 2>/dev/null || true
	@echo ""
	@echo "$(COLOR_BOLD)=== Operator Pods ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(GITLAB_RUNNER_OPERATOR_NS) get pods -o wide 2>/dev/null || true
	@echo ""
	@echo "$(COLOR_BOLD)=== Runner CR ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) get runner 2>/dev/null || \
	  $(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) get runners.apps.gitlab.com 2>/dev/null || true
	@echo ""
	@echo "$(COLOR_BOLD)=== Runner Pods / Service ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) get pods -o wide 2>/dev/null || true
	@$(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) get svc -o wide 2>/dev/null || true
	@echo ""
	@echo "$(COLOR_BOLD)=== Runner Secret ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(GITLAB_RUNNER_INSTANCES_NS) get secret $(RUNNER_SECRET_NAME) 2>/dev/null || true

.PHONY: gitlab-runner-uninstall
gitlab-runner-uninstall: gitlab-runner-delete-instance gitlab-runner-uninstall-operator
	$(call print_success,GitLab Runner fully uninstalled (best-effort).)
