#!/bin/bash

scriptversion=2605122356

DB_HOST="HIER DATEN EINTRAGEN"
DB_NAME="HIER DATEN EINTRAGEN"
DB_USER="HIER DATEN EINTRAGEN"
DB_PASS="HIER DATEN EINTRAGEN"

GLOBAL_TIMEOUT=90
CONNECT_TIMEOUT=5
CURL_TIMEOUT=10

MYSQL="mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -N -B"
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/OUTPUT"


header_date="$(date '+%d.%m.%Y %H:%M')"

run_init() {

$MYSQL 2>/dev/null <<EOF

CREATE TABLE IF NOT EXISTS providers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    url VARCHAR(1024) NOT NULL,
    enabled TINYINT(1) NOT NULL DEFAULT 1,
    sort_order INT NOT NULL DEFAULT 0,
    timeout_seconds INT NOT NULL DEFAULT 10,

    success_count BIGINT NOT NULL DEFAULT 0,
    failure_count BIGINT NOT NULL DEFAULT 0,
    last_success_at DATETIME NULL,
    last_failure_at DATETIME NULL,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS connectivity_checks (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    target VARCHAR(255) NOT NULL,
    enabled TINYINT(1) NOT NULL DEFAULT 1,
    sort_order INT NOT NULL DEFAULT 0,
    timeout_seconds INT NOT NULL DEFAULT 5,

    success_count BIGINT NOT NULL DEFAULT 0,
    failure_count BIGINT NOT NULL DEFAULT 0,
    last_success_at DATETIME NULL,
    last_failure_at DATETIME NULL,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS state (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL UNIQUE,
    value TEXT NULL,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS iplog (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,

    measured_at DATETIME NOT NULL,
    ip VARCHAR(45) NULL,

    status ENUM(
        'OK',
        'CHECK_FAILED',
        'OFFLINE',
        'INVALID_RESPONSE',
        'NO_RUN'
    ) NOT NULL DEFAULT 'OK',

    planned_provider_id INT NULL,
    used_provider_id INT NULL,
    attempts INT NOT NULL DEFAULT 0,

    msg TEXT NULL,
    raw_response TEXT NULL,

    planned_connectivity_id INT NULL,
    used_connectivity_id INT NULL,
    connectivity_attempts INT NOT NULL DEFAULT 0,
    connectivity_msg TEXT NULL,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_measured_at (measured_at),
    INDEX idx_ip (ip),
    INDEX idx_status (status),

    CONSTRAINT fk_iplog_planned_provider
        FOREIGN KEY (planned_provider_id)
        REFERENCES providers(id)
        ON DELETE SET NULL,

    CONSTRAINT fk_iplog_used_provider
        FOREIGN KEY (used_provider_id)
        REFERENCES providers(id)
        ON DELETE SET NULL,

    CONSTRAINT fk_iplog_planned_connectivity
        FOREIGN KEY (planned_connectivity_id)
        REFERENCES connectivity_checks(id)
        ON DELETE SET NULL,

    CONSTRAINT fk_iplog_used_connectivity
        FOREIGN KEY (used_connectivity_id)
        REFERENCES connectivity_checks(id)
        ON DELETE SET NULL
);

INSERT IGNORE INTO providers
(id, name, url, sort_order, timeout_seconds)
VALUES
(1, 'icanhazip.com', 'https://icanhazip.com', 1, 10),
(2, 'ifconfig.me', 'https://ifconfig.me/ip', 2, 10),
(3, 'api.ipify.org', 'https://api.ipify.org', 3, 10),
(4, 'checkip.amazonaws.com', 'https://checkip.amazonaws.com', 4, 10);

INSERT IGNORE INTO connectivity_checks
(id, name, target, sort_order, timeout_seconds)
VALUES
(1, 'Google DNS', '8.8.8.8', 1, 5),
(2, 'Quad9 DNS', '9.9.9.9', 2, 5),
(3, 'Cloudflare DNS', '1.1.1.1', 3, 5);

INSERT IGNORE INTO state
(name, value)
VALUES
('next_provider_index', '1'),
('next_connectivity_index', '1');

EOF

echo "Datenbankstruktur erfolgreich initialisiert."
}

now_sql() {
    date +"%Y-%m-%d %H:%M:%S"
}

sql_escape() {
    sed "s/'/''/g"
}

db_query() {
    $MYSQL -e "$1" 2>/dev/null
}

get_state() {
    local name="$1"
    local value

    value=$(db_query "SELECT value FROM state WHERE name='$name' LIMIT 1;")

    if [ -z "$value" ]; then
        echo "1"
    else
        echo "$value"
    fi
}

set_state() {
    local name="$1"
    local value="$2"

    db_query "
        INSERT INTO state (name, value)
        VALUES ('$name', '$value')
        ON DUPLICATE KEY UPDATE
            value=VALUES(value),
            updated_at=CURRENT_TIMESTAMP;
    "
}

update_connectivity_success() {
    local id="$1"

    db_query "
        UPDATE connectivity_checks
        SET success_count = success_count + 1,
            last_success_at = NOW()
        WHERE id = $id;
    "
}

update_connectivity_failure() {
    local id="$1"

    db_query "
        UPDATE connectivity_checks
        SET failure_count = failure_count + 1,
            last_failure_at = NOW()
        WHERE id = $id;
    "
}

update_provider_success() {
    local id="$1"

    db_query "
        UPDATE providers
        SET success_count = success_count + 1,
            last_success_at = NOW()
        WHERE id = $id;
    " 2>/dev/null
}

update_provider_failure() {
    local id="$1"

    db_query "
        UPDATE providers
        SET failure_count = failure_count + 1,
            last_failure_at = NOW()
        WHERE id = $id;
    " 2>/dev/null
}

insert_iplog() {
    local measured_at="$1"
    local ip="$2"
    local status="$3"
    local planned_provider_id="$4"
    local used_provider_id="$5"
    local attempts="$6"
    local msg="$7"
    local raw_response="$8"
    local planned_connectivity_id="$9"
    local used_connectivity_id="${10}"
    local connectivity_attempts="${11}"
    local connectivity_msg="${12}"

    msg=$(printf "%s" "$msg" | sql_escape)
    raw_response=$(printf "%s" "$raw_response" | sql_escape)
    connectivity_msg=$(printf "%s" "$connectivity_msg" | sql_escape)

    [ -z "$ip" ] && ip="NULL" || ip="'$ip'"
    [ -z "$planned_provider_id" ] && planned_provider_id="NULL"
    [ -z "$used_provider_id" ] && used_provider_id="NULL"
    [ -z "$planned_connectivity_id" ] && planned_connectivity_id="NULL"
    [ -z "$used_connectivity_id" ] && used_connectivity_id="NULL"

    db_query "
        INSERT INTO iplog (
            measured_at,
            ip,
            status,
            planned_provider_id,
            used_provider_id,
            attempts,
            msg,
            raw_response,
            planned_connectivity_id,
            used_connectivity_id,
            connectivity_attempts,
            connectivity_msg
        )
        VALUES (
            '$measured_at',
            $ip,
            '$status',
            $planned_provider_id,
            $used_provider_id,
            $attempts,
            NULLIF('$msg', ''),
            NULLIF('$raw_response', ''),
            $planned_connectivity_id,
            $used_connectivity_id,
            $connectivity_attempts,
            NULLIF('$connectivity_msg', '')
        );
    "
}

is_valid_ipv4() {
    local ip="$1"

    [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1

    IFS='.' read -r a b c d <<< "$ip"

    for part in "$a" "$b" "$c" "$d"; do
        [ "$part" -ge 0 ] 2>/dev/null || return 1
        [ "$part" -le 255 ] 2>/dev/null || return 1
    done

    return 0
}

is_valid_ip() {
    local ip="$1"

    if is_valid_ipv4 "$ip"; then
        return 0
    fi

    if [[ "$ip" =~ ^[0-9a-fA-F:]+$ ]] && [[ "$ip" == *:* ]]; then
        return 0
    fi

    return 1
}

load_connectivity_checks() {
    db_query "
        SELECT id, target, timeout_seconds
        FROM connectivity_checks
        WHERE enabled = 1
        ORDER BY sort_order, id;
    "
}

load_providers() {
    db_query "
        SELECT id, url, timeout_seconds
        FROM providers
        WHERE enabled = 1
        ORDER BY sort_order, id;
    "
}

rotate_list() {
    local list="$1"
    local start_id="$2"

    echo "$list" | awk -v start="$start_id" '
        BEGIN { found=0 }
        {
            lines[NR]=$0
            split($0,a,"\t")
            ids[NR]=a[1]
            if (a[1] == start) startpos=NR
        }
        END {
            if (!startpos) startpos=1

            for (i=startpos; i<=NR; i++) print lines[i]
            for (i=1; i<startpos; i++) print lines[i]
        }
    '
}

next_id_after() {
    local list="$1"
    local current_id="$2"

    echo "$list" | awk -v current="$current_id" '
        {
            split($0,a,"\t")
            ids[NR]=a[1]
            if (a[1] == current) pos=NR
        }
        END {
            if (!pos) {
                print ids[1]
            } else if (pos == NR) {
                print ids[1]
            } else {
                print ids[pos+1]
            }
        }
    '
}

check_connectivity() {
    local target="$1"
    local timeout="$2"

    ping -4 -c 1 -W "$timeout" "$target" >/dev/null 2>&1
}

fetch_ip() {
    local url="$1"
    local timeout="$2"

    curl -sS --max-time "$timeout" "$url" 2>/dev/null \
        | tr -d '\r' \
        | head -n 1 \
        | xargs
}

run_check() {
    MEASURED_AT="$(now_sql)"

    connectivity_list="$(load_connectivity_checks)"

    if [ -z "$connectivity_list" ]; then
        insert_iplog "$MEASURED_AT" "" "OFFLINE" "" "" 0 "Keine aktiven Connectivity-Checks vorhanden" "" "" "" 0 "Keine Connectivity-Checks vorhanden"
        echo "OFFLINE: Keine aktiven Connectivity-Checks vorhanden"
        exit 1
    fi

    provider_list="$(load_providers)"

    if [ -z "$provider_list" ]; then
        insert_iplog "$MEASURED_AT" "" "CHECK_FAILED" "" "" 0 "Keine aktiven IP-Provider vorhanden" "" "" "" 0 ""
        echo "CHECK_FAILED: Keine aktiven IP-Provider vorhanden"
        exit 1
    fi

    next_connectivity_id="$(get_state "next_connectivity_index")"
    next_provider_id="$(get_state "next_provider_index")"

    planned_connectivity_id="$next_connectivity_id"
    planned_provider_id="$next_provider_id"

    connectivity_deadline=$((SECONDS + GLOBAL_TIMEOUT))
    connectivity_attempts=0
    connectivity_ok=0
    used_connectivity_id=""
    connectivity_msg=""

    rotated_connectivity="$(rotate_list "$connectivity_list" "$next_connectivity_id")"

    while [ "$SECONDS" -lt "$connectivity_deadline" ]; do
        while IFS=$'\t' read -r cid target timeout; do
            [ -z "$cid" ] && continue

            connectivity_attempts=$((connectivity_attempts + 1))

            if check_connectivity "$target" "$timeout"; then
                connectivity_ok=1
                used_connectivity_id="$cid"
                update_connectivity_success "$cid"
                break 2
            else
                update_connectivity_failure "$cid"
                connectivity_msg="${connectivity_msg}Connectivity $target fehlgeschlagen; "
            fi

            [ "$SECONDS" -ge "$connectivity_deadline" ] && break 2
        done <<< "$rotated_connectivity"
    done

    new_next_connectivity_id="$(next_id_after "$connectivity_list" "$planned_connectivity_id")"
    set_state "next_connectivity_index" "$new_next_connectivity_id"

    if [ "$connectivity_ok" -ne 1 ]; then
        insert_iplog \
            "$MEASURED_AT" \
            "" \
            "OFFLINE" \
            "$planned_provider_id" \
            "" \
            0 \
            "Kein Connectivity-Check innerhalb ${GLOBAL_TIMEOUT}s erfolgreich" \
            "" \
            "$planned_connectivity_id" \
            "" \
            "$connectivity_attempts" \
            "$connectivity_msg"

        echo "OFFLINE: Kein Connectivity-Check erfolgreich"
        exit 1
    fi

    provider_deadline=$((SECONDS + GLOBAL_TIMEOUT))
    provider_attempts=0
    ip_ok=0
    used_provider_id=""
    final_ip=""
    raw_response=""
    provider_msg=""

    rotated_providers="$(rotate_list "$provider_list" "$next_provider_id")"

    while [ "$SECONDS" -lt "$provider_deadline" ]; do
        while IFS=$'\t' read -r pid url timeout; do
            [ -z "$pid" ] && continue

            provider_attempts=$((provider_attempts + 1))

            response="$(fetch_ip "$url" "$timeout")"
            raw_response="$response"

            if is_valid_ip "$response"; then
                ip_ok=1
                final_ip="$response"
                used_provider_id="$pid"
                update_provider_success "$pid"
                break 2
            else
                update_provider_failure "$pid"
                provider_msg="${provider_msg}Provider $url ungültig oder nicht erreichbar: $response; "
            fi

            [ "$SECONDS" -ge "$provider_deadline" ] && break 2
        done <<< "$rotated_providers"
    done

    new_next_provider_id="$(next_id_after "$provider_list" "$planned_provider_id")"
    set_state "next_provider_index" "$new_next_provider_id"

    if [ "$ip_ok" -eq 1 ]; then
        insert_iplog \
            "$MEASURED_AT" \
            "$final_ip" \
            "OK" \
            "$planned_provider_id" \
            "$used_provider_id" \
            "$provider_attempts" \
            "" \
            "$raw_response" \
            "$planned_connectivity_id" \
            "$used_connectivity_id" \
            "$connectivity_attempts" \
            "$connectivity_msg"

        echo "OK: $final_ip"
        exit 0
    else
        insert_iplog \
            "$MEASURED_AT" \
            "" \
            "CHECK_FAILED" \
            "$planned_provider_id" \
            "" \
            "$provider_attempts" \
            "Internet vorhanden, aber keine gültige IP innerhalb ${GLOBAL_TIMEOUT}s ermittelbar" \
            "$raw_response" \
            "$planned_connectivity_id" \
            "$used_connectivity_id" \
            "$connectivity_attempts" \
            "$connectivity_msg $provider_msg"

        echo "CHECK_FAILED: Internet vorhanden, aber keine gültige IP ermittelbar"
        exit 1
    fi
}

import_csv() {
    local file="$1"
    local delimiter="${2:-;}"

    if [ -z "$file" ]; then
        echo "Fehler: Keine CSV-Datei angegeben."
        exit 1
    fi

    if [ ! -f "$file" ]; then
        echo "Fehler: Datei nicht gefunden: $file"
        exit 1
    fi

    local count=0
    local skipped=0

    while IFS= read -r line || [ -n "$line" ]; do
        [ -z "$line" ] && continue

        IFS="$delimiter" read -r csv_date csv_time csv_value extra <<< "$line"

        if [ -z "$csv_date" ] || [ -z "$csv_time" ] || [ -z "$csv_value" ]; then
            skipped=$((skipped + 1))
            continue
        fi

        local measured_at="${csv_date} ${csv_time}:00"
        local ip=""
        local status=""
        local msg="CSV-Import"
        local raw_response="$csv_value"

        if is_valid_ip "$csv_value"; then
            ip="$csv_value"
            status="OK"
            msg="CSV-Import: IP erfolgreich"
        elif echo "$csv_value" | grep -qi "offline"; then
            status="OFFLINE"
            msg="CSV-Import: offline"
        elif echo "$csv_value" | grep -qi "nicht erreichbar"; then
            status="CHECK_FAILED"
            msg="CSV-Import: Prüfdienst nicht erreichbar"
        else
            status="INVALID_RESPONSE"
            msg="CSV-Import: unbekannter Wert"
        fi

        insert_iplog \
            "$measured_at" \
            "$ip" \
            "$status" \
            "" \
            "" \
            0 \
            "$msg" \
            "$raw_response" \
            "" \
            "" \
            0 \
            ""

        count=$((count + 1))
    done < "$file"

    echo "Import abgeschlossen: $count Zeilen importiert, $skipped Zeilen übersprungen."
}


summary_rows() {
    db_query "
        SELECT
            DATE_FORMAT(measured_at, '%Y-%m-%d %H:%i:%s') AS measured_at,
            IFNULL(ip, '') AS ip,
            status
        FROM iplog
        ORDER BY measured_at, id;
    " | awk -F '\t' '
        BEGIN {
            OFS="\t"
            active=0
        }

        function emit_period() {
            if (active == 1) {
                print begin_at, last_seen_at, current_ip, samples, offline_count, fail_count
            }
        }

        {
            measured_at=$1
            ip=$2
            status=$3

            if (status == "OK" && ip != "") {
                if (active == 0) {
                    active=1
                    current_ip=ip
                    begin_at=measured_at
                    last_seen_at=measured_at
                    samples=1
                    offline_count=0
                    fail_count=0
                    next
                }

                if (ip == current_ip) {
                    last_seen_at=measured_at
                    samples++
                    next
                }

                emit_period()

                current_ip=ip
                begin_at=measured_at
                last_seen_at=measured_at
                samples=1
                offline_count=0
                fail_count=0
                next
            }

            if (active == 1) {
                if (status == "OFFLINE") {
                    offline_count++
                } else if (status == "CHECK_FAILED" || status == "INVALID_RESPONSE" || status == "NO_RUN") {
                    fail_count++
                }
            }
        }

        END {
            emit_period()
        }
    '
}

summary_tabelle() {
    printf "%-19s %-19s %-15s %8s %8s %8s\n" "BEGIN_AT" "END_AT" "IP" "SAMPLES" "OFFLINE" "FAILS"
    summary_rows | awk -F '\t' '{
        printf "%-19s %-19s %-15s %8d %8d %8d\n", $1, $2, $3, $4, $5, $6
    }'
}

summary_text() {
    summary_rows | awk -F '\t' '
        function de_date(dt, parts, d, t) {
            split(dt, parts, " ")
            split(parts[1], d, "-")
            split(parts[2], t, ":")
            return d[3] "." d[2] "." d[1] " " t[1] ":" t[2] " Uhr"
        }

        function stats_text(samples, offline, fails, text) {
            text = samples "x online"

            if (offline > 0) {
                text = text ", " offline "x offline"
            }

            if (fails > 0) {
                text = text ", " fails "x Fehler"
            }

            return text
        }

        {
            printf "%s - %s: IP %s - (%s)\n", de_date($1), de_date($2), $3, stats_text($4, $5, $6)
        }
    '
}

summary_export_csv() {
    mkdir -p "$OUTPUT_DIR"

    local outfile="$OUTPUT_DIR/iplogger-export-$(date +%Y%m%dT%H%M).csv"

    {
        echo "begin_at;end_at;ip;samples;offline;fails"
        summary_rows | awk -F '\t' 'BEGIN { OFS=";" } { print $1, $2, $3, $4, $5, $6 }'
    } > "$outfile"

    echo "CSV exportiert: $outfile"
}


summary_detail_times_for_period() {
    local begin_at="$1"
    local end_at="$2"
    local ip="$3"

    db_query "
        SELECT DATE_FORMAT(measured_at, '%Y-%m-%d %H:%i:%s')
        FROM iplog
        WHERE status = 'OK'
          AND ip = '$(printf "%s" "$ip" | sql_escape)'
          AND measured_at BETWEEN '$begin_at' AND '$end_at'
        ORDER BY measured_at, id;
    "
}

summary_details_text() {
    summary_rows | while IFS=$'\t' read -r begin_at end_at ip samples offline fails; do
        [ -z "$begin_at" ] && continue

        awk -F '\t' -v begin_at="$begin_at" -v end_at="$end_at" -v ip="$ip" -v samples="$samples" -v offline="$offline" -v fails="$fails" '
            function de_date(dt, parts, d, t) {
                split(dt, parts, " ")
                split(parts[1], d, "-")
                split(parts[2], t, ":")
                return d[3] "." d[2] "." d[1] " " t[1] ":" t[2]
            }

            function stats_text(samples, offline, fails, text) {
                text = samples "x online"

                if (offline > 0) {
                    text = text ", " offline "x offline"
                }

                if (fails > 0) {
                    text = text ", " fails "x Fehler"
                }

                return text
            }

            BEGIN {
                printf "> %s Uhr - %s Uhr: IP %s (%s)\n", de_date(begin_at), de_date(end_at), ip, stats_text(samples, offline, fails)
            }
        '

        summary_detail_times_for_period "$begin_at" "$end_at" "$ip" | awk '
            function date_part(dt, parts, d) {
                split(dt, parts, " ")
                split(parts[1], d, "-")
                return d[3] "." d[2] "." d[1]
            }

            function time_part(dt, parts, t) {
                split(dt, parts, " ")
                split(parts[2], t, ":")
                return t[1] ":" t[2]
            }

            function flush_line() {
                if (line != "") {
                    print "    - " line
                    line = ""
                    col = 0
                }
            }

            function append_token(token) {
                if (line == "") {
                    line = token
                } else {
                    line = line " " token
                }
                col++
            }

            BEGIN {
                max_cols = 20
                col = 0
                current_date = ""
                line = ""
            }

            {
                d = date_part($0)
                t = time_part($0)

                if (d != current_date) {
                    flush_line()
                    current_date = d
                    append_token(d " " t)
                    next
                }

                if (col >= max_cols) {
                    flush_line()
                    append_token(d " " t)
                    next
                }

                append_token(t)
            }

            END {
                flush_line()
                printf "\n"
            }
        '
    done
}

summary_export_pdf() {
    local mode="$1"

    mkdir -p "$OUTPUT_DIR"

    local suffix=""
    if [ "$mode" = "details" ]; then
        suffix="-details"
    fi

    local base="$OUTPUT_DIR/iplogger-export-$(date +%Y%m%dT%H%M)$suffix"
    local txtfile="$base.txt"
    local pdffile="$base.pdf"

    {
        echo "IPLogger-Auswertung"
        echo "Erstellt am: $(date '+%d.%m.%Y %H:%M Uhr')"
        echo ""

        if [ "$mode" = "details" ]; then
            summary_details_text
        else
            summary_text
        fi
    } > "$txtfile"

    if command -v enscript >/dev/null 2>&1 && command -v ps2pdf >/dev/null 2>&1; then
        if [ "$mode" = "details" ]; then
            enscript --header="IPlogger Export Details|$header_date|Seite \$% von \$=" -q -f "LucidaConsole6" -o - "$txtfile" 2>/dev/null | ps2pdf - "$pdffile"
        else
            enscript --header="IPlogger Export|$header_date|Seite \$% von \$=" -q -f "LucidaConsole8" -o - "$txtfile" 2>/dev/null | ps2pdf - "$pdffile"
        fi

        rm -f "$txtfile"
        echo "PDF exportiert: $pdffile"
        return 0
    fi

    if command -v pandoc >/dev/null 2>&1; then
        pandoc "$txtfile" -o "$pdffile" >/dev/null 2>&1
        rm -f "$txtfile"
        echo "PDF exportiert: $pdffile"
        return 0
    fi

    echo "PDF konnte nicht erzeugt werden: enscript+ps2pdf oder pandoc fehlt."
    echo "TXT-Ersatz wurde erzeugt: $txtfile"
    return 1
}

run_summary() {
    case "$1" in
        tabelle|table|"")
            summary_tabelle
        ;;

        text)
            summary_text
        ;;

        export)
            case "$2" in
                csv)
                    summary_export_csv
                ;;

                pdf)
                    summary_export_pdf "$3"
                ;;

                *)
                    echo "Fehler: unbekanntes Exportformat: $2"
                    echo "Verwendung: $0 summary export csv|pdf [details]"
                    exit 1
                ;;
            esac
        ;;

        *)
            echo "Fehler: unbekannter summary-Befehl: $1"
            echo "Verwendung: $0 summary tabelle|text|export csv|export pdf"
            exit 1
        ;;
    esac
}

usage() {
    echo "Verwendung:"
    echo "  $0 check"
    echo "  $0 run"
    echo "  $0 import DATEI.csv [TRENNER]"
    echo "  $0 summary tabelle"
    echo "  $0 summary text"
    echo "  $0 summary export csv"
    echo "  $0 summary export pdf"
    echo "  $0 summary export pdf details"
    echo "  $0 init"
    echo ""
    echo "Beispiele:"
    echo "  $0 check"
    echo "  $0 import ipdb.csv ';'"
    echo "  $0 summary tabelle"
    echo "  $0 summary text"
    echo "  $0 summary export csv"
}

case "$1" in
    check|run)
        run_check
    ;;

    import)
        import_csv "$2" "${3:-;}"
    ;;

    summary)
        run_summary "$2" "$3" "$4"
    ;;

    init)
        run_init
    ;;

    *)
        usage
        exit 1
    ;;
esac