#!/bin/bash
# CFS 6hrly grib2 顺序串行下载脚本
# Usage: ./cfs_dl.sh 20260728 00 32

# ====================== 全局常量配置区 ======================
readonly PROGNAME="$(basename "$0")"
readonly SRC_BASE_URL="https://nomads.ncep.noaa.gov/pub/data/nccf/com/cfs/prod"
readonly RETRY_TIMES=2
# 极小文件判定阈值 100字节
readonly CHECK_FILE_SIZE=100
# 本地存储根目录，可自行修改
readonly SAVE_ROOT="/data/public/Goldwind/cfsr/"

# ====================== 基础下载函数（带超时防卡死） ======================
download_file() {
    local url="$1"
    local save_path="$2"
    local filename="$3"

    echo "---------------------------------------------------------"
    echo "Start downloading: $filename"
    echo "URL: $url"

    # wget 强制超时，杜绝境外链接挂死阻塞脚本
    wget --no-check-certificate -q -c \
        --dns-timeout=8 \
        --connect-timeout=10 \
        --read-timeout=15 \
        --timeout=20 \
        --tries="${RETRY_TIMES}" \
        -O "${save_path}/${filename}" "${url}"

    echo "Finish attempt: $filename"
}

# ====================== 单文件校验+补下逻辑 ======================
check_and_redownload() {
    local full_url="$1"
    local file_path="$2"
    local file_name="$3"

    # 判断文件是否存在
    if [ ! -f "${file_path}" ]; then
        echo "File missing, re-download: ${file_name}"
        download_file "${full_url}" "$(dirname "${file_path}")" "${file_name}"
        return
    fi

    # 获取文件大小，出错记为0
    local file_size
    file_size=$(stat -c %s "${file_path}" 2>/dev/null || echo 0)

    # 小于100字节判定损坏，删除重下
    if [ "${file_size}" -lt "${CHECK_FILE_SIZE}" ]; then
        echo "WARNING: ${file_name} size ${file_size} bytes < ${CHECK_FILE_SIZE}, delete and re-download"
        rm -f "${file_path}"
        download_file "${full_url}" "$(dirname "${file_path}")" "${file_name}"
    else
        echo "OK: ${file_name} complete, size: ${file_size} bytes"
    fi
}

# ====================== 逐日逐时次顺序下载核心 ======================
batch_download() {
    local base_date="$1"
    local init_hour="$2"
    local total_days="$3"

    # 拼接远端子路径
    local remote_subdir="cfs.${base_date}/${init_hour}/6hrly_grib_01"
    local full_remote_prefix="${SRC_BASE_URL}/${remote_subdir}"
    local local_target_dir="${SAVE_ROOT}/${remote_subdir}"

    # 创建本地目录
    mkdir -p "${local_target_dir}"

    # 循环每一天预报日：严格顺序 第0天~第total_days-1天
    for ((day_offset=0; day_offset < total_days; day_offset++)); do
        # 计算预报日期字符串 YYYYMMDD
        fc_date=$(date -d "${base_date} +${day_offset} day" +%Y%m%d)
        echo -e "\n===================== Download forecast day: ${fc_date} ====================="

        # 单日4个时次：0 6 12 18，顺序遍历
        for hour_step in 0 6 12 18; do
            # 补零：0→00，6→06，12→12，18→18
            if [ "${hour_step}" -lt 10 ]; then
                step_str="0${hour_step}"
            else
                step_str="${hour_step}"
            fi

            # 拼接正确文件名
            suffix="${fc_date}${step_str}.01.${base_date}${init_hour}.grb2"
            file_pgb="pgbf${suffix}"
            file_flx="flxf${suffix}"

            # 处理 pgbf 文件
            pgb_url="${full_remote_prefix}/${file_pgb}"
            pgb_local="${local_target_dir}/${file_pgb}"
            check_and_redownload "${pgb_url}" "${pgb_local}" "${file_pgb}"

            # 顺序处理 flxf 文件（必须等上一个完全结束才执行）
            flx_url="${full_remote_prefix}/${file_flx}"
            flx_local="${local_target_dir}/${file_flx}"
            check_and_redownload "${flx_url}" "${flx_local}" "${file_flx}"
        done
    done

    echo -e "\n===================== All sequential download finished ====================="
}

# ====================== 入口参数校验 ======================
main() {
    # 必须传入3个参数
    if [ $# -ne 3 ]; then
        echo "ERROR: Wrong arguments count!"
        echo "Usage: ${PROGNAME} YYYYMMDD INIT_HOUR TOTAL_DAYS"
        echo "Example: ${PROGNAME} 20260728 00 32"
        exit 1
    fi

    local ARG_DATE="$1"
    local ARG_HOUR="$2"
    local ARG_DAYS="$3"

    local ARG_DATE=$(date +%Y%m%d)
    # 格式简单校验
    if ! [[ "${ARG_DATE}" =~ ^[0-9]{8}$ ]]; then
        echo "ERROR: First param must be 8-digit date YYYYMMDD"
        exit 1
    fi
    if ! [[ "${ARG_HOUR}" =~ ^(00|06|12|18)$ ]]; then
        echo "ERROR: Second param only allow 00/06/12/18"
        exit 1
    fi
    if ! [[ "${ARG_DAYS}" =~ ^[0-9]+$ ]]; then
        echo "ERROR: Third param must be integer forecast days"
        exit 1
    fi

    # 开始顺序串行下载
    batch_download "${ARG_DATE}" "${ARG_HOUR}" "${ARG_DAYS}"
}

# 启动，把外部命令行参数全部传入
main "$@"
