#!/bin/bash
# TSID SSH authentication wrapper script
# Switches to actual user after PIN input

# UTF-8 locale settings
export LANG=C.UTF-8
export LC_ALL=C.UTF-8

set -e

# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# Log functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Read server code
get_server_code() {
    local config_file="/etc/tsid/config.conf"
    local server_code_file="/etc/tsid/server_code"
    
    if [ -f "$server_code_file" ]; then
        cat "$server_code_file" 2>/dev/null
    elif [ -f "$config_file" ]; then
        grep "^server_code=" "$config_file" | cut -d'=' -f2 2>/dev/null
    fi
}

# Get PIN input
get_pin() {
    while true; do
        echo -n "Enter TSID PIN: "
        read -r pin
        
        if [ -z "$pin" ]; then
            log_error "Please enter a PIN."
            continue
        fi
        
        # Validate PIN format
        if ! [[ "$pin" =~ ^[0-9]+$ ]]; then
            log_error "PIN must contain digits only."
            continue
        fi
        
        echo "$pin"
        break
    done
}

# API call function
call_api() {
    local url="$1"
    local data="$2"
    
    curl -s -X POST "$url" \
        -H "Content-Type: application/json" \
        -d "$data" 2>/dev/null
}

# Extract JSON field
extract_field() {
    local json="$1"
    local field="$2"
    
    echo "$json" | grep -o "\"$field\":\"[^\"]*\"" | cut -d'"' -f4
}

# Request PIN authentication
request_pin_auth() {
    local server_code="$1"
    local pin="$2"
    local api_url="https://tpg.tsidcert.com/svr/auth/pin"
    
    log_info "Requesting PIN authentication..."
    
    local data="{\"server_code\":\"$server_code\",\"pin\":\"$pin\",\"pin_type\":\"T\"}"
    local response=$(call_api "$api_url" "$data")
    
    if [ -z "$response" ]; then
        log_error "Cannot connect to server."
        return 1
    fi
    
    # Check for errors
    local err_code=$(extract_field "$response" "errCode")
    if [ "$err_code" != "null" ] && [ -n "$err_code" ]; then
        case "$err_code" in
            "C4001")
                log_error "Server code error."
                ;;
            "C4006")
                log_error "PIN type error."
                ;;
            *)
                log_error "Unknown error: $err_code"
                ;;
        esac
        return 1
    fi
    
    # Validate response
    local is_svr_valid=$(extract_field "$response" "is_svr_valid")
    local is_tsid_valid=$(extract_field "$response" "is_tsid_valid")
    local state_code=$(extract_field "$response" "state_code")
    
    if [ "$is_svr_valid" != "true" ]; then
        log_error "No server access permission."
        return 1
    fi
    
    if [ "$is_tsid_valid" != "true" ]; then
        log_error "User does not have TSID installed."
        return 1
    fi
    
    if [ -z "$state_code" ] || [ "$state_code" = "null" ]; then
        log_error "Failed to receive state code."
        return 1
    fi
    
    log_success "PIN authentication request sent."
    echo "$state_code"
    return 0
}

# Check authentication status
check_auth_status() {
    local server_code="$1"
    local state_code="$2"
    local api_url="https://tpg.tsidcert.com/svr/auth/check"
    
    local data="{\"server_code\":\"$server_code\",\"state_code\":\"$state_code\"}"
    local response=$(call_api "$api_url" "$data")
    
    if [ -z "$response" ]; then
        log_error "Cannot connect to server."
        return 1
    fi
    
    # Check for errors
    local err_code=$(extract_field "$response" "errCode")
    if [ "$err_code" != "null" ] && [ -n "$err_code" ]; then
        case "$err_code" in
            "C4001")
                log_error "Server code error."
                ;;
            "C4008")
                log_error "State code error."
                ;;
            *)
                log_error "Unknown error: $err_code"
                ;;
        esac
        return 1
    fi
    
    # Check status
    local status=$(extract_field "$response" "status")
    local name=$(extract_field "$response" "name")
    local role=$(extract_field "$response" "role")
    local user_code=$(extract_field "$response" "user_code")
    local msg=$(extract_field "$response" "msg")
    
    case "$status" in
        "P")
            echo -n "."
            return 2  # still pending
            ;;
        "C")
            echo
            log_success "Authentication completed successfully!"
            log_info "User: $name"
            log_info "Role: $role"
            echo "$name:$role:$user_code"
            return 0
            ;;
        "B")
            echo
            log_error "Authenticated but user is not registered."
            if [ -n "$msg" ]; then
                log_error "Message: $msg"
            fi
            return 1
            ;;
        "R")
            echo
            log_error "Authentication rejected."
            if [ -n "$msg" ]; then
                log_error "Reason: $msg"
            fi
            return 1
            ;;
        *)
            echo
            log_error "Unknown authentication status: $status"
            return 1
            ;;
    esac
}

# Start user shell
start_user_shell() {
    local user_info="$1"
    local name=$(echo "$user_info" | cut -d':' -f1)
    local role=$(echo "$user_info" | cut -d':' -f2)
    
    # Check user exists
    if ! id "$name" &>/dev/null; then
        log_error "User $name not found."
        exit 1
    fi
    
    log_success "Logging in as $name."
    
    # Switch user and start shell
    exec sudo -u "$name" -i bash
}

# Main function
main() {
    echo "TSID SSH Authentication System"
    echo "=============================="
    echo
    
    # Check server code
    local server_code=$(get_server_code)
    if [ -z "$server_code" ]; then
        log_error "Server code not found."
        exit 1
    fi
    
    # Get PIN
    local pin=$(get_pin)
    
    # Request PIN authentication
    local state_code=$(request_pin_auth "$server_code" "$pin")
    if [ $? -ne 0 ]; then
        exit 1
    fi
    
    echo
    log_info "Please complete authentication on your mobile device..."
    echo
    
    # Poll authentication status
    local timeout=300  # 5 minutes
    local start_time=$(date +%s)
    
    while [ $(($(date +%s) - start_time)) -lt $timeout ]; do
        local result=$(check_auth_status "$server_code" "$state_code")
        local status=$?
        
        if [ $status -eq 0 ]; then
            # Auth success
            start_user_shell "$result"
            break
        elif [ $status -eq 1 ]; then
            # Auth failed
            exit 1
        elif [ $status -eq 2 ]; then
            # Pending
            sleep 1
            continue
        fi
    done
    
    # Timeout
    echo
    log_error "Authentication timeout (5 min). Please try again."
    exit 1
}

# Call main only when script is executed directly
if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
    main "$@"
fi
