#!/bin/bash

[[ ! -d "$CONFIG_DIR" ]] && mkdir -p "$CONFIG_DIR"
if [[ ! -f "$CONFIG_FILE" || ! -s "$CONFIG_FILE" ]]; then
    echo "{}" > "$CONFIG_FILE"
    NEEDS_SETUP=1
fi

validate_config() {
    local is_valid=true
    local temp_file=$(mktemp)

    local keys
    keys=$(jq -r 'keys[]' "$CONFIG_FILE")

    for key in $keys; do
        if [[ -z "${ALLOWED_KEYS[$key]}" ]]; then
            jq "del(.\"$key\")" "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
        else
            local value
            value=$(jq -r --arg key "$key" '.[$key]' "$CONFIG_FILE")
            if ! [[ "$value" =~ ${ALLOWED_KEYS[$key]} ]]; then
                jq "del(.\"$key\")" "$CONFIG_FILE" > "$temp_file" && mv "$temp_file" "$CONFIG_FILE"
            fi
        fi
    done

    for req_key in "${REQUIRED_KEYS[@]}"; do
        if ! jq -e --arg key "$req_key" 'has($key)' "$CONFIG_FILE" >/dev/null; then
            NEEDS_SETUP=1
        fi
    done
}

get_value() {
    local key="$1"
    jq -r ".${key} // empty" "$CONFIG_FILE"
}

get_starting_with() {
    local prefix="$1"
    jq -r "to_entries | map(select(.key | startswith(\"$prefix\"))) | from_entries" "$CONFIG_FILE"
}

set_value() {
    local key="$1"
    local value="$2"

    if [[ -z "$key" || -z "$value" ]]; then
        echo "Usage: $0 set <key> <value>"
        exit 1
    fi
    if [[ -z "${ALLOWED_KEYS[$key]}" ]]; then
        echo "Invalid key: $key"
        exit 1
    fi
    if ! [[ "$value" =~ ${ALLOWED_KEYS[$key]} ]]; then
        echo "Invalid value for $key: $value"
        exit 1
    fi

    jq ". + {\"$key\": \"$value\"}" "$CONFIG_FILE" > temp.json && mv temp.json "$CONFIG_FILE"
}

remove_value() {
    local key="$1"
    jq "del(.${key})" "$CONFIG_FILE" > temp.json && mv temp.json "$CONFIG_FILE"
    echo "Removed $key."
}

list_values() {
    cat "$CONFIG_FILE" | jq .
}

setup_domain() {
    local domain
    local service
    local auth

    if [[ -z "$SERVICE" ]]; then
        while true; do
            echo -ne "${CYAN}Choose a service (${valid_services[*]}): ${RESET}"
            read service

            if [[ " ${valid_services[*]} " =~ " $service " ]]; then
                break
            else
                echo -e "${RED}Invalid service. Please choose from: ${valid_services[*]}${RESET}"
            fi
        done
        
        set_value "SERVICE" "$service"
    else
        service="$SERVICE"
    fi

    if [[ "$service" == "zipline" ]]; then
        while true; do
            echo -ne "${CYAN}Enter the domain (e.g. example.com): ${RESET}"
            read domain

            if [[ "$domain" =~ ^[a-zA-Z0-9.-]+$ ]]; then
                break
            else
                echo -e "${RED}Invalid domain format. Please enter a valid domain (e.g. example.com).${RESET}"
            fi
        done

        domain="https://$domain"
        domain="${domain%/}"
        [[ "$domain" != */api/upload ]] && domain="$domain/api/upload"

        set_value "DOMAIN" "$domain"
        echo -e "${GREEN}Domain set to: $domain${RESET}"

        # extra options for zipline
        echo -ne "${CYAN}Do you want to change upload options? (y/n): ${RESET}"
        read change_options
        while ! [[ "$change_options" =~ ^(y|Y|n|N|true|false)$ ]]; do
            echo -e "${RED}Invalid option. Please enter 'y' or 'n'.${RESET}"
            echo -ne "${CYAN}Do you want to change upload options? (y/n): ${RESET}"
            read change_options
        done

        if [[ "$change_options" =~ ^(y|Y)$ ]]; then
            echo -ne "${CYAN}Enter the number of max views (default: 0): ${RESET}"
            read max_views
            while [[ -n "$max_views" && ! "$max_views" =~ ^[0-9]+$ ]]; do
                echo -e "${RED}Invalid number. Please enter a valid number.${RESET}"
                echo -ne "${CYAN}Enter the number of views (default: 0): ${RESET}"
                read max_views
            done
            if [[ -n "$max_views" && "$max_views" -ne 0 ]]; then
                set_value "x-zipline-max-views" "$max_views"
                echo -e "${GREEN}Max views set to: $max_views${RESET}"
            else
                echo -e "${YELLOW}Using default max views (0). Not saving.${RESET}"
            fi

            echo -ne "${CYAN}Enter the image compression percent (default: 0): ${RESET}"
            read compression_percent
            while [[ -n "$compression_percent" && ! "$compression_percent" =~ ^[0-9]+$ ]]; do
                echo -e "${RED}Invalid number. Please enter a valid number.${RESET}"
                echo -ne "${CYAN}Enter the image compression percent (default: 0): ${RESET}"
                read compression_percent
            done
            if [[ -n "$compression_percent" && "$compression_percent" -ne 0 ]]; then
                set_value "x-zipline-image-compression-percent" "$compression_percent"
                echo -e "${GREEN}Image compression percent set to: $compression_percent${RESET}"
            else
                echo -e "${YELLOW}Using default compression percent (0). Not saving.${RESET}"
            fi

            echo -ne "${CYAN}Do you want to keep the original name on download? (y/n): ${RESET}"
            read keep_original_name
            while [[ -n "$keep_original_name" && ! "$keep_original_name" =~ ^(y|Y|n|N|true|false)$ ]]; do
                echo -e "${RED}Invalid option. Please enter 'y' or 'n'.${RESET}"
                echo -ne "${CYAN}Do you want to keep the original name on download? (y/n): ${RESET}"
                read keep_original_name
            done
            if [[ "$keep_original_name" =~ ^(y|Y)$ ]]; then
                keep_original_name="true"
            else
                keep_original_name="false"
            fi
            set_value "x-zipline-original-name" "$keep_original_name"
            echo -e "${GREEN}Keep original name set to: $keep_original_name${RESET}"

            echo -ne "${CYAN}What do you want the name format to be? (default: date): ${RESET}"
            read name_format
            while [[ -n "$name_format" && ! "$name_format" =~ ^(date|random|uuid|name|gfycat)$ ]]; do
                echo -e "${RED}Invalid option. Please enter 'date', 'random', 'uuid', 'name', or 'gfycat'.${RESET}"
                echo -ne "${CYAN}What do you want the name format to be? (default: date): ${RESET}"
                read name_format
            done
            if [[ -n "$name_format" ]]; then
                set_value "x-zipline-format" "$name_format"
                echo -e "${GREEN}Name format set to: $name_format${RESET}"
            else
                echo -e "${YELLOW}Using default name format (date). Not saving.${RESET}"
            fi

            echo -e "${GREEN}Upload options set successfully.${RESET}"
        fi
    fi

    while [[ -z "$auth" ]]; do
        echo -ne "${CYAN}Enter your auth token: ${RESET}"
        read auth
        [[ -z "$auth" ]] && echo -e "${RED}Auth token cannot be empty. Please enter a valid token.${RESET}"
    done

    set_value "${service}_auth" "$auth"
    echo -e "${GREEN}Auth token set successfully.${RESET}"
}

setup_config() {
    local save_dir
    local show_capture_preview
    local show_notifications
    local save_images
    local default_option
	local snip_sound

    echo -ne "${CYAN}What do you want the default option to be? (upload/save/copy): ${RESET}"
    read default_option
    while ! [[ "$default_option" =~ ^(upload|save|copy)$ ]]; do
        echo -e "${RED}Invalid option. Please enter 'upload', 'save', or 'copy'.${RESET}"
        echo -ne "${CYAN}Choose (upload/save/copy): ${RESET}"
        read default_option
    done
    set_value "DEFAULT_OPTION" "$default_option"

    [[ "$default_option" == "upload" ]] && setup_domain

    echo -ne "${CYAN}Do you want to save images? (y/n): ${RESET}"
    read save_images
    while ! [[ "$save_images" =~ ^(y|Y|n|N|true|false)$ ]]; do
        echo -e "${RED}Invalid option. Please enter 'y' or 'n'.${RESET}"
        echo -ne "${CYAN}Do you want to save images? (y/n): ${RESET}"
        read save_images
    done
    [[ "$save_images" =~ ^(y|Y)$ ]] && save_images="true" || save_images="false"
    set_value "SAVE_IMAGES" "$save_images"

    if [[ "$save_images" == "true" ]]; then
        echo -ne "${CYAN}Enter the directory to save images (default: $HOME/Pictures): ${RESET}"
        read save_dir
        save_dir="${save_dir:-$HOME/Pictures}"
        while [[ ! -d "$save_dir" ]]; do
            echo -e "${RED}Directory does not exist. Please enter a valid directory.${RESET}"
            echo -ne "${CYAN}Enter the directory to save images: ${RESET}"
            read save_dir
        done
        set_value "SAVE_DIR" "$save_dir"
    fi  

    echo -ne "${CYAN}Do you want to show capture notifications? (y/n): ${RESET}"
    read show_notifications
    while ! [[ "$show_notifications" =~ ^(y|Y|n|N|true|false)$ ]]; do
        echo -e "${RED}Invalid option. Please enter 'y' or 'n'.${RESET}"
        echo -ne "${CYAN}Do you want to show capture notifications? (y/n): ${RESET}"
        read show_notifications
    done
    [[ "$show_notifications" =~ ^(y|Y)$ ]] && show_notifications="true" || show_notifications="false"
    set_value "SHOW_NOTIFICATIONS" "$show_notifications"

    echo -ne "${CYAN}Do you want to play a sound after upload? (y/n): ${RESET}"
    read snip_sound
    while ! [[ "$snip_sound" =~ ^(y|Y|n|N|true|false)$ ]]; do
        echo -e "${RED}Invalid option. Please enter 'y' or 'n'.${RESET}"
        echo -ne "${CYAN}Do you want to play a sound after upload? (y/n): ${RESET}"
        read snip_sound
    done
    [[ "$snip_sound" =~ ^(y|Y)$ ]] && snip_sound="true" || snip_sound="false"
    set_value "SNIP_SOUND" "$snip_sound"

    echo -ne "${CYAN}Do you want to show capture preview? (y/n): ${RESET}"
    read show_capture_preview
    while ! [[ "$show_capture_preview" =~ ^(y|Y|n|N|true|false)$ ]]; do
        echo -e "${RED}Invalid option. Please enter 'y' or 'n'.${RESET}"
        echo -ne "${CYAN}Do you want to show capture preview? (y/n): ${RESET}"
        read show_capture_preview
    done
    [[ "$show_capture_preview" =~ ^(y|Y)$ ]] && show_capture_preview="true" || show_capture_preview="false"
    set_value "SHOW_CAPTURE_PREVIEW" "$show_capture_preview"

    echo -e "${GREEN}${BOLD}Configuration completed successfully!${RESET}"
    echo -e "${YELLOW}You can change the configuration later by running the script with the --config option.${RESET}"

    [[ "$show_capture_preview" == "true" ]] && setup_venv
}