# Makefile variables set automatically
plugin_package_json=plugin.json
plugin_id=`cat ${plugin_package_json} | python3 -c "import sys, json; print(str(json.load(sys.stdin)['id']).replace('/',''))"`
ifeq ($(origin plugin_version), undefined)
    plugin_version=$(shell cat $(plugin_package_json) | python3 -c "import sys, json; print(str(json.load(sys.stdin)['version']).replace('/',''))")
    $(info No argument plugin_version has been passed, we will use current version: $(plugin_version))
	fe-build-required=false
else
    plugin_version=$(plugin_version)
    $(info Using provided plugin_version: $(plugin_version))
	fe-build-required=true
endif

archive_file_name="dss-plugin-${plugin_id}-${plugin_version}.zip"
remote_url=`git config --get remote.origin.url`

# Print a message based on whether the branch argument is passed or not
ifeq ($(origin branch), undefined)
    branch = $(shell git rev-parse --abbrev-ref HEAD)
    $(info No argument branch has been passed, we will use current branch: $(branch))
else
    $(info Using branch: $(branch))
endif

last_commit_id=`git rev-parse ${branch}`

.DEFAULT_GOAL := plugin

frontend_package_json=resource/frontend/package.json
backend_version_path=python-lib/answers/backend/__version__.py

# Help target
help:
	@echo "Available targets and options:"
	@echo ""
	@echo "Steps:"
	@echo "  plugin          		Build a version of the plugin."
	@echo "                  		Usage: make plugin [plugin_version=VERSION] [branch=BRANCH] [add_tag=true]"
	@echo "                  		- plugin_version: Specify the plugin version (default: current version from plugin.json)."
	@echo "                  		- branch: Specify the branch to build from (default: current branch)."
	@echo "                  		- add_tag: Specify if you want to add a git tag after building (default: false)."
	@echo ""
	@echo "  dev             		Build plugin version based on local branch."
	@echo "                  		Usage: make dev"
	@echo ""
	@echo "  backend-unit-tests           		Run unit tests with your current environment"
	@echo "                  		Usage: make backend-unit-tests"
	@echo ""
	@echo "  reinstall-env-run-be-unit-tests      		Run unit tests for the plugin after installing a new python env."
	@echo "                  		Usage: make reinstall-env-run-be-unit-tests"
	@echo ""
	@echo "  tests           		Run both unit tests and integration tests for the plugin."
	@echo "                  		Usage: make tests"
	@echo ""		
	@echo "  frontend-lint-check  	Run frontend lint checks"
	@echo "                  		Usage: make frontend-lint-check"
	@echo ""


##########################################
######## Plugin Release #########
##########################################

# Plugin target: Building plugin for PROD mode
plugin: dist-clean update-package-version-in-git-and-build
	@echo "[START] Archiving plugin to dist/ folder..."
	@cat ${plugin_package_json} | json_pp > /dev/null
	@mkdir dist
	@echo "{\"remote_url\":\"${remote_url}\",\"branch\":\"${branch}\",\"last_commit_id\":\"${last_commit_id}\"}" > release_info.json
	@ORIGINAL_COMMIT=$$(git rev-parse HEAD); echo "Current commit: $$ORIGINAL_COMMIT";
	@echo "Flattening submodule python-lib/common..."
	@cd temp_repo && git rm --cached -rf python-lib/common
	@cd temp_repo && rm -rf .git/modules/python-lib/common
	@cd temp_repo && rm -f .gitmodules
	@cd temp_repo && git add .
	@cd temp_repo && git commit -m "Temporary commit: flatten submodule python-lib/common for release"
	@echo "Creating archive..."
	@cd temp_repo && git archive -v -9 --format zip -o ../dist/${archive_file_name} HEAD
	@if [[ -d tests ]]; then \
		zip --delete dist/${archive_file_name} "tests/*"; \
	fi
	@zip -u dist/${archive_file_name} release_info.json
	@if [ "$(add_tag)" = "true" ]; then \
        $(MAKE) tagged-release; \
	fi
	@rm release_info.json
	@rm -rf temp_repo
	@echo "[WARNING] ⚠️ Your ${branch} is now behind the newly created commit on the remote. It is recommended that you pull these changes"
	@echo "[SUCCESS] Archiving plugin to dist/ folder:"
	@echo "🌟💎Done!💎🌟"

#Dev target: Building plugin DEV mode based on local branch
dev: dist-clean update-frontend-version update-backend-version build-frontend update-plugin-json-version
	@echo "[START] Archiving plugin to dist/ folder... (dev mode)"
	@cat ${plugin_package_json} | json_pp > /dev/null
	@mkdir dist
	@zip -v -9 dist/${archive_file_name} -r . \
	--exclude "tests/*" \
	--exclude "env/*" \
	--exclude ".git/*" \
	--exclude ".pytest_cache/*" \
	--exclude ".venv*" \
	--exclude ".env" \
	--exclude "node_modules/*" \
	--exclude "**/node_modules/*" \
	--exclude ".ruff_cache/*" \
	--exclude ".gitattributes" \
	--exclude ".gitignore" \
	--exclude ".gitattributes" \
	--exclude "*coverage*" \
	--exclude "resource/frontend/rebranding/*" \
	--exclude "**/.vscode/*" \
	--exclude ".vscode/*" \
	--exclude "*test*" \
	--exclude "**/*.venv*" \
	--exclude "playwrite/*" \
	--exclude ".gitignore" \
	--exclude "playwright-report/*" \
	--exclude ".github/*" \
	--exclude "playwright.config.ts" \
	--exclude "python-lib/.mypy_cache/*" \
	--exclude "**/.DS_Store" \
	--exclude ".DS_Store" \
	--exclude ".wlock" \
	--exclude "**/.wlock" \
	--exclude "playwright/*" \
	--exclude "documentation/*" \
	--exclude "pyproject.toml"
	@echo "[SUCCESS] Archiving plugin to dist/ folder: Done!"

dist-clean:
	@echo "Cleanning dist/ folder..."
	rm -rf dist

.PHONY: update-frontend-version
update-frontend-version:
	@echo "Updating frontend ${frontend_package_json} with plugin version ${plugin_version}"
	@cp $(frontend_package_json) $(frontend_package_json).bak
	@sed "s/\"version\": \".*\"/\"version\": \"${plugin_version}\"/" $(frontend_package_json).bak > $(frontend_package_json)
	@rm $(frontend_package_json).bak

build-frontend:
	@echo "Building frontend"
	@cd resource/frontend && yarn install && yarn build

.PHONY: update-backend-version
update-backend-version:
	@echo "Updating backend ${backend_version_path} with new plugin version ${plugin_version}"
	@if [ -f "${backend_version_path}" ]; then \
		echo "Backing up existing file..."; \
		cp "${backend_version_path}" "${backend_version_path}.bak"; \
	else \
		echo "No existing version file found, skipping backup."; \
	fi
	@echo "__version__ = \"${plugin_version}\"" > ${backend_version_path}
	@rm -f $(backend_version_path).bak

.PHONY: update-plugin-json-version
update-plugin-json-version:
	@current_plugin_version=`cat ${plugin_package_json} | python3 -c "import sys, json; print(str(json.load(sys.stdin)['version']))"`
	@if [ "${plugin_version}" != "$$current_plugin_version" ]; then \
		cp ${plugin_package_json} ${plugin_package_json}.bak; \
		echo "Updating ${plugin_package_json} with new version ${plugin_version}"; \
		sed "s/\"version\": \".*\"/\"version\": \"${plugin_version}\"/" ${plugin_package_json}.bak > ${plugin_package_json}; \
		rm ${plugin_package_json}.bak; \
	else \
		echo "${plugin_package_json} is already at version ${plugin_version}"; \
	fi

.PHONY: check-branch-is-on-remote
check-branch-is-on-remote:
	@echo "Fetching latest from remote..."
	@git fetch origin $(branch)

	@echo "Checking if local and remote HEADs match for branch '$(branch)'..."
	@LOCAL_COMMIT=$$(git rev-parse $(branch)); \
	REMOTE_COMMIT=$$(git rev-parse origin/$(branch)); \
	if [ "$$LOCAL_COMMIT" = "$$REMOTE_COMMIT" ]; then \
	    echo "[INFO] ✅ Local and remote branches are in sync."; \
	else \
	    echo "[INFO] ℹ️ Local and remote branches are different!"; \
	fi

.PHONY: tagged-release
tagged-release:
	@echo "Creating GitHub release and attaching archive..."
	@gh release create "v${plugin_version}" dist/${archive_file_name} \
	    --title "Version ${plugin_version}" \
		--generate-notes


.PHONY: update-package-version-in-git-and-build
update-package-version-in-git-and-build: check-branch-is-on-remote
	@echo "[START] Updating package.json version with plugin version ${plugin_version} in git"
	@echo "Cleaning temp_repo folder..."
	@rm -rf temp_repo
	@git clone --branch ${branch} --single-branch ${remote_url} temp_repo
	@cd temp_repo && git submodule update --init --recursive
	@cp Makefile temp_repo/Makefile	
	@cd temp_repo && $(MAKE) update-plugin-json-version
	@cd temp_repo && $(MAKE) update-frontend-version
	@cd temp_repo && $(MAKE) update-backend-version
	@cd temp_repo && git add ${frontend_package_json} ${plugin_package_json}
	@echo "Building frontend with new version..."
	@echo "Building with new version..."
	@if [ "$(fe-build-required)" = "false" ]; then \
		echo "Skipping frontend build ⏭️"; \
	else \
		echo "Building frontend 🔨👷 ..."; \
		cd temp_repo/resource/frontend && rm -f yarn.lock && yarn install && yarn build || exit 1; \
	fi
	@cd temp_repo && git add resource/dist || echo "No changes were made"
	@echo "Committing package.json version update and frontend build..."
	@cd temp_repo && git commit -m "Update package.json version ${plugin_version} and build frontend" || echo "Nothing to commit"
	@echo "Pushing changes to ${branch} branch..."
	@cd temp_repo && git push origin ${branch} || echo "Nothing to push"
	@if [ "$(add_tag)" = "true" ]; then \
		$(MAKE) add-git-tag; \
	fi
	@echo "[SUCCESS] Updating package.json version with plugin version ${plugin_version} in git: Done!"


.PHONY: add-git-tag
add-git-tag:
	@echo "Adding tag v${plugin_version} to main repository"
	@git tag -a "v${plugin_version}" -m "Tagging version ${plugin_version}"
	@git push origin "v${plugin_version}"
	@echo "Updating submodules and adding tag"
	@git submodule foreach 'git tag -a "answers-v${plugin_version}" -m "Tagging version answers-v${plugin_version}"; git push origin "answers-v${plugin_version}"'

##########################################
######## TESTS #########
##########################################
# This creates (or delete and recreate) a new python env `env` and runs the unit tests. 
# If you want to run the tests with your current environment, use backend-unit-tests instead
reinstall-env-run-be-unit-tests:
	@echo "Running unit tests..."
	@( \
		PYTHON_VERSION=`python3 -c "import sys; print()"`; \
		PYTHON_VERSION_IS_CORRECT=`cat code-env/python/desc.json | python3 -c "import sys, json; print('$$PYTHON_VERSION' in json.load(sys.stdin)['acceptedPythonInterpreters']);"`; \
		if [ $$PYTHON_VERSION_IS_CORRECT == "False" ]; then echo "Python version $$PYTHON_VERSION is not in acceptedPythonInterpreters"; exit 1; else echo "Python version $$PYTHON_VERSION is in acceptedPythonInterpreters"; fi; \
	)
	@( \
		rm -rf ./env/; \
		python3 -m venv env/; \
		source env/bin/activate; \
		pip install --upgrade pip;\
		pip install --no-cache-dir -r tests/python/unit/requirements.txt; \
		pip install --no-cache-dir -r code-env/python/spec/requirements.github.txt; \
		export PYTHONPATH="$(PYTHONPATH):$(PWD)/python-lib"; \
		pytest tests/python/unit --alluredir=tests/allure_report || ret=$$?; exit $$ret \
		allure serve tests/allure_report \
	)

api-tests:
	@echo "Running api tests..."
	@cd tests/api_tests && make tests

tests: backend-unit-tests api-tests


##########################################
######## Dev tools: backend #########
##########################################

backend-lint-check:
	@echo "Running ruff ..."
	@cd python-lib && ruff check


backend-mypy:
	@echo "Running mypy ..."
	@cd python-lib && mypy -p answers.backend -p answers.llm_assist -p answers.solutions --config-file=../pyproject.toml

backend-unit-tests:
	@echo "Running unit tests ..."
	@pip install -r tests/python/unit/requirements.txt
	@export PYTHONPATH="$(PYTHONPATH):$(PWD)/python-lib:$(PWD)/tests/python/unit";
	@pytest tests/python/unit --cov=python-lib

##########################################
######## Dev tools: frontend #########
##########################################

frontend-lint-check:
	@echo "Running lint ..."
	@cd resource/frontend && yarn run lint .
