# -*- coding: utf-8 -*-
"""THU_NHAP.PY — nhập THẲNG mọi module, không try/except, để lỗi lộ ra.

VÌ SAO TỆP NÀY TỒN TẠI
----------------------
`nao/tra_loi.py` bọc MỌI phụ thuộc trong try/except. Đó là chủ ý và đúng:
thiếu một mảnh thì bot vẫn sống với các nhánh còn lại thay vì sập cả cổng.

Nhưng chính tính chất đó làm hỏng việc kiểm thử. Ngày 23/09/2026 tôi thêm
một hàm vào `congcu/khuon_mau.py` và làm vỡ cú pháp của tệp đó. Chạy toàn
bộ bộ test: 45/45, 35/35, 36/36, 0 ca sai — TẤT CẢ ĐỀU XANH. Tự kiểm của
`nao/tra_loi.py` cũng chạy hết không lỗi.

Lý do: `tra_loi.py` nhập `khuon_mau` trong try/except, gặp SyntaxError thì
nuốt, ghi một dòng log rồi chạy tiếp với `cau_gia = None`. Bot vẫn trả lời
— chỉ là mọi câu hỏi giá và tra key đều rơi xuống "chuyển người". Nhìn từ
ngoài: dịch vụ khoẻ, test xanh, khách vẫn nhận được câu trả lời. Chỉ có
chất lượng là tụt, âm thầm.

Chỉ phát hiện ra khi đọc log dịch vụ trên máy chủ.

Bộ này nhập thẳng từng module, KHÔNG bọc try/except khi nhập. Vỡ ở đâu là
trượt ngay tại đó, kèm nguyên traceback.

Chạy:  python thu/thu_nhap.py
"""
from __future__ import annotations

import importlib
import os
import sys
import traceback

_THU_MUC_CHA = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if _THU_MUC_CHA not in sys.path:
    sys.path.insert(0, _THU_MUC_CHA)

# Mọi module của gói. Thêm module mới thì thêm vào đây — danh sách viết tay
# có chủ ý: tự quét thư mục sẽ nhặt cả tệp nháp và tệp thử nghiệm.
CAC_MODULE = (
    'giao_uoc',
    'cau_hinh',
    'congcu.csdl',
    'congcu.lien_ket',
    'congcu.cau_hinh_ai',
    'shop',
    'congcu.san_pham',
    'congcu.licence',
    'congcu.khuon_mau',
    'congcu.cho_trong',
    'congcu.hang_doi',
    'congcu.nhat_ky',
    'congcu.so_tay',
    'congcu.phien',
    'kho.cat_doan',
    'kho.trich',
    'kho.nhung',
    'kho.chi_muc',
    'kho.tu_kho_tuvan',
    'tim.bm25',
    'tim.lai',
    'llm.giao_dien',
    'llm.rong',
    'llm.anthropic',
    'llm.tuongthich_openai',
    'nao.dinh_tuyen',
    'nao.tang_mot',
    'nao.tra_loi',
    'nao.tom_tat',
    'nao.compact',
    'kenh.messenger',
    'bao_ve.ngan_sach',
)

# Hàm mà các module khác PHẢI thấy được. Nhập được module nhưng thiếu hàm
# cũng là hỏng — và cũng bị try/except ở nơi gọi nuốt mất y như vậy.
HAM_BAT_BUOC = {
    'congcu.khuon_mau': ('cau_gia', 'cau_bang_gia_tat_ca', 'cau_key',
                         'cau_khong_ro', 'cau_hoi_san_pham'),
    'congcu.cho_trong': ('dien', 'kiem_cu_phap'),
    'congcu.hang_doi': ('gom', 'ghi_nhan'),
    'congcu.nhat_ky': ('ghi',),
    'congcu.so_tay': ('cap_nhat', 'gop', 'thanh_van_ban', 'che_du_lieu_nhay_cam'),
    'congcu.phien': ('tai_phien', 'luu_phien', 'tai_ho_so', 'nhan_ve_tai_khoan', 'them_luot'),
    'nao.tang_mot': ('khop', 'tra_loi_tu_muc', 'nap_muc', 'tang_so_lan_dung'),
    'nao.dinh_tuyen': ('phan_loai', 'doan_san_pham'),
    'nao.tra_loi': ('tra_loi',),
    'nao.tom_tat': ('chay_mot_vong', 'khoi_dong_nen', 'xu_ly_phien'),
    'nao.compact': ('lich_su_cho_prompt', 'kich_hoat_nen', 'tom_gon'),
    'kenh.messenger': ('xu_ly_khach', 'khoi_dong_nen', 'danh_thuc', 'dinh_dang', 'chia_tin'),
    'kho.tu_kho_tuvan': ('nap_tu_kho_tuvan', 'trung_tinh_hoa'),
    'llm.giao_dien': ('dung_prompt_dien_giai', 'dung_prompt_phan_loai'),
}


def chay() -> int:
    """Trả về số module hỏng. 0 nghĩa là đạt."""
    print('=' * 78)
    print('NHẬP THẲNG %d MODULE — không try/except, vỡ ở đâu lộ ra ở đó' % len(CAC_MODULE))
    print('=' * 78)
    so_hong = 0
    for ten in CAC_MODULE:
        try:
            m = importlib.import_module(ten)
        except Exception:  # noqa: BLE001 - đây CHÍNH LÀ thứ cần bắt
            so_hong += 1
            print('  HỎNG  %s' % ten)
            for dong in traceback.format_exc().strip().splitlines()[-3:]:
                print('        %s' % dong)
            continue

        thieu = [h for h in HAM_BAT_BUOC.get(ten, ()) if not hasattr(m, h)]
        if thieu:
            so_hong += 1
            print('  THIẾU %s -> không có: %s' % (ten, ', '.join(thieu)))
        else:
            print('  ok    %s' % ten)

    print('-' * 78)
    print('SỐ MODULE HỎNG: %d' % so_hong)
    if so_hong:
        print('Nhớ: nơi gọi bọc try/except nên bot VẪN CHẠY và test khác VẪN XANH.')
        print('Chất lượng tụt âm thầm — đừng bỏ qua dòng này.')
    return so_hong


if __name__ == '__main__':
    sys.exit(1 if chay() else 0)
