# PostgreSQL Operator Management
# Crunchy PGO (PostgreSQL Operator) and PostgreSQL clusters

# Include common variables and functions
include common/Makefile

# PostgreSQL Operator configuration
# Using common namespace variables from common/Makefile
HELMFILE_OPERATOR := helmfile-operator.yaml

.PHONY: postgres-help
postgres-help:
	@echo ""
	@echo "$(COLOR_BOLD)PostgreSQL Commands:$(COLOR_RESET)"
	@echo "  make postgres-install-operator - Install Crunchy PGO (PostgreSQL Operator)"
	@echo "  make postgres-update-operator  - Update Crunchy PGO"
	@echo "  make postgres-uninstall-operator - Uninstall operator (keeps clusters)"
	@echo "  make postgres-create-cluster   - Create pg-public cluster"
	@echo "  make postgres-update-cluster   - Update pg-public cluster"
	@echo "  make postgres-delete-cluster   - Delete pg-public cluster (keeps operator)"
	@echo "  make postgres-recreate-cluster - Recreate cluster keeping data (PVCs preserved)"
	@echo "  make postgres-status          - Check PostgreSQL status"
	@echo "  make postgres-uninstall       - Uninstall operator and all clusters"
	@echo "  make postgres-init-service-db SERVICE=name - Initialize databases and secrets for a service"
	@echo "  make postgres-get-migration-vars SERVICE=name - Generate GitLab CI/CD migration variables"
	@echo ""
	@echo "$(COLOR_BOLD)PostgreSQL Monitoring:$(COLOR_RESET)"
	@echo "  make postgres-monitoring-status - Check monitoring status"
	@echo "  make postgres-create-pgbouncer-exporter-secret - Create connection string secret for PgBouncer exporter"
	@echo "  make postgres-install-pgbouncer-exporter - Install PgBouncer exporter (for PGO 5.7.0)"
	@echo "  make postgres-uninstall-pgbouncer-exporter - Uninstall PgBouncer exporter"
	@echo "  Note: Postgres monitoring is built-in via PostgresCluster CR (monitoring.pgmonitor.exporter)"
	@echo "  ServiceMonitor and PrometheusRule should be configured separately in monitoring namespace"
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) Before installing, prepare nodes:"
	@echo "  cd ../.. && make k8s-prepare-nodes"

.PHONY: postgres-install-operator
postgres-install-operator: install-namespaces
	$(call print_info,Creating PostgreSQL namespaces...)
	@$(KUBECTL) apply -f postgres/manifests/tech-postgres-operator.yaml
	@$(KUBECTL) apply -f postgres/manifests/tech-postgres-databases.yaml
	$(call print_info,Installing Crunchy PGO via helmfile...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$postgresDir = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'postgres')); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$helmfilePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$postgresDir, 'helmfile-operator.yaml')); Write-Host 'Using helmfile: ' $$helmfilePath; if (-not (Test-Path $$helmfilePath)) { Write-Host 'Error: Helmfile not found at: ' $$helmfilePath; exit 1 }; $$content = Get-Content $$helmfilePath -Raw; if ($$content -notmatch 'postgres-operator') { Write-Host 'Error: Wrong helmfile content! Expected postgres-operator but found:'; Get-Content $$helmfilePath | Select-Object -First 3; exit 1 }; $$env:KUBECONFIG = $$kubeconfig; Push-Location $$postgresDir; try { helmfile -f helmfile-operator.yaml sync } finally { Pop-Location }"
else
	@cd postgres && $(call run_helmfile,$(HELMFILE_OPERATOR),sync)
endif
	$(call print_info,Waiting for operator to be ready...)
	@$(KUBECTL) -n $(POSTGRES_OPERATOR_NAMESPACE) rollout status deployment/pgo --timeout=5m
	$(call print_success,Crunchy PGO installed!)

.PHONY: postgres-update-operator
postgres-update-operator:
	$(call print_info,Updating Crunchy PGO via helmfile...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$postgresDir = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'postgres')); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$helmfilePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$postgresDir, 'helmfile-operator.yaml')); if (-not (Test-Path $$helmfilePath)) { Write-Host 'Error: Helmfile not found at: ' $$helmfilePath; exit 1 }; $$env:KUBECONFIG = $$kubeconfig; Push-Location $$postgresDir; try { helmfile -f helmfile-operator.yaml sync } finally { Pop-Location }"
else
	@cd postgres && $(call run_helmfile,$(HELMFILE_OPERATOR),sync)
endif
	$(call print_info,Waiting for operator to be ready...)
	@$(KUBECTL) -n $(POSTGRES_OPERATOR_NAMESPACE) rollout status deployment/pgo --timeout=5m
	$(call print_success,Crunchy PGO updated!)

.PHONY: postgres-uninstall-operator
postgres-uninstall-operator:
	$(call print_warning,This will uninstall Crunchy PGO!)
	@echo "Note: PostgreSQL clusters will NOT be deleted."
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Uninstalling operator...)
ifeq ($(DETECTED_OS),Windows)
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$postgresDir = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'postgres')); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$helmfilePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$postgresDir, 'helmfile-operator.yaml')); if (Test-Path $$helmfilePath) { $$env:KUBECONFIG = $$kubeconfig; Push-Location $$postgresDir; try { helmfile -f helmfile-operator.yaml destroy } finally { Pop-Location } }" 2>nul || echo "Operator may already be uninstalled"
else
	-@cd postgres && $(call run_helmfile,$(HELMFILE_OPERATOR),destroy) || true
endif
	$(call print_success,Operator uninstalled. Clusters remain.)

.PHONY: postgres-check-longhorn
postgres-check-longhorn:
	$(call check_longhorn)

.PHONY: postgres-create-cluster
postgres-create-cluster: postgres-check-longhorn
	$(call print_info,Applying PostgreSQL resource policies...)
	@$(KUBECTL) apply -f postgres/manifests/default-deny-networkpolicy.yaml
	@$(KUBECTL) apply -f postgres/manifests/limitrange.yaml
	@$(KUBECTL) apply -f postgres/manifests/resourcequota.yaml
	@$(KUBECTL) apply -f postgres/manifests/networkpolicy.yaml
	$(call print_info,Creating StorageClass for PostgreSQL...)
	@$(KUBECTL) apply -f postgres/manifests/storageclass.yaml
	$(call print_info,Applying init SQL ConfigMap...)
	@$(KUBECTL) apply -f postgres/manifests/cluster/pg-public-init-sql-configmap.yaml
	$(call print_info,Creating PostgreSQL cluster pg-public...)
	@$(KUBECTL) apply -f postgres/manifests/cluster/pg-public.yaml
	$(call print_info,Applying PgBouncer metrics Service...)
	@$(KUBECTL) apply -f postgres/manifests/monitoring/pgbouncer-metrics-service.yaml
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for cluster to be ready (this may take 3-5 minutes)...$(COLOR_RESET)"
	@echo "Monitor with: make postgres-status"
	$(call sleep_seconds,30)
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) wait --for=condition=Ready postgrescluster/pg-public --timeout=10m || true
	$(call print_success,PostgreSQL cluster created!)

.PHONY: postgres-update-cluster
postgres-update-cluster:
	$(call print_info,Updating PostgreSQL resource policies...)
	@$(KUBECTL) apply -f postgres/manifests/default-deny-networkpolicy.yaml
	@$(KUBECTL) apply -f postgres/manifests/limitrange.yaml
	@$(KUBECTL) apply -f postgres/manifests/resourcequota.yaml
	@$(KUBECTL) apply -f postgres/manifests/networkpolicy.yaml
	$(call print_info,Updating PostgreSQL cluster pg-public...)
	@$(KUBECTL) apply -f postgres/manifests/cluster/pg-public.yaml
	$(call print_info,Applying PgBouncer metrics Service...)
	@$(KUBECTL) apply -f postgres/manifests/monitoring/pgbouncer-metrics-service.yaml
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for cluster to be ready (this may take 3-5 minutes)...$(COLOR_RESET)"
	@echo "Monitor with: make postgres-status"
	$(call sleep_seconds,30)
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) wait --for=condition=Ready postgrescluster/pg-public --timeout=10m || true
	$(call print_success,PostgreSQL cluster updated!)

.PHONY: postgres-delete-cluster
postgres-delete-cluster:
	$(call print_warning,This will delete the pg-public PostgreSQL cluster and its data!)
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting pg-public cluster CR...)
	-@$(KUBECTL) delete postgrescluster pg-public -n $(POSTGRES_DATABASES_NAMESPACE) || true
	$(call print_info,Waiting for cluster resources to be cleaned up...)
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) wait --for=delete postgrescluster/pg-public --timeout=5m || true
	$(call print_info,Deleting pg-public services...)
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 -n $(POSTGRES_DATABASES_NAMESPACE) delete svc -l postgres-operator.crunchydata.com/cluster=pg-public 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(POSTGRES_DATABASES_NAMESPACE) delete svc pg-public 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(POSTGRES_DATABASES_NAMESPACE) delete svc pg-public-replica 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(POSTGRES_DATABASES_NAMESPACE) delete svc pg-public-pgbouncer 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
else
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete svc -l postgres-operator.crunchydata.com/cluster=pg-public 2>/dev/null || true
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete svc pg-public 2>/dev/null || true
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete svc pg-public-replica 2>/dev/null || true
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete svc pg-public-pgbouncer 2>/dev/null || true
endif
	$(call print_info,Deleting pg-public PVCs (if any)...)
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 -n $(POSTGRES_DATABASES_NAMESPACE) delete pvc -l postgres-operator.crunchydata.com/cluster=pg-public 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
else
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete pvc -l postgres-operator.crunchydata.com/cluster=pg-public 2>/dev/null || true
endif
	$(call print_info,Deleting pg-public secrets (credentials)...)
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 -n $(POSTGRES_DATABASES_NAMESPACE) delete secret -l postgres-operator.crunchydata.com/cluster=pg-public 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pguser-pgpublic-app 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pguser-pgpublic-monitoring 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pguser-postgres 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
else
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete secret -l postgres-operator.crunchydata.com/cluster=pg-public 2>/dev/null || true
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pguser-pgpublic-app 2>/dev/null || true
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pguser-pgpublic-monitoring 2>/dev/null || true
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pguser-postgres 2>/dev/null || true
endif
	$(call print_info,Deleting pg-public pods (if any)...)
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 -n $(POSTGRES_DATABASES_NAMESPACE) delete pod -l postgres-operator.crunchydata.com/cluster=pg-public --grace-period=0 --force 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
else
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete pod -l postgres-operator.crunchydata.com/cluster=pg-public --grace-period=0 --force 2>/dev/null || true
endif
	$(call print_info,Deleting pg-public statefulsets (if any)...)
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete statefulset -l postgres-operator.crunchydata.com/cluster=pg-public || true
	$(call print_info,Deleting pg-public deployments (if any)...)
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 -n $(POSTGRES_DATABASES_NAMESPACE) delete deployment -l postgres-operator.crunchydata.com/cluster=pg-public 2>$$null; if ($$LASTEXITCODE -ne 0) { exit 0 }"
else
	-@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete deployment -l postgres-operator.crunchydata.com/cluster=pg-public 2>/dev/null || true
endif
	$(call print_success,pg-public cluster deleted.)

.PHONY: postgres-recreate-cluster
postgres-recreate-cluster:
	$(call print_warning,This will recreate the pg-public PostgreSQL cluster!)
	@echo "Data will be preserved (PVCs will NOT be deleted)."
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting pg-public cluster CR (keeping PVCs)...)
	-@$(KUBECTL) delete postgrescluster pg-public -n $(POSTGRES_DATABASES_NAMESPACE) || true
	$(call print_info,Waiting for cluster resources to be cleaned up...)
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) wait --for=delete postgrescluster/pg-public --timeout=5m || true
	$(call sleep_seconds,10)
	$(call print_info,Recreating pg-public cluster...)
	@$(KUBECTL) apply -f postgres/manifests/cluster/pg-public.yaml
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for cluster to be ready (this may take 3-5 minutes)...$(COLOR_RESET)"
	@echo "Monitor with: make postgres-status"
	$(call sleep_seconds,30)
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) wait --for=condition=Ready postgrescluster/pg-public --timeout=10m || true
	$(call print_success,pg-public cluster recreated! Data should be preserved.)
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) If the operator created new PVCs instead of reusing old ones,"
	@echo "you may need to manually bind the old PVCs to the new pods."

.PHONY: postgres-status
postgres-status:
	@echo ""
	@echo "$(COLOR_BOLD)=== Postgres Operator Status ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(POSTGRES_OPERATOR_NAMESPACE) get pods
	@echo ""
	@echo "$(COLOR_BOLD)=== PostgreSQL Clusters ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) get postgrescluster
	@echo ""
	@echo "$(COLOR_BOLD)=== pg-public Pods ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) get pods -l postgres-operator.crunchydata.com/cluster=pg-public -o wide
	@echo ""
	@echo "$(COLOR_BOLD)=== pg-public Services ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) get svc -l postgres-operator.crunchydata.com/cluster=pg-public
	@echo ""

.PHONY: postgres-uninstall
postgres-uninstall:
	$(call print_warning,This will delete ALL PostgreSQL clusters and data!)
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting PostgreSQL clusters...)
	-@$(KUBECTL) delete postgrescluster --all -n $(POSTGRES_DATABASES_NAMESPACE)
	$(call print_info,Uninstalling operator...)
ifeq ($(DETECTED_OS),Windows)
	-@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$postgresDir = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'postgres')); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$helmfilePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$postgresDir, 'helmfile-operator.yaml')); if (Test-Path $$helmfilePath) { $$env:KUBECONFIG = $$kubeconfig; Push-Location $$postgresDir; try { helmfile -f helmfile-operator.yaml destroy } finally { Pop-Location } }" 2>nul || echo "Operator may already be uninstalled"
else
	-@cd postgres && $(call run_helmfile,$(HELMFILE_OPERATOR),destroy) || true
endif
	$(call print_success,Uninstall complete.)

.PHONY: postgres-monitoring-status
postgres-monitoring-status:
	@echo ""
	@echo "$(COLOR_BOLD)=== PostgreSQL Built-in Exporter Status ===$(COLOR_RESET)"
	@echo "Note: Monitoring is built-in via PostgresCluster CR (monitoring.pgmonitor.exporter)"
	@echo ""
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) get pods -l postgres-operator.crunchydata.com/cluster=pg-public -o wide | grep exporter || echo "Exporter pods are part of PostgresCluster"
	@echo ""
	@echo "$(COLOR_BOLD)=== ServiceMonitor ===$(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; $$result = kubectl -n tech-monitoring get servicemonitor postgres-exporter 2>$$null; if ($$LASTEXITCODE -ne 0) { Write-Host 'ServiceMonitor not found (should be configured separately)' } else { $$result }"
else
	@$(KUBECTL) -n tech-monitoring get servicemonitor postgres-exporter 2>/dev/null || echo "ServiceMonitor not found (should be configured separately)"
endif
	@echo ""
	@echo "$(COLOR_BOLD)=== PrometheusRule ===$(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; $$result = kubectl -n tech-monitoring get prometheusrule postgres-alerts 2>$$null; if ($$LASTEXITCODE -ne 0) { Write-Host 'PrometheusRule not found (should be configured separately)' } else { $$result }"
else
	@$(KUBECTL) -n tech-monitoring get prometheusrule postgres-alerts 2>/dev/null || echo "PrometheusRule not found (should be configured separately)"
endif
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) ServiceMonitor and PrometheusRule should be configured in monitoring namespace"
	@echo "      to scrape metrics from the built-in exporter."
	@echo ""
	@echo "$(COLOR_BOLD)=== PgBouncer Exporter Status ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) get deployment pg-public-pgbouncer-exporter 2>/dev/null || echo "PgBouncer exporter not installed (use: make postgres-install-pgbouncer-exporter)"

.PHONY: postgres-install-pgbouncer-exporter
postgres-install-pgbouncer-exporter: install-namespaces
	$(call print_info,Installing PgBouncer exporter (sidecar approach)...)
	$(call print_info,Applying PgBouncer metrics Service...)
	@$(KUBECTL) apply -f postgres/manifests/monitoring/pgbouncer-metrics-service.yaml
	$(call print_info,Applying ServiceMonitor...)
	@$(KUBECTL) apply -f monitoring/manifests/monitors/pgbouncer-exporter-servicemonitor.yaml
	$(call print_success,PgBouncer exporter Service and ServiceMonitor installed!)
	@echo ""
	@echo "$(COLOR_BOLD)Note:$(COLOR_RESET) PgBouncer exporter runs as sidecar container in PgBouncer pods."
	@echo "  The exporter is configured in PostgresCluster CR (spec.proxy.pgBouncer.containers)."
	@echo ""
	@echo "$(COLOR_BOLD)Next steps:$(COLOR_RESET)"
	@echo "  1. Verify sidecar exporters are running: kubectl -n $(POSTGRES_DATABASES_NAMESPACE) get pods -l postgres-operator.crunchydata.com/role=pgbouncer -o jsonpath='{.items[*].spec.containers[*].name}'"
	@echo "  2. Check Service endpoints: kubectl -n $(POSTGRES_DATABASES_NAMESPACE) get endpoints pg-public-pgbouncer-metrics"
	@echo "  3. Check metrics: kubectl -n $(POSTGRES_DATABASES_NAMESPACE) port-forward svc/pg-public-pgbouncer-metrics 9127:9127"
	@echo "  4. Open http://localhost:9127/metrics in browser"

.PHONY: postgres-uninstall-pgbouncer-exporter
postgres-uninstall-pgbouncer-exporter:
	$(call print_info,Uninstalling PgBouncer exporter...)
	@$(KUBECTL) delete -f monitoring/manifests/monitors/pgbouncer-exporter-servicemonitor.yaml 2>/dev/null || true
	@$(KUBECTL) delete -f postgres/manifests/monitoring/pgbouncer-metrics-service.yaml 2>/dev/null || true
	@$(KUBECTL) delete -f postgres/manifests/monitoring/pgbouncer-exporter-deployment.yaml 2>/dev/null || true
	@$(KUBECTL) -n $(POSTGRES_DATABASES_NAMESPACE) delete secret pg-public-pgbouncer-exporter-connection 2>/dev/null || true
	$(call print_success,PgBouncer exporter uninstalled!)

.PHONY: postgres-init-service-db
postgres-init-service-db:
ifeq ($(SERVICE),)
	$(error SERVICE variable is required. Example: make postgres-init-service-db SERVICE=my-service)
endif
	$(call print_info,Initializing database for service: $(SERVICE)...)
	$(eval ROTATE_FLAG := $(if $(filter true,$(ROTATE)),--rotate,))
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -ExecutionPolicy Bypass -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$scriptPath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'postgres', 'scripts', 'init-service-db.py')); python \"$$scriptPath\" \"$(SERVICE)\" $(ROTATE_FLAG) --kubeconfig \"$$kubeconfig\""
else
	@python3 postgres/scripts/init-service-db.py "$(SERVICE)" $(ROTATE_FLAG) --kubeconfig "$(KUBECONFIG_REL)"
endif
	$(call print_success,Service $(SERVICE) database initialized!)

.PHONY: postgres-get-migration-vars
postgres-get-migration-vars:
ifeq ($(SERVICE),)
	$(error SERVICE variable is required. Example: make postgres-get-migration-vars SERVICE=my-service)
endif
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -ExecutionPolicy Bypass -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$scriptPath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'postgres', 'scripts', 'generate-migration-vars.py')); python \"$$scriptPath\" \"$(SERVICE)\" --kubeconfig \"$$kubeconfig\""
else
	@python3 postgres/scripts/generate-migration-vars.py "$(SERVICE)" --kubeconfig "$(KUBECONFIG_REL)"
endif
