#!/usr/bin/env bash

# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

#
# "Libraries"
#

[ -z "$DOCKER_FINANCE_CONTAINER_REPO" ] && exit 1
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_utils.bash" || exit 1

#
# Execute
#

if [ $UID -lt 1000 ]; then
  lib_utils::die_fatal "Do not run as root or system user!"
fi

# IMPORTANT: keep umask for security
umask go-rwx

# Top-level caller
global_basename="dfi"
declare -rx global_basename

# Dependencies
if [ -z "$EDITOR" ]; then
  lib_utils::die_fatal "Shell EDITOR is not set, export EDITOR in your shell"
fi

# Globals (argument delimiters)
# NOTE: argument parsing will use this unified format
[ -z "$global_arg_delim_1" ] && declare -rx global_arg_delim_1="/"
[ -z "$global_arg_delim_2" ] && declare -rx global_arg_delim_2="="
[ -z "$global_arg_delim_3" ] && declare -rx global_arg_delim_3=","

# "Constructor" for finance environment
function lib_finance::finance()
{
  # Ensure profile/subprofile
  [[ ! $1 =~ $global_arg_delim_1 ]] && return 2
  IFS="$global_arg_delim_1" read -ra _profile <<<"$1"
  declare -grx global_parent_profile="${_profile[0]}"
  declare -grx global_child_profile="${_profile[1]}"

  # Subcommand
  declare -grx global_arg_subcommand="$2"

  # Globals (convenience)
  declare -grx global_usage="$global_basename ${global_parent_profile}${global_arg_delim_1}${global_child_profile} $global_arg_subcommand"

  # Globals (implementation)
  [ -z "$DOCKER_FINANCE_CONTAINER_FLOW" ] && lib_utils::die_fatal
  declare -grx global_child_profile_flow="${DOCKER_FINANCE_CONTAINER_FLOW}/profiles/${global_parent_profile}/${global_child_profile}"

  if [ ! -d "$global_child_profile_flow" ]; then
    lib_utils::die_fatal "Profiles '${global_parent_profile}${global_arg_delim_1}${global_child_profile}' do not exist!"
  fi

  declare -grx global_child_profile_journal="${global_child_profile_flow}/all-years.journal"
  declare -grx global_hledger_cmd=("hledger" "-f" "$global_child_profile_journal")

  # Globals (configuration)
  declare -grx global_conf_fetch="${global_child_profile_flow}/docker-finance.d/fetch/fetch.yaml"
  declare -grx global_conf_hledger="${global_child_profile_flow}/docker-finance.d/hledger/hledger.conf"
  declare -grx global_conf_meta="${global_child_profile_flow}/docker-finance.d/meta/meta.csv"
  declare -grx global_conf_subscript="${global_child_profile_flow}/docker-finance.d/shell/subscript.bash"
  declare -grx global_conf_visidata="${global_child_profile_flow}/docker-finance.d/visidata" # dir for config/addons

  # Implementation "libraries" (requires previously set globals)
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_edit.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_fetch.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_hledger.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_meta.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_plugins.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_reports.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_root.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_taxes.bash" || exit 1
  source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_times.bash" || exit 1
}

#
# Library implementation facades
#

# The "all" command which fetches, imports, generates taxes and reports for given year
function lib_finance::all()
{
  time lib_finance::__all "$@"
  lib_utils::catch $?
}

function lib_finance::__all()
{
  local _arg="$1"
  local _usage="
\e[32mDescription:\e[0m

  The 'all' command which fetches and imports accounts, and then generates taxes and reports

\e[32mUsage:\e[0m

  $ $global_usage year${global_arg_delim_2}<year>

\e[32mExamples:\e[0m

  \e[37;2m# Fetch, import, generates taxes and reports for year 2023\e[0m
  $ $global_usage year${global_arg_delim_2}2023
"

  if [ "$#" -gt 1 ]; then
    lib_utils::die_usage "$_usage"
  fi

  # Get/Set year
  if [ ! -z "$_arg" ]; then
    if [[ ! "$_arg" =~ ^year[s]?${global_arg_delim_2} ]]; then
      lib_utils::die_usage "$_usage"
    fi

    # Parse key for value
    local _key="${_arg%${global_arg_delim_2}*}"
    local _len="$((${#_key} + 1))"
    if [[ "$_key" =~ ^year[s]?$ ]]; then
      local _arg_year="${_arg:${_len}}"
      if [ -z "$_arg_year" ]; then
        lib_utils::die_usage "$_usage"
      fi
    fi
  else
    _arg_year="$(date +%Y)"
  fi

  # Execute
  lib_utils::print_custom "\n\t\e[1mFetching 'all' for year ${_arg_year}\e[0m\n"

  (lib_finance::fetch year${global_arg_delim_2}"${_arg_year}" all=all) \
    && (lib_finance::import year${global_arg_delim_2}"${_arg_year}") \
    && (lib_finance::taxes year${global_arg_delim_2}"${_arg_year}" all=all) \
    && (lib_finance::reports year${global_arg_delim_2}"${_arg_year}" all=all)

  [ $? -eq 0 ] \
    && lib_utils::print_custom "\n\t\e[1mFetching 'all' for year ${_arg_year} completed successfully!\e[0m\n"

  return $?
}

function lib_finance::meta()
{
  lib_meta::meta "$@"
  lib_utils::catch $?
}

function lib_finance::fetch()
{
  lib_fetch::fetch "$@"
  lib_utils::catch $?
}

function lib_finance::import()
{
  lib_hledger::hledger-import "$@"
  lib_utils::catch $?
}

function lib_finance::hledger()
{
  lib_hledger::hledger-cli "$@"
  lib_utils::catch $?
}

function lib_finance::hledger-ui()
{
  lib_hledger::hledger-ui "$@"
  lib_utils::catch $?
}

function lib_finance::hledger-vui()
{
  lib_hledger::hledger-vui "$@"
  lib_utils::catch $?
}

function lib_finance::hledger-web()
{
  lib_hledger::hledger-web "$@"
  lib_utils::catch $?
}

function lib_finance::plugins()
{
  lib_plugins::plugins "$@"
  lib_utils::catch $?
}

function lib_finance::reports()
{
  lib_reports::reports "$@"
  lib_utils::catch $?
}

function lib_finance::root()
{
  lib_root::root "$@"
  lib_utils::catch $?
}

function lib_finance::taxes()
{
  lib_taxes::taxes "$@"
  lib_utils::catch $?
}

function lib_finance::times()
{
  lib_times::times "$@"
  lib_utils::catch $?
}

function lib_finance::edit()
{
  lib_edit::edit "$@"
  lib_utils::catch $?
}

# vim: sw=2 sts=2 si ai et
