# === Config (all overridable via environment / CLI) ===
ENDPOINT_URL ?= http://localhost:4566
REGION_NAME  ?= us-east-1

S3_BUCKET_NAME ?= omicslab
S3_PREFIX      ?= data/tools

# Dev creds for local S3-compatible storage. Override via env / CI secrets for prod.
AWS_ACCESS_KEY_ID ?= test
AWS_SECRET_ACCESS_KEY ?= testtest
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY

# Pixi: use root workspace environment
PIXI_RUN := pixi run -e sdk
PIXI_CONFIG_FILE := $(CURDIR)/pixi.config.toml

# --- APP_ENV: dev or prod — selects the section from regions.json ---
APP_ENV ?= dev

# --- Regions config (single source of truth) ---
REGIONS_JSON ?= envs/regions.json
JQ           ?= jq

# --- Derived from JSON ---
CONFIG_HOST_EP   := $(shell $(JQ) -r '.["$(APP_ENV)"].config_host.endpoint' $(REGIONS_JSON))
CONFIG_HOST_BK   := $(shell $(JQ) -r '.["$(APP_ENV)"].config_host.bucket' $(REGIONS_JSON))
CONFIG_HOST_RGN  := $(shell $(JQ) -r '.["$(APP_ENV)"].config_host.region' $(REGIONS_JSON))
CONFIG_HOST_PROF := $(shell $(JQ) -r '.["$(APP_ENV)"].config_host.profile' $(REGIONS_JSON))
# The dev profile maps to the local S3 (SeaweedFS) with env creds test/testtest,
# so no named aws --profile is needed. Remote profiles (prod) keep --profile.
ifeq ($(CONFIG_HOST_PROF),dev)
CONFIG_HOST_PROF_FLAG :=
else
CONFIG_HOST_PROF_FLAG := --profile $(CONFIG_HOST_PROF)
endif
CONFIG_S3_BUCKET := s3://$(CONFIG_HOST_BK)/$(S3_PREFIX)

# Cloud env source (never modified)
CLOUD_ENV_DIR  := envs
CLOUD_ENV_TOML := $(CLOUD_ENV_DIR)/pixi.toml
# Output dir per environment
ENV_OUT_DIR    := $(CLOUD_ENV_DIR)/$(APP_ENV)

# Per-region helpers — look up endpoint/bucket/profile for a given region name
region_endpoint = $(shell $(JQ) -r '.["$(APP_ENV)"].regions["$(1)"].endpoint' $(REGIONS_JSON))
region_bucket   = $(shell $(JQ) -r '.["$(APP_ENV)"].regions["$(1)"].bucket' $(REGIONS_JSON))
region_profile  = $(shell $(JQ) -r '.["$(APP_ENV)"].regions["$(1)"].profile' $(REGIONS_JSON))
# dev profile → local S3 env creds (no --profile); remote profiles keep --profile.
region_prof_flag = $(if $(filter dev,$(call region_profile,$(1))),,--profile $(call region_profile,$(1)))

# Regions list — derived from JSON (fallback to empty)
CLOUD_REGIONS := $(shell $(JQ) -r '.["$(APP_ENV)"].regions | keys[]' $(REGIONS_JSON) 2>/dev/null)

# --- Pixi binary ---
PIXI_VERSION   ?= v0.76.1
PIXI_ARCH       = x86_64-unknown-linux-musl
PIXI_GITHUB_URL = https://github.com/prefix-dev/pixi/releases/download/$(PIXI_VERSION)/pixi-$(PIXI_ARCH).tar.gz
PIXI_LOCAL_FILE = pixi/pixi-$(PIXI_VERSION)-linux-amd64.tar.gz

# --- Derived ---
# Version comes from src/omicslab/_version.py (single source of truth; hatch
# reads the same file — see [tool.hatch.version] in pyproject.toml).
VERSION          := $(shell grep -m1 '__version__' src/omicslab/_version.py | sed 's/.*"\(.*\)"/\1/')
WHEEL            := dist/omicslab-$(VERSION)-py3-none-any.whl
WHEEL_S3_NAME    := $(notdir $(WHEEL))
VERSION_MANIFEST := dist/sdk-version.json

# Public-read bucket policy for the config host bucket.
S3_PUBLIC_POLICY := {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":"*","Action":"s3:ListBucket","Resource":"arn:aws:s3:::$(CONFIG_HOST_BK)"},{"Effect":"Allow","Principal":"*","Action":"s3:GetObject","Resource":"arn:aws:s3:::$(CONFIG_HOST_BK)/data/*"}]}

.PHONY: ensure-bucket build make-public prepare-cache prepare-cache-all cache-pixi upload-pixi clean

ensure-bucket: ## Create bucket in config host S3 if it does not exist
	aws s3api head-bucket --bucket $(CONFIG_HOST_BK) \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG) 2>/dev/null \
		|| aws s3 mb s3://$(CONFIG_HOST_BK) \
			--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
			$(CONFIG_HOST_PROF_FLAG)

build: ## Build wheel + upload to config host S3 (with sdk-version.json)
	$(PIXI_RUN) python -c "import hatchling.build; hatchling.build.build_wheel('dist/')"
	$(PIXI_RUN) python scripts/write_version_manifest.py $(WHEEL) $(VERSION_MANIFEST)
	aws s3 cp $(WHEEL) $(CONFIG_S3_BUCKET)/$(WHEEL_S3_NAME) \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG)
	aws s3 cp $(WHEEL) $(CONFIG_S3_BUCKET)/omicslab-latest.whl \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG)
	aws s3 cp $(VERSION_MANIFEST) $(CONFIG_S3_BUCKET)/sdk-version.json \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG)

make-public: ## Allow anonymous LIST of the config host bucket + GET of s3://bucket/data/*
	aws s3api put-bucket-policy --bucket $(CONFIG_HOST_BK) \
		--region $(CONFIG_HOST_RGN) --endpoint-url $(CONFIG_HOST_EP) \
		$(CONFIG_HOST_PROF_FLAG) \
		--policy '$(S3_PUBLIC_POLICY)'

# --- Channel cache (per-region S3) ---

prepare-cache-region: ## Pack channel and upload to a specific region's S3 (set CACHE_*)
	mkdir -p $(CLOUD_ENV_DIR)/_build
	cp $(CLOUD_ENV_TOML) $(CLOUD_ENV_DIR)/_build/pixi.toml
	cd $(CLOUD_ENV_DIR)/_build && pixi lock --config-file $(PIXI_CONFIG_FILE)
	$(PIXI_RUN) pixi-pack $(CLOUD_ENV_DIR)/_build/pixi.toml \
		--platform linux-64 --directory-only --output-file $(CLOUD_ENV_DIR)/_build/.cache
	aws s3 sync $(CLOUD_ENV_DIR)/_build/.cache/ s3://$(CACHE_BUCKET)/$(S3_PREFIX)/pixi/ \
		--endpoint-url $(CACHE_ENDPOINT) --region $(CACHE_REGION) \
		$(CACHE_PROF_FLAG)
	@rm -rf $(CLOUD_ENV_DIR)/_build

prepare-cache-all: ## Pack channel once and upload to all regions' S3
	$(foreach region,$(CLOUD_REGIONS),\
		$(MAKE) prepare-cache-region \
			CACHE_ENDPOINT=$(call region_endpoint,$(region)) \
			CACHE_BUCKET=$(call region_bucket,$(region)) \
			CACHE_REGION=$(region) \
			CACHE_PROF_FLAG="$(call region_prof_flag,$(region))"; \
	)

# --- Config files (toml+lock) uploaded to config host ---

cache-pixi: ## Generate per-region toml+lock, upload to config host
	mkdir -p $(ENV_OUT_DIR)
	# Generate default (non-region-specific) toml+lock
	mkdir -p $(ENV_OUT_DIR)/default
	sed 's|channels = \["conda-forge", "bioconda"\]|channels = ["$(CONFIG_HOST_EP)/$(CONFIG_HOST_BK)/$(S3_PREFIX)/pixi/channel"]|' \
		$(CLOUD_ENV_TOML) > $(ENV_OUT_DIR)/default/pixi.toml
	cd $(ENV_OUT_DIR)/default && pixi lock --config-file $(PIXI_CONFIG_FILE) && cd $(CURDIR)
	sed -i 's|https://files.pythonhosted.org/packages/[^/]*/[^/]*/[^/]*/\([^/]*\.whl\)|$(CONFIG_HOST_EP)/$(CONFIG_HOST_BK)/$(S3_PREFIX)/pixi/pypi/\1|g' \
		$(ENV_OUT_DIR)/default/pixi.lock
	mv $(ENV_OUT_DIR)/default/pixi.lock $(ENV_OUT_DIR)/pixi.lock
	mv $(ENV_OUT_DIR)/default/pixi.toml $(ENV_OUT_DIR)/pixi.toml
	rm -rf $(ENV_OUT_DIR)/default
	# Generate per-region toml+lock — each region gets its own cache endpoint
	$(foreach region,$(CLOUD_REGIONS),\
		mkdir -p $(ENV_OUT_DIR)/$(region); \
		sed 's|channels = \["conda-forge", "bioconda"\]|channels = ["$(call region_endpoint,$(region))/$(call region_bucket,$(region))/$(S3_PREFIX)/pixi/channel"]|' \
			$(CLOUD_ENV_TOML) > $(ENV_OUT_DIR)/$(region)/pixi.toml; \
		cd $(ENV_OUT_DIR)/$(region) && pixi lock --config-file $(PIXI_CONFIG_FILE); cd $(CURDIR); \
		sed -i 's|https://files.pythonhosted.org/packages/[^/]*/[^/]*/[^/]*/\([^/]*\.whl\)|$(call region_endpoint,$(region))/$(call region_bucket,$(region))/$(S3_PREFIX)/pixi/pypi/\1|g' \
			$(ENV_OUT_DIR)/$(region)/pixi.lock; \
		mv $(ENV_OUT_DIR)/$(region)/pixi.lock $(ENV_OUT_DIR)/$(region).pixi.lock; \
		mv $(ENV_OUT_DIR)/$(region)/pixi.toml $(ENV_OUT_DIR)/$(region).pixi.toml; \
		rm -rf $(ENV_OUT_DIR)/$(region); \
	)
	# Upload default config files to config host
	aws s3 cp $(ENV_OUT_DIR)/pixi.toml $(CONFIG_S3_BUCKET)/pixi/config/pixi.toml \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG) --no-progress
	aws s3 cp $(ENV_OUT_DIR)/pixi.lock $(CONFIG_S3_BUCKET)/pixi/config/pixi.lock \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG) --no-progress
	# Upload per-region config files to config host
	$(foreach region,$(CLOUD_REGIONS),\
		aws s3 cp $(ENV_OUT_DIR)/$(region).pixi.toml $(CONFIG_S3_BUCKET)/pixi/config/$(region).pixi.toml \
			--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
			$(CONFIG_HOST_PROF_FLAG) --no-progress; \
		aws s3 cp $(ENV_OUT_DIR)/$(region).pixi.lock $(CONFIG_S3_BUCKET)/pixi/config/$(region).pixi.lock \
			--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
			$(CONFIG_HOST_PROF_FLAG) --no-progress; \
	)

# --- Pixi binary ---

$(PIXI_LOCAL_FILE): ## Download pixi binary to local cache (versioned)
	@mkdir -p $(dir $(PIXI_LOCAL_FILE))
	curl -fsSL $(PIXI_GITHUB_URL) -o $(PIXI_LOCAL_FILE)

upload-pixi: $(PIXI_LOCAL_FILE) ## Upload pixi binary to config host S3
	aws s3 cp $(PIXI_LOCAL_FILE) $(CONFIG_S3_BUCKET)/pixi/bin/$(notdir $(PIXI_LOCAL_FILE)) \
		--endpoint-url $(CONFIG_HOST_EP) --region $(CONFIG_HOST_RGN) \
		$(CONFIG_HOST_PROF_FLAG)
	@echo "Uploaded $(PIXI_LOCAL_FILE) -> $(CONFIG_S3_BUCKET)/pixi/bin/$(notdir $(PIXI_LOCAL_FILE))"

clean: ## Clean build artifacts
	rm -rf dist/ *.egg-info .cache/ pixi-*.tar.gz
