File size: 9,948 Bytes
519b145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
#!/bin/bash
# Script tự động tổ chức các file markdown theo ngày tạo và category
# Chạy: bash backend/scripts/organize_markdowns.sh [--dry-run] [--backup]

set -e

# Parse arguments
DRY_RUN=false
BACKUP=false
for arg in "$@"; do
    case $arg in
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --backup)
            BACKUP=true
            shift
            ;;
        *)
            ;;
    esac
done

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
REPORTS_DIR="${PROJECT_ROOT}/tài nguyên/báo cáo"
DOCS_DIR="${PROJECT_ROOT}/backend/docs"

echo "📁 Tổ chức file markdown theo ngày và category..."
if [ "$DRY_RUN" = true ]; then
    echo "🔍 DRY-RUN MODE: Chỉ preview, không di chuyển file"
fi
echo ""

# Hàm xác định ngày tạo file
get_file_creation_date() {
    local file="$1"
    local git_date=""
    local birth_date=""
    local mod_date=""
    local meta_date=""
    local final_date=""
    
    # Git history
    if command -v git &> /dev/null && [ -d "${PROJECT_ROOT}/.git" ]; then
        git_date=$(cd "$PROJECT_ROOT" && git log --diff-filter=A --format="%ai" -- "$file" 2>/dev/null | tail -1 | cut -d' ' -f1)
        if [ -z "$git_date" ] || [[ ! "$git_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
            git_date=""
        fi
    fi
    
    # File birth time
    if [[ "$OSTYPE" == "darwin"* ]]; then
        birth_date=$(stat -f "%SB" -t "%Y-%m-%d" "$file" 2>/dev/null || stat -f "%Sm" -t "%Y-%m-%d" -B "$file" 2>/dev/null || echo "")
        if [ -z "$birth_date" ]; then
            birth_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$file" 2>/dev/null || echo "")
        fi
    else
        birth_date=$(stat -c "%y" "$file" 2>/dev/null | cut -d' ' -f1 || echo "")
    fi
    
    # File modified time
    if [[ "$OSTYPE" == "darwin"* ]]; then
        mod_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$file" 2>/dev/null || echo "")
    else
        mod_date=$(stat -c "%y" "$file" 2>/dev/null | cut -d' ' -f1 || echo "")
    fi
    
    # Metadata trong file
    if [ -f "$file" ]; then
        meta_date=$(grep -iE "(created|date|ngày):\s*[0-9]{4}-[0-9]{2}-[0-9]{2}" "$file" 2>/dev/null | head -1 | grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}" | head -1 || echo "")
    fi
    
    # Sử dụng ngày đầu tiên tìm được
    if [ -n "$git_date" ]; then
        final_date="$git_date"
    elif [ -n "$birth_date" ]; then
        final_date="$birth_date"
    elif [ -n "$mod_date" ]; then
        final_date="$mod_date"
    elif [ -n "$meta_date" ]; then
        final_date="$meta_date"
    else
        final_date=$(date +"%Y-%m-%d")
    fi
    
    # Validate format
    if [[ ! "$final_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
        final_date=$(date +"%Y-%m-%d")
    fi
    
    echo "$final_date"
}

# Hàm detect category từ tên file và nội dung
detect_category() {
    local file="$1"
    local filename=$(basename "$file" | tr '[:upper:]' '[:lower:]')
    local category=""
    
    # Ưu tiên 1: Metadata trong file
    if [ -f "$file" ]; then
        meta_category=$(grep -iE "category:\s*[a-z]+" "$file" 2>/dev/null | head -1 | grep -oE "category:\s*([a-z_]+)" | cut -d: -f2 | tr -d ' ' || echo "")
        if [ -n "$meta_category" ]; then
            echo "$meta_category"
            return
        fi
    fi
    
    # Ưu tiên 2: Tên file
    declare -A category_keywords
    category_keywords["database"]="database|postgresql|mysql|mongodb|redis|db_|_db|sql"
    category_keywords["backend"]="backend|api|server|django|flask|fastapi|be_|_be|endpoint"
    category_keywords["frontend"]="frontend|ui|react|vue|angular|component|fe_|_fe|interface"
    category_keywords["devops"]="devops|docker|kubernetes|ci/cd|deploy|jenkins|terraform"
    category_keywords["ml"]="ml|ai|model|training|neural|tensorflow|pytorch|embedding"
    category_keywords["plan"]="plan|roadmap|planning|strategy|milestone"
    category_keywords["setup"]="setup|config|install|installation|guide|tutorial"
    
    local max_matches=0
    for cat in "${!category_keywords[@]}"; do
        matches=$(echo "$filename" | grep -oiE "${category_keywords[$cat]}" | wc -l | tr -d ' ')
        if [ "$matches" -gt "$max_matches" ]; then
            max_matches=$matches
            category="$cat"
        fi
    done
    
    # Ưu tiên 3: Nội dung file (100 dòng đầu)
    if [ -z "$category" ] && [ -f "$file" ]; then
        local content=$(head -100 "$file" | tr '[:upper:]' '[:lower:]')
        max_matches=0
        for cat in "${!category_keywords[@]}"; do
            matches=$(echo "$content" | grep -oiE "${category_keywords[$cat]}" | wc -l | tr -d ' ')
            if [ "$matches" -gt "$max_matches" ]; then
                max_matches=$matches
                category="$cat"
            fi
        done
    fi
    
    # Fallback
    if [ -z "$category" ]; then
        category="general"
    fi
    
    echo "$category"
}

# Hàm tạo folder và README nếu chưa có
ensure_category_folder() {
    local date_folder="$1"
    local category="$2"
    local category_folder="${date_folder}/${category}"
    
    if [ ! -d "$category_folder" ]; then
        if [ "$DRY_RUN" = false ]; then
            mkdir -p "$category_folder"
            echo "✅ Đã tạo folder: $category_folder"
            
            # Tạo README.md trong folder category
            cat > "${category_folder}/README.md" << EOF
# Tài liệu ${category} - $(basename "$date_folder")

Folder này chứa các file markdown về **${category}** được tạo trong ngày $(basename "$date_folder").

## Danh sách file

$(find "$category_folder" -maxdepth 1 -name "*.md" ! -name README.md -type f | sed 's|.*/||' | sort | sed 's/^/- /')

## Category
${category}

## Ngày tạo
$(basename "$date_folder")
EOF
        else
            echo "🔍 [DRY-RUN] Sẽ tạo folder: $category_folder"
        fi
    fi
}

# Hàm di chuyển file markdown
move_markdown() {
    local source_file="$1"
    local target_dir="$2"
    local filename=$(basename "$source_file")
    local target_file="${target_dir}/${filename}"
    
    if [ -f "$target_file" ]; then
        if cmp -s "$source_file" "$target_file" 2>/dev/null; then
            echo "⚠️  File trùng nội dung: $target_file (xóa file gốc)"
            if [ "$DRY_RUN" = false ]; then
                rm "$source_file"
            fi
            return 1
        else
            echo "⚠️  File đã tồn tại nhưng khác nội dung: $target_file"
            return 1
        fi
    fi
    
    if [ "$BACKUP" = true ] && [ "$DRY_RUN" = false ]; then
        backup_dir="${PROJECT_ROOT}/.backup/markdowns/$(date +%Y%m%d_%H%M%S)"
        mkdir -p "$backup_dir"
        cp "$source_file" "${backup_dir}/${filename}"
    fi
    
    if [ "$DRY_RUN" = false ]; then
        mv "$source_file" "$target_file"
        echo "✅ Đã di chuyển: $filename$target_dir"
    else
        echo "🔍 [DRY-RUN] Sẽ di chuyển: $filename$target_dir"
    fi
    return 0
}

# Xử lý các file trong backend/docs
if [ -d "$DOCS_DIR" ]; then
    echo "🔍 Tìm file markdown trong: $DOCS_DIR"
    
    find "$DOCS_DIR" -maxdepth 1 -name "*.md" -type f | while read -r file; do
        if [ -f "$file" ]; then
            filename=$(basename "$file")
            echo ""
            echo "📄 Xử lý: $filename"
            
            # Xác định ngày tạo
            date_created=$(get_file_creation_date "$file")
            echo "  📅 Ngày: $date_created"
            
            # Detect category
            category=$(detect_category "$file")
            echo "  📂 Category: $category"
            
            date_folder="${REPORTS_DIR}/${date_created}"
            ensure_category_folder "$date_folder" "$category"
            
            # Di chuyển file
            move_markdown "$file" "${date_folder}/${category}"
        fi
    done
fi

# Tìm các file markdown lộn xộn khác
echo ""
echo "🔍 Tìm file markdown lộn xộn khác..."

EXCLUDE_DIRS=(
    "node_modules"
    "ops"
    "chatbot/training"
    ".git"
    ".venv"
    "__pycache__"
    ".cursor"
    "tài nguyên/báo cáo"
    ".backup"
)

find "$PROJECT_ROOT" -name "*.md" -type f | while read -r file; do
    skip=false
    for exclude in "${EXCLUDE_DIRS[@]}"; do
        if [[ "$file" == *"$exclude"* ]]; then
            skip=true
            break
        fi
    done
    
    if [[ "$file" == *"tài nguyên/báo cáo"* ]]; then
        skip=true
    fi
    
    if [ "$skip" = true ]; then
        continue
    fi
    
    filename=$(basename "$file")
    echo ""
    echo "📄 Xử lý: $filename"
    
    # Xác định ngày tạo
    date_created=$(get_file_creation_date "$file")
    echo "  📅 Ngày: $date_created"
    
    # Detect category
    category=$(detect_category "$file")
    echo "  📂 Category: $category"
    
    date_folder="${REPORTS_DIR}/${date_created}"
    ensure_category_folder "$date_folder" "$category"
    
    # Di chuyển file
    move_markdown "$file" "${date_folder}/${category}"
done

echo ""
echo "✅ Hoàn tất tổ chức file markdown!"
echo ""
echo "📊 Thống kê:"
for date_folder in "${REPORTS_DIR}"/20*; do
    if [ -d "$date_folder" ]; then
        date_name=$(basename "$date_folder")
        echo "  📁 $date_name:"
        for category_folder in "${date_folder}"/*; do
            if [ -d "$category_folder" ]; then
                category_name=$(basename "$category_folder")
                count=$(find "$category_folder" -maxdepth 1 -name "*.md" ! -name README.md -type f | wc -l | tr -d ' ')
                if [ "$count" -gt 0 ]; then
                    echo "    └─ $category_name: $count file(s)"
                fi
            fi
        done
    fi
done

if [ "$DRY_RUN" = true ]; then
    echo ""
    echo "💡 Chạy lại không có --dry-run để thực sự di chuyển file"
fi