#!/bin/bash

LOG_DIR="/var/log/rename"
LOG_FILE="$LOG_DIR/anime-batch-dry-$(date '+%Y%m%d-%H%M%S').log"

# Log function
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# Usage: ./script.sh [directory]
# If no directory specified, uses current directory
get_showname() {
    local filename="$1"

    if [ -z "$filename" ]; then
        echo "Usage: clean_basename 'filename.mkv'" >&2
        return 1
    fi

    # Extract just the filename without path
    filename=$(basename "$filename")

    filename=$(echo "$filename" | sed 's/\[[^]]*\]//g; s/^[[:space:]]*//; s/[[:space:]]*$//')

    # Extract episode (e.g., 001)
    if [[ $filename =~ ([0-9]{3}) ]]; then
        episode="${BASH_REMATCH[1]}"

        # Get the part before the season/episode
        show_part="${filename%%$episode*}"

        # Replace dots with spaces and clean up
        show_name=$(echo "$show_part" | sed 's/\.\./\./g' | sed 's/\./ /g' | sed 's/ *$//')

        # Remove trailing " -"
        show_name="${show_name% -}"

        # Return formatted filename
        echo "${show_name}"
    else
        echo "Error: Could not find season/episode pattern in filename" >&2
        return 1
    fi
}

get_season() {
    local filename="$1"

    echo "Absolute"
}

clean_basename() {
    local filename="$1"

    if [ -z "$filename" ]; then
        echo "Usage: clean_basename 'filename.mkv'" >&2
        return 1
    fi

    # Extract just the filename without path
    filename=$(basename "$filename")

    # Get file extension
    extension="${new_filename##*.}"

    new_filename=$(echo "$filename" | sed 's/\[[^]]*\]//g; s/^[[:space:]]*//; s/[[:space:]]*$//')

    # Extract episode (e.g., 001)
    if [[ $filename =~ ([0-9]{3}) ]]; then
        episode="${BASH_REMATCH[1]}"

        # Get the part before the season/episode
        show_part="${filename%%$episode*}"

        # Replace dots with spaces and clean up
        show_name=$(echo "$show_part" | sed 's/\.\./\./g' | sed 's/\./ /g' | sed 's/ *$//')

        # Remove trailing " -"
        show_name="${show_name% -}"

        # Return formatted filename
        echo "${show_name} - ${episode}" #.${extension}"
    else
        echo "${new_filename}.${extension}"
        #echo "Error: Could not find season/episode pattern in filename" >&2
        #return 1
    fi
}

get_file_extension() {
    local filename="$1"

    if [ -z "$filename" ]; then
        echo "Usage: clean_basename 'filename.mkv'" >&2
        return 1
    fi

    # Extract just the filename without path
    filename=$(basename "$filename")

    extension="${filename##*.}"

    echo $extension
}

get_resolution() {
    local input="$1"
    local width=$(ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=p=0 "$input")
    local height=$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=p=0 "$input")

    # Remove any non-numeric characters (commas, etc.)
    width=$(echo "$width" | tr -cd '0-9')
    height=$(echo "$height" | tr -cd '0-9')

    # Validate we got numeric values
    if [ -z "$width" ] || [ -z "$height" ] || [ "$width" -eq 0 ] || [ "$height" -eq 0 ]; then
        echo "Unknown"
        return 1
    fi

    # Check if video is interlaced
    local field_order=$(ffprobe -v error -select_streams v:0 -show_entries stream=field_order -of csv=p=0 "$input")
    local is_interlaced=false

    if [[ "$field_order" != "progressive" ]] && [[ "$field_order" != "unknown" ]] && [[ -n "$field_order" ]]; then
        is_interlaced=true
    fi

    # Calculate aspect ratio to detect letterboxing
    local aspect_ratio=$(awk "BEGIN {printf \"%.2f\", $width/$height}")

    # Determine resolution number
    local res_number=""

    # Detect letterboxed content by checking if aspect ratio is significantly wider than 16:9 (1.78)
    if awk "BEGIN {exit !($aspect_ratio > 2.0)}"; then
        # Likely letterboxed - estimate source resolution from width
        if [ "$width" -ge 3800 ]; then
            res_number="2160"
        elif [ "$width" -ge 2500 ]; then
            res_number="1440"
        elif [ "$width" -ge 1900 ]; then
            res_number="1080"
        elif [ "$width" -ge 1260 ]; then
            res_number="720"
        elif [ "$width" -ge 700 ]; then
            res_number="576"
        elif [ "$width" -ge 640 ]; then
            res_number="480"
        else
            res_number="$height"
        fi
    else
        # Not letterboxed - use actual height
        case $height in
            2160) res_number="2160" ;;
            1440) res_number="1440" ;;
            1080) res_number="1080" ;;
            720)  res_number="720"  ;;
            576)  res_number="576"  ;;
            480)  res_number="480"  ;;
            *)    res_number="$height" ;;
        esac
    fi

    # Add 'i' for interlaced, 'p' for progressive
    if [ "$is_interlaced" = true ]; then
        echo "${res_number}i"
    else
        echo "${res_number}p"
    fi
}

get_video_codec() {
    local input="$1"
    local codec=$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 "$input")

    # Remove any commas or whitespace
    codec=$(echo "$codec" | tr -d ', ' | tr -d '\n')

    case "$codec" in
        h264)
            echo "x264"
            ;;
        hevc|h265)
            echo "x265"
            ;;
        av1)
            echo "AV1"
            ;;
        vp9)
            echo "VP9"
            ;;
        vp8)
            echo "VP8"
            ;;
        mpeg4)
            echo "MPEG4"
            ;;
        mpeg2video)
            echo "MPEG2"
            ;;
        *)
            # Uppercase and clean unknown codecs
            echo "${codec^^}"
            ;;
    esac
}

get_colour_depth() {
    local input="$1"
    local bit_depth=$(ffprobe -v error -select_streams v:0 -show_entries stream=bits_per_raw_sample -of csv=p=0 "$input")

    # Clean the output - remove commas, whitespace, and check for N/A
    bit_depth=$(echo "$bit_depth" | tr -d ', ' | tr -d '\n')

    if [[ -z "$bit_depth" ]] || [[ "$bit_depth" == "N/A" ]] || [[ "$bit_depth" == "0" ]]; then
        # Fallback to pix_fmt if bits_per_raw_sample is not available
        local pix_fmt=$(ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of csv=p=0 "$input")
        pix_fmt=$(echo "$pix_fmt" | tr -d ', ' | tr -d '\n')

        if [[ "$pix_fmt" == *"10"* ]]; then
            echo "10bit"
        elif [[ "$pix_fmt" == *"12"* ]]; then
            echo "12bit"
        else
            echo "8bit"
        fi
    else
        echo "${bit_depth}bit"
    fi
}

get_hdr_status() {
    local input="$1"
    local color_transfer=$(ffprobe -v error -select_streams v:0 -show_entries stream=color_transfer -of csv=p=0 "$input")

    if [[ "$color_transfer" == "smpte2084" ]] || [[ "$color_transfer" == "arib-std-b67" ]]; then
        echo "HDR"
    else
        echo "SDR"
    fi
}

get_audio_tracks() {
    local input="$1"
    ffprobe -v error -select_streams a -show_entries stream=index,codec_name,profile,channels:stream_tags=language -of csv=p=0 "$input" | while IFS=',' read -r index codec profile channels lang; do
        [[ -z "$lang" ]] && lang="und"

        # Check for codec variants
        case "$codec" in
            aac)
                if [[ "$profile" =~ HE|SBR ]]; then
                    codec="heaac"
                fi
                ;;
            dts)
                if [[ "$profile" =~ "DTS-HD MA" ]]; then
                    codec="dts-hdma"
                elif [[ "$profile" =~ "DTS-HD HRA" ]]; then
                    codec="dts-hd"
                elif [[ "$profile" =~ "DTS:X" ]]; then
                    codec="dtsx"
                fi
                ;;
            truehd)
                if [[ "$profile" =~ "Atmos" ]]; then
                    codec="truehd-atmos"
                fi
                ;;
        esac

        echo "$index:$codec:$channels:$lang"
    done
}

format_audio_info() {
    local input="$1"
    local tracks=$(get_audio_tracks "$input")

    # Store tracks in arrays
    local -a codecs languages channel_counts
    while IFS=':' read -r index codec channels lang; do
        codecs+=("$codec")
        channel_counts+=("$channels")
        languages+=("$lang")
    done <<< "$tracks"

    # Check if all codecs and channels are the same
    local all_same=true
    local first_codec="${codecs[0]}"
    local first_channels="${channel_counts[0]}"
    for i in "${!codecs[@]}"; do
        if [[ "${codecs[$i]}" != "$first_codec" ]] || [[ "${channel_counts[$i]}" != "$first_channels" ]]; then
            all_same=false
            break
        fi
    done

    # Format output
    if [[ "$all_same" == true ]] && [[ ${#codecs[@]} -gt 1 ]]; then
        local channel_suffix=$(format_channels "$first_channels")
        echo "Dual Audio ${first_codec^^}${channel_suffix}"
    else
        local output=""
        for i in "${!codecs[@]}"; do
            local channel_suffix=$(format_channels "${channel_counts[$i]}")
            [[ -n "$output" ]] && output+=" "
            output+="${languages[$i]^^} ${codecs[$i]^^}${channel_suffix}"
        done
        echo "$output"
    fi
}

format_channels() {
    local channels="$1"
    case "$channels" in
        2) echo "" ;;      # Stereo - no suffix
        6) echo " 51" ;;   # 5.1
        8) echo " 71" ;;   # 7.1
        *) echo "" ;;      # Other channel counts - no suffix
    esac
}

generate_output_filename() {
    local input="$1"
    local resolution="$2"
    local video_codec="$3"
    local colour_depth="$4"
    local hdr="$5"
    local audio="$6"
    local extension="$7"

    # Remove common video extensions from basename
    local basename=$(basename "$input" | sed 's/\.\(mkv\|mp4\|avi\|mov\|m4v\|flv\|wmv\|webm\)$//')

    echo "${basename} [${resolution}] [${video_codec} ${colour_depth} ${hdr}] [${audio}].${extension}"
}

create_output_directory() {
	local path="$1"

	mkdir -p "$path"
}

rename_video_file() {
    local input="$1"          # e.g. /path/to/Movie (2023).mkv
    local path="$2"           # Target directory (with trailing slash)
    local output="$3"         # New filename only, e.g. Movie.2023.1080p.mkv

    create_output_directory "$OUTPUT_PATH"

    local full_output_path="${path}${output}"
    local src_dir="$(dirname "$input")"
    local src_base="$(basename "$input")"
    local src_name="${src_base%.*}"    # original basename without extension
    local dst_name="${output%.*}"      # new basename without extension

    # --- 1. Sanity check on source video ---
    if [[ ! -f "$input" ]]; then
        log "ERROR: Source video file not found: $input"
        echo "ERROR: Source video file not found: $input"
        return 1
    fi
    if [[ ! -r "$input" ]]; then
        log "ERROR: Source video file not readable: $input"
        echo "ERROR: Source video file not readable: $input"
        return 1
    fi

    # --- 2. Move/rename the main video file ---
    log "Moving video: $(basename "$input") -> $output"
    echo "Moving video file..."

    if mv -v "$input" "$full_output_path"; then
        log "SUCCESS: Video moved to $output"
    else
        log "ERROR: Failed to move video file"
        echo "ERROR: Failed to move video file"
        return 1
    fi

    # --- 3. Move/rename .nfo if present ---
    if [[ -f "${src_dir}/${src_name}.nfo" ]]; then
        local dst_nfo="${path}${dst_name}.nfo"
        if mv -v "${src_dir}/${src_name}.nfo" "$dst_nfo"; then
            log "SUCCESS: ${src_name}.nfo → ${dst_name}.nfo"
        else
            log "WARNING: Failed to move .nfo (continuing anyway)"
            echo "WARNING: Could not move .nfo file"
        fi
    fi

    # --- 4. Move/rename -thumb.jpg if present ---
    if [[ -f "${src_dir}/${src_name}-thumb.jpg" ]]; then
        local dst_thumb="${path}${dst_name}-thumb.jpg"
        if mv -v "${src_dir}/${src_name}-thumb.jpg" "$dst_thumb"; then
            log "SUCCESS: ${src_name}-thumb.jpg → ${dst_name}-thumb.jpg"
        else
            log "WARNING: Failed to move -thumb.jpg"
            echo "WARNING: Could not move thumbnail"
        fi
    fi

    # --- 5. Move/rename .trickplay folder (with all contents) if present ---
    if [[ -d "${src_dir}/${src_name}.trickplay" ]]; then
        local dst_trickplay="${path}${dst_name}.trickplay"
        if mv -v "${src_dir}/${src_name}.trickplay" "$dst_trickplay"; then
            log "SUCCESS: ${src_name}.trickplay/ → ${dst_name}.trickplay/"
        else
            log "WARNING: Failed to move .trickplay folder"
            echo "WARNING: Could not move .trickplay folder"
        fi
    fi

    log "SUCCESS: All available assets moved/renamed to new basename"
    echo "Rename/move completed successfully"
    return 0
}

process_file() {
    local INPUT="$1"
    local file_num="$2"
    local total_files="$3"

    log "Starting: $INPUT"
    echo ""
    echo "========================================"
    echo "Processing file $file_num of $total_files: $(basename "$INPUT")"
    echo "========================================"

    # Naming
    showname=$(get_showname "$INPUT")
    season=$(get_season "$INPUT")
    new_name=$(clean_basename "$INPUT")

    # Extract information
    RESOLUTION=$(get_resolution "$INPUT")
    VIDEO_CODEC=$(get_video_codec "$INPUT")
    COLOUR_DEPTH=$(get_colour_depth "$INPUT")
    HDR=$(get_hdr_status "$INPUT")
    AUDIO=$(format_audio_info "$INPUT")
    EXTENSION=$(get_file_extension "$INPUT")
    OUTPUT=$(generate_output_filename "$new_name" "$RESOLUTION" "$VIDEO_CODEC" "$COLOUR_DEPTH" "$HDR" "$AUDIO" "$EXTENSION")
    OUTPUT_PATH="/mnt/truenas/media/Anime/$showname/$season/"

    echo "Output: $OUTPUT_PATH$OUTPUT"

    # Check for existing file and encode if doesn't exist
    # Check for existing file and encode if doesn't exist
    if [ -f "$OUTPUT_PATH$OUTPUT" ]; then
        log "File exists, skipping..."
        echo "File exists, skipping..."
    else
        rename_video_file "$INPUT" "$OUTPUT_PATH" "$OUTPUT"
        log "Finished: $OUTPUT"
        echo "Completed: $(basename "$INPUT")"
    fi
}

# Main script
SEARCH_DIR="${1:-.}"

# Check if directory exists
if [[ ! -d "$SEARCH_DIR" ]]; then
    echo "Error: Directory not found: $SEARCH_DIR"
    exit 1
fi

# Find all .mkv files
shopt -s nullglob
FILES=("$SEARCH_DIR"/*.{mkv,mp4,avi})
shopt -u nullglob

# Check if any files found
if [ ${#FILES[@]} -eq 0 ]; then
    echo "No .mkv,.mp4,.avi files found in $SEARCH_DIR"
    exit 0
fi

echo "Found ${#FILES[@]} .mkv,.mp4,.avi file(s) to process"

# Process each file
count=0
for file in "${FILES[@]}"; do
    ((count++))
    process_file "$file" "$count" "${#FILES[@]}"
done

echo ""
echo "========================================"
echo "Batch processing complete!"
echo "Processed $count file(s)"
echo "========================================"
