#!/usr/bin/env bash

# Conventional commit helper
# Usage: gc [type] [message] [-s scope] [-b] [-B body]
#        gc (interactive mode)

set -o errexit
set -o nounset

TYPES="feat fix docs style refactor test chore perf ci build"

usage() {
    echo "Usage: gc [type] [message] [-s scope] [-b] [-B body]"
    echo "       gc (interactive mode)"
    echo ""
    echo "Options:"
    echo "  -s, --scope    Scope of the change"
    echo "  -b, --breaking Mark as breaking change (!)"
    echo "  -B, --body     Commit body (longer description)"
    echo ""
    echo "Types: $TYPES"
    echo ""
    echo "Examples:"
    echo "  gc feat 'add user auth'"
    echo "  gc fix 'resolve crash' -s api     # fix(api): resolve crash"
    echo "  gc feat 'new api' -b              # feat!: new api"
    echo "  gc feat 'new api' -s auth -b      # feat(auth)!: new api"
    echo "  gc feat 'big change' -B 'Details here'"
    exit 1
}

build_message() {
    local type="$1"
    local scope="$2"
    local breaking="$3"
    local msg="$4"
    local body="$5"

    local commit_msg="$type"

    if [ -n "$scope" ]; then
        commit_msg+="($scope)"
    fi

    if [ "$breaking" = "true" ]; then
        commit_msg+="!"
    fi

    commit_msg+=": $msg"

    if [ -n "$body" ]; then
        commit_msg+=$'\n\n'"$body"
    fi

    echo "$commit_msg"
}

# Interactive mode if no args
if [ $# -eq 0 ]; then
    echo "Types: $TYPES"
    printf "Type: "
    read -r type
    printf "Scope (optional): "
    read -r scope
    printf "Breaking change? [y/N]: "
    read -r breaking_input
    printf "Message: "
    read -r msg
    printf "Body (optional, enter for none): "
    read -r body

    breaking="false"
    if [[ $breaking_input =~ ^[Yy] ]]; then
        breaking="true"
    fi

    commit_msg=$(build_message "$type" "$scope" "$breaking" "$msg" "$body")
    git commit -m "$commit_msg"
    exit 0
fi

# Parse arguments
type=""
msg=""
scope=""
breaking="false"
body=""

while [ $# -gt 0 ]; do
    case "$1" in
    -s | --scope)
        scope="$2"
        shift 2
        ;;
    -b | --breaking)
        breaking="true"
        shift
        ;;
    -B | --body)
        body="$2"
        shift 2
        ;;
    -h | --help)
        usage
        ;;
    *)
        if [ -z "$type" ]; then
            type="$1"
        else
            msg="$1"
        fi
        shift
        ;;
    esac
done

# Validate type
if ! echo "$TYPES" | grep -qw "$type"; then
    echo "Invalid type: $type"
    echo "Valid types: $TYPES"
    exit 1
fi

if [ -z "$msg" ]; then
    echo "Message required"
    usage
fi

commit_msg=$(build_message "$type" "$scope" "$breaking" "$msg" "$body")
git commit -m "$commit_msg"
