#!/bin/sh

GREEN='\033[0;32m'
ORANGE='\033[0;33m'
NO_COLOR='\033[0m'
BRIGHT_CYAN='\033[0;96m'
BRIGHT_PURPLE='\033[0;95m'

__check_go() {
    if ! command -v go &>/dev/null; then
        echo -e "\nGo is not installed. Please install Go."
        echo -e "\nhttps://golang.org/doc/install"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}go "
    fi
}

__check_node() {
    if ! command -v npm &>/dev/null; then
        echo -e "\nNode is not installed. Please install Node."
        echo -e "\nhttps://nodejs.org/en/download/"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}npm "
    fi
}

__check_dlv() {
    if ! command -v dlv &>/dev/null; then
        echo -e "\nDLV is not installed. Please install DLV."
        echo -e "\nbin/app install-tools"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}dlv "
    fi
}

__check_sqlc() {
    if ! command -v sqlc &>/dev/null; then
        echo -e "\nSQLC is not installed. Please install SQLC."
        echo -e "\nbin/app install-tools"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}sqlc "
    fi
}

__check_goose() {
    if ! command -v goose &>/dev/null; then
        echo -e "\nGoose is not installed. Please install Goose."
        echo -e "\nbin/app install-tools"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}goose "
    fi
}

__check_air() {
    if ! command -v air &>/dev/null; then
        echo -e "\nAir is not installed. Please install Air."
        echo -e "\nbin/app install-tools"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}air "
    fi
}

__check_templ() {
    if ! command -v templ &>/dev/null; then
        echo -e "\nTempl is not installed. Please install Templ."
        echo -e "\nbin/app install-tools"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}templ "
    fi
}

__check_tailwind() {
    if ! command -v tailwindcss &>/dev/null; then
        echo -e "\nTailwind is not installed. Please install Tailwind."
        echo -e "\nnpm i -g tailwindcss && npm i -D @tailwindcss/forms"
        _cmd_missing=true
        _cmd_missing_list="${_cmd_missing_list}tailwindcss "
    fi
}

__check_missing() {
    export _cmd_missing=false
    export _cmd_missing_list=
    __check_go
    __check_node
    __check_dlv
    __check_sqlc
    __check_goose
    __check_air
    __check_templ
    __check_tailwind
    if $_cmd_missing; then
        echo -e "\nMissing commands: ${_cmd_missing_list}"
        export _cmd_missing=false
        __cmd_missing_list=
        exit 1
    fi
}

__install_deps() {
	echo ================================================================================
	echo = Install dependencies =========================================================
	echo ================================================================================
	go mod download && go mod verify
	echo -e "\n"
}
INSTALL_DEPS_match=install-deps

__install_project_tools() {
    export _cmd_missing=false
    __check_go
    if $_cmd_missing; then
        exit 1
    fi
	go install github.com/a-h/templ/cmd/templ@latest
	go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
	go install github.com/pressly/goose/v3/cmd/goose@latest
	go install github.com/air-verse/air@latest
    go install github.com/go-delve/delve/cmd/dlv@latest
}
INSTALL_PROJECT_TOOLS_match=install-tools

__clean() {
	echo ================================================================================
	echo = Cleaning environment =========================================================
	echo ================================================================================
	echo -e "\n"
	find . -name '*_templ.go' -delete
	rm -rf ./ptpp ./debug ./public/assets/css/output.css ./dist/* ./models/*
	echo -e "\n"
}
CLEAN_match=clean

__init_project() {
	echo ================================================================================
	echo = First install ================================================================
	echo ================================================================================
	mkdir -p data && mkdir -p log
	if ! [ -f "data/database.db" ]; then
		touch data/database.db
	fi

    _cmd_missing=false
    __check_go
    if $_cmd_missing; then
        exit 1
    fi

	__install_project_tools
	sudo -S npm install
	echo -e "\n"
}
INIT_PROJECT_match=init-project

__first_install_macro() {
	_and_run=${1:-}
	if ! [ -z ${1+x} ]; then
		shift
	fi

	__init_project
	__install_deps
    __check_missing
	__clean
	__generate_macro
	__migrate --all
	case "$_and_run" in
	--and-run) __run "$@" ;;
	*) ;;
	esac
}
FIRST_INSTALL_MACRO_match=first-install

__build() {
    _cmd_missing=false
    __check_go
    if $_cmd_missing; then
        exit 1
    fi
	echo ================================================================================
	echo = Building =====================================================================
	echo ================================================================================
	go build -v -o ptpp ./cmd
	echo -e "\n"
}
BUILD_match=build

__run() {
	_case=${1:-}
	case "$1" in
	--reload) _reload=true ;;
	"") _reload=false ;;
	*)
        echo -e "Invalid flag $_case\n" 
        __help
        ;;
	esac

	__build

	if $_reload; then
        _cmd_missing=false
        __check_air
        if $_cmd_missing; then
            exit 1
        fi

		air
		echo -e "\n"
	else
		echo ================================================================================
		echo = Running ======================================================================
		echo ================================================================================
		echo -e "\n"
		./ptpp
	fi
}
RUN_match=run

__build_debug() {
    _cmd_missing=false
    __check_go
    __check_dlv
    if $_cmd_missing; then
        exit 1
    fi
	echo ================================================================================
	echo = Building debug ==============================================================
	echo ================================================================================
	go build -gcflags "all=-N -l" -o debug ./cmd/main.go
	echo -e "\n"
}
BUILD_DEBUG_match=build-debug

__run_debug() {
    _cmd_missing=false
    __check_dlv
    if $_cmd_missing; then
        exit 1
    fi

	__build_debug
	echo ================================================================================
	echo = Running debug ===============================================================
	echo ================================================================================
	dlv -l 127.0.0.1:2345 --headless --api-version=2 --accept-multiclient exec ./debug
	echo -e "\n"
}
RUN_DEBUG_match=run-debug

__migrate() {
    _cmd_missing=false
    __check_goose
    if $_cmd_missing; then
        exit 1
    fi

	_env=${1:-dev}
	if ! [ -z ${1+x} ]; then
		shift
	fi
	_direction=${1:-up}
	case "$_env" in
	--all)
		GOOSE_DRIVER=postgres GOOSE_MIGRATION_DIR="./migrations/postgres" goose $_direction
		GOOSE_DRIVER=sqlite GOOSE_MIGRATION_DIR="./migrations/sqlite" goose $_direction
		;;
	dev)
		GOOSE_DRIVER=sqlite GOOSE_MIGRATION_DIR="./migrations/sqlite" goose $_direction
		;;
	prod)
		GOOSE_DRIVER=postgres GOOSE_MIGRATION_DIR="./migrations/postgres" goose $_direction
		;;
	esac

	echo ================================================================================
	echo = Migrating ====================================================================
	echo ================================================================================

	echo -e "\n"
}
MIGRATE_match=migrate

__sqlc() {
    _cmd_missing=false
    __check_sqlc
    if $_cmd_missing; then
        exit 1
    fi
    echo ================================================================================
    echo = Generating SQLC ==============================================================
    echo ================================================================================
    sqlc generate
    echo -e "\n"
}

__templ() {
	echo ================================================================================
	echo = Generating templates =========================================================
	echo ================================================================================
	templ generate
	echo -e "\n"
}
TEMPL_match=templ

__tailwind() {
    _cmd_missing=false
    __check_tailwind
    if $_cmd_missing; then
        exit 1
    fi
	echo ================================================================================
	echo = Generating Tailwind ==========================================================
	echo ================================================================================
	tailwindcss build -i ./public/assets/css/index.css -o ./public/assets/css/output.css
	echo -e "\n"
}
TAILWIND_match=tailwind

__generate_macro() {
	_base=${1:---all}
	case "$_base" in
	--all)
		__templ
		__sqlc
		__tailwind
		;;
    --templ) __templ ;;
    --sqlc) __sqlc ;;
    --tailwind) __tailwind ;;
    *)
        echo -e "Invalid flag $_base\n" 
        __help
        ;;
	esac
}
GENERATE_MACRO_match=generate

__help() {
	echo -e "Usage: $0 <command>"
	echo -e "Commands:"
	echo -e "  ${GREEN}${FIRST_INSTALL_MACRO_match}${NO_COLOR}: ${ORANGE}First install macro${NO_COLOR}"
	echo -e "    ${BRIGHT_PURPLE}? ${GREEN}--and-run${NO_COLOR}: ${ORANGE}Run project after first install${NO_COLOR}"
	echo -e "      ${BRIGHT_PURPLE}? ${GREEN}--reload${NO_COLOR}: ${ORANGE}Run project with reload${NO_COLOR}"
	echo -e "  ${GREEN}${CLEAN_match}${NO_COLOR}: ${ORANGE}Clean environment${NO_COLOR}"
	echo -e "  ${GREEN}${INSTALL_DEPS_match}${NO_COLOR}: ${ORANGE}Install dependencies${NO_COLOR}"
	echo -e "  ${GREEN}${INSTALL_PROJECT_TOOLS_match}${NO_COLOR}: ${ORANGE}Install project tools${NO_COLOR}"
	echo -e "  ${GREEN}${BUILD_match}${NO_COLOR}: ${ORANGE}Build project${NO_COLOR}"
	echo -e "  ${GREEN}${RUN_match}${NO_COLOR}: ${ORANGE}Run project${NO_COLOR}"
	echo -e "    ${BRIGHT_PURPLE}? ${GREEN}--reload${NO_COLOR}: ${ORANGE}Run project with reload${NO_COLOR}"
	echo -e "  ${GREEN}${GENERATE_MACRO_match}${NO_COLOR}: ${ORANGE}Run code generation${NO_COLOR}"
	echo -e "    ${BRIGHT_PURPLE}* ${GREEN}--all${NO_COLOR}: ${ORANGE}Generate all${NO_COLOR}"
	echo -e "    ${GREEN}--tailwind${NO_COLOR}: ${ORANGE}Generate Tailwind CSS${NO_COLOR}"
	echo -e "    ${GREEN}--templ${NO_COLOR}: ${ORANGE}Generate templates${NO_COLOR}"
	echo -e "    ${GREEN}--sqlc${NO_COLOR}: ${ORANGE}Generate ORM${NO_COLOR}"
	echo -e "  ${GREEN}${MIGRATE_match}${NO_COLOR}: ${ORANGE}Migrate database${NO_COLOR}"
	echo -e "    ${GREEN}--all${NO_COLOR}: ${ORANGE}Migrate all databases${NO_COLOR}"
	echo -e "    ${BRIGHT_PURPLE}* ${GREEN}dev${NO_COLOR}: ${ORANGE}Migrate development database${NO_COLOR}"
	echo -e "    ${GREEN}prod${NO_COLOR}: ${ORANGE}Migrate production database${NO_COLOR}"
	echo -e "      ${BRIGHT_PURPLE}?* ${GREEN}up${NO_COLOR}: ${ORANGE}Migrate up${NO_COLOR}"
	echo -e "      ${BRIGHT_PURPLE}? ${GREEN}down${NO_COLOR}: ${ORANGE}Migrate down${NO_COLOR}"
	echo -e "  ${GREEN}${BUILD_DEBUG_match}${NO_COLOR}: ${ORANGE}Build debug${NO_COLOR}"
	echo -e "  ${GREEN}${RUN_DEBUG_match}${NO_COLOR}: ${ORANGE}Run debug${NO_COLOR}"
	echo -e "\n${BRIGHT_PURPLE}* Default\n? Optional${NO_COLOR}"
}

__main() {
	_cmd=${1:-help}
	if ! [ -z ${1+x} ]; then
		shift
	fi

	case "$_cmd" in
	help) __help ;;
	"$CLEAN_match") __clean ;;
	"$INSTALL_DEPS_match") __install_deps ;;
	"$BUILD_match") __build ;;
	"$RUN_match") __run "$@" ;;
	"$MIGRATE_match") __migrate "$@" ;;
	"$BUILD_DEBUG_match") __build_debug ;;
	"$RUN_DEBUG_match") __run_debug ;;
	"$FIRST_INSTALL_MACRO_match") __first_install_macro "$@" ;;
	"$GENERATE_MACRO_match") __generate_macro "$@" ;;
	"$INSTALL_PROJECT_TOOLS_match") __install_project_tools ;;
	*) 
        echo -e "Invalid command: $_cmd\n" 
        __help
        ;;
	esac

    __check_missing
}

__main "$@"
