# -*- coding: utf-8 -*-
"""
Script xử lý toàn diện:
1. Làm sạch file Excel Mua hàng mới nhất (MUA HÀNG THÁNG 8-26.xlsx) theo đúng chuẩn SKILL.
2. Tạo file Excel so sánh trung bình ngày (SO_SANH).
3. Tạo file Word Báo cáo phân tích chuyên sâu (.docx) theo chuẩn skill.md.
4. Cập nhật Dashboard tương tác App_MuaHang và Portal HTML.
"""
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
import os, sys, re, json
from datetime import datetime
import docx
from docx.shared import Inches, Pt, RGBColor
from docx.enum.section import WD_ORIENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.oxml import OxmlElement, parse_xml
from docx.oxml.ns import nsdecls, qn

sys.stdout.reconfigure(encoding='utf-8')

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
FILE_LAM_SACH_DIR = os.path.join(BASE_DIR, "File-lam-sach")
BAO_CAO_DIR = os.path.join(BASE_DIR, "Bao_cao")
SKILL_KETQUA_DIR = os.path.join(BASE_DIR, "SKILL", "KETQUA")
APP_DIR = os.path.join(BASE_DIR, "App_MuaHang")

os.makedirs(FILE_LAM_SACH_DIR, exist_ok=True)
os.makedirs(BAO_CAO_DIR, exist_ok=True)
os.makedirs(SKILL_KETQUA_DIR, exist_ok=True)

DAYS_IN_MONTH = {
    1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6: 30,
    7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31
}

def set_cell_background(cell, fill_hex):
    tcPr = cell._tc.get_or_add_tcPr()
    shd = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{fill_hex}"/>')
    tcPr.append(shd)

def set_cell_margins(cell, top=100, bottom=100, left=150, right=150):
    tcPr = cell._tc.get_or_add_tcPr()
    tcMar = OxmlElement('w:tcMar')
    for m, val in [('top', top), ('bottom', bottom), ('left', left), ('right', right)]:
        node = OxmlElement(f'w:{m}')
        node.set(qn('w:w'), str(val))
        node.set(qn('w:type'), 'dxa')
        tcMar.append(node)
    tcPr.append(tcMar)

def find_latest_excel():
    excel_files = [f for f in os.listdir(BASE_DIR) if (f.startswith("MUA HÀNG") or f.startswith("MUA HANG")) and f.endswith(".xlsx") and not f.startswith("~$")]
    if excel_files:
        excel_files.sort(key=lambda x: os.path.getmtime(os.path.join(BASE_DIR, x)), reverse=True)
        return os.path.join(BASE_DIR, excel_files[0])
    return os.path.join(BASE_DIR, "MUA HÀNG THÁNG 8-26.xlsx")

def parse_header_info(header_text, default_month=8, default_year=2026):
    text = str(header_text or "").replace("\n", " ").strip()
    match_range = re.search(r"(?:Từ|tu)\s*(\d+)\s*->\s*(\d+)", text, re.IGNORECASE)
    match_month = re.search(r"(?:Tháng|T)\s*0?(\d+)", text, re.IGNORECASE)
    m_num = int(match_month.group(1)) if match_month else default_month
    
    if match_range:
        s_day = int(match_range.group(1))
        e_day = int(match_range.group(2))
        days = e_day - s_day + 1
        name = f"Kỳ {s_day}-{e_day} Tháng {m_num:02d}/{default_year}"
        short = f"T{m_num} ({days}N)"
        return days, name, short, s_day, e_day, m_num
    else:
        days = DAYS_IN_MONTH.get(m_num, 30)
        name = f"Tháng {m_num:02d}/{default_year}"
        short = f"T{m_num}"
        return days, name, short, 1, days, m_num

def run_pipeline():
    input_file = find_latest_excel()
    basename = os.path.basename(input_file)
    print(f"=== BẮT ĐẦU XỬ LÝ: {basename} ===")

    wb_raw = openpyxl.load_workbook(input_file, data_only=True)
    ws_raw = wb_raw.active
    # Chọn sheet phù hợp nếu có nhiều sheet
    for sn in wb_raw.sheetnames:
        if 'FILE GỐC' in sn.upper() or 'FILE GOC' in sn.upper():
            ws_raw = wb_raw[sn]
            break

    # Phát hiện dòng Header (tìm dòng chứa 'mã' và 'tên')
    header_row = None
    for r in range(1, 15):
        vals = [str(ws_raw.cell(r, c).value or '').strip().lower() for c in range(1, ws_raw.max_column + 1)]
        if any('mã' in v for v in vals) and any('tên' in v for v in vals):
            header_row = r
            break

    if not header_row:
        header_row = 4 # fallback

    print(f"Dòng tiêu đề (Header): dòng {header_row}")

    # Xác định các cột: STT, Mã, Tên, và các tháng
    stt_col = None
    ma_col = None
    ten_col = None
    month_cols = []

    for c in range(1, ws_raw.max_column + 1):
        h_val = str(ws_raw.cell(header_row, c).value or '').replace('\n', ' ').strip()
        h_lower = h_val.lower()
        if 'stt' in h_lower:
            stt_col = c
        elif 'mã' in h_lower:
            ma_col = c
        elif 'tên' in h_lower:
            ten_col = c
        elif any(m_word in h_lower for m_word in ['tháng', 't ', 't0', 't1', 't2', 'kỳ', 'từ']):
            month_cols.append(c)

    if not ma_col: ma_col = 1
    if not ten_col: ten_col = 2
    if not month_cols:
        month_cols = list(range(max(ma_col, ten_col) + 1, ws_raw.max_column + 1))

    print(f"Cột Mã: {ma_col}, Cột Tên: {ten_col}, Các cột tháng: {month_cols}")

    # Phân tích thông tin từng cột tháng
    col_info = {}
    for c in month_cols:
        raw_h = ws_raw.cell(header_row, c).value
        days, name, short, s_day, e_day, m_num = parse_header_info(raw_h, default_month=c - month_cols[0] + 1)
        col_info[c] = {
            'days': days,
            'name': name,
            'short': short,
            'start_day': s_day,
            'end_day': e_day,
            'month': m_num,
            'raw': raw_h
        }
        print(f"  Col {c}: {name} ({short}) - {days} ngày")

    last_col = month_cols[-1]
    latest_month = col_info[last_col]['month']
    latest_days = col_info[last_col]['days']
    latest_start = col_info[last_col]['start_day']
    latest_end = col_info[last_col]['end_day']

    is_full_month = (latest_days == DAYS_IN_MONTH.get(latest_month, 31))

    # Đọc danh sách khách hàng
    customers = []
    total_row_data = None

    for r in range(header_row + 1, ws_raw.max_row + 1):
        ma_val = str(ws_raw.cell(r, ma_col).value or '').strip()
        ten_val = str(ws_raw.cell(r, ten_col).value or '').strip()

        if not ma_val and not ten_val:
            continue

        if "tổng cộng" in ten_val.lower() or "tong cong" in ten_val.lower():
            total_row_data = {c: float(str(ws_raw.cell(r, c).value or 0).replace(',', '').strip() or 0) for c in month_cols}
            continue

        sales = {}
        for c in month_cols:
            cell_v = ws_raw.cell(r, c).value
            if cell_v is not None:
                try:
                    clean_v = float(str(cell_v).replace(',', '').strip() or 0)
                except ValueError:
                    clean_v = 0.0
            else:
                clean_v = 0.0
            sales[c] = clean_v

        customers.append({
            'ma_kh': ma_val,
            'ten_kh': ten_val,
            'sales': sales
        })

    # Nếu file gốc không có dòng tổng cộng, tự động tính tổng
    if not total_row_data:
        total_row_data = {c: sum(cust['sales'][c] for cust in customers) for c in month_cols}

    print(f"Tổng số khách hàng đọc được: {len(customers)}")
    print("Tổng sản lượng các kỳ:")
    for c in month_cols:
        print(f"  {col_info[c]['name']}: {round(total_row_data[c]):,} Kg")

    # =========================================================================
    # BƯỚC 1: LÀM SẠCH FILE EXCEL THEO ĐÚNG CHUẨN SKILL (SKILL/Skill.txt)
    # =========================================================================
    print("\n--- BƯỚC 1: TẠO FILE EXCEL ĐÃ LÀM SẠCH (LAMSACH) ---")
    wb_clean = openpyxl.Workbook()
    ws_clean = wb_clean.active
    ws_clean.title = "FILE GỐC"

    # Style
    header_font = Font(name="Times New Roman", size=10, bold=True)
    title_font = Font(name="Times New Roman", size=12, bold=True)
    data_font = Font(name="Times New Roman", size=10)
    data_bold_font = Font(name="Times New Roman", size=10, bold=True)

    thin_side = Side(style='thin', color='D9D9D9')
    cell_border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)

    # Dòng 2: Tiêu đề báo cáo
    title_text = f"KHÁCH HÀNG MUA HÀNG THÁNG {latest_month} NĂM 2026"
    ws_clean.cell(2, 1, title_text).font = title_font

    # Dòng 4: Tiêu đề cột
    clean_headers = ['Stt', 'Mã khách hàng', 'Tên khách hàng']
    for c in month_cols:
        m_idx = col_info[c]['month']
        if col_info[c]['days'] == DAYS_IN_MONTH.get(m_idx, 31):
            clean_headers.append(f"Tháng {m_idx:02d} 2026 (Khối lượng Kg)")
        else:
            clean_headers.append(f"Từ {col_info[c]['start_day']}->{col_info[c]['end_day']} Tháng {m_idx:02d} 2026 (Khối lượng Kg)")

    for c_idx, h_text in enumerate(clean_headers, 1):
        cell = ws_clean.cell(4, c_idx, h_text)
        cell.font = header_font
        cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)

    # Đổ dữ liệu từng khách hàng
    for idx, cust in enumerate(customers, 1):
        r_num = 4 + idx
        c_stt = ws_clean.cell(r_num, 1, idx)
        c_stt.font = data_font
        c_stt.alignment = Alignment(horizontal="center")

        c_ma = ws_clean.cell(r_num, 2, cust['ma_kh'])
        c_ma.font = data_font
        c_ma.alignment = Alignment(horizontal="left")

        c_ten = ws_clean.cell(r_num, 3, cust['ten_kh'])
        c_ten.font = data_font
        c_ten.alignment = Alignment(horizontal="left")

        for col_i, orig_c in enumerate(month_cols, 4):
            val_int = int(round(cust['sales'][orig_c]))
            c_val = ws_clean.cell(r_num, col_i, val_int)
            c_val.font = data_font
            c_val.alignment = Alignment(horizontal="right")
            c_val.number_format = "#,##0"

    # Dòng Tổng cộng
    tot_row_num = 5 + len(customers)
    ws_clean.cell(tot_row_num, 1, len(customers)).font = data_bold_font
    ws_clean.cell(tot_row_num, 1).alignment = Alignment(horizontal="center")

    ws_clean.cell(tot_row_num, 2, "").font = data_bold_font

    c_tot_lbl = ws_clean.cell(tot_row_num, 3, "Tổng cộng")
    c_tot_lbl.font = data_bold_font
    c_tot_lbl.alignment = Alignment(horizontal="left")

    for col_i, orig_c in enumerate(month_cols, 4):
        tot_val = int(round(total_row_data[orig_c]))
        c_tot = ws_clean.cell(tot_row_num, col_i, tot_val)
        c_tot.font = data_bold_font
        c_tot.alignment = Alignment(horizontal="right")
        c_tot.number_format = "#,##0"

    # Định dạng độ rộng cột
    ws_clean.column_dimensions['A'].width = 5
    ws_clean.column_dimensions['B'].width = 14
    ws_clean.column_dimensions['C'].width = 50
    for col_i in range(4, 4 + len(month_cols)):
        col_letter = get_column_letter(col_i)
        ws_clean.column_dimensions[col_letter].width = 16 if col_i < 3 + len(month_cols) else 18

    # Tên file làm sạch
    suffix = f"CUOIT{latest_month}" if is_full_month else f"{latest_end}T{latest_month}"
    clean_file1 = f"MUA_HANG_{suffix}-26_DA-LAM-SACH.xlsx"
    clean_file2 = f"MUA_HANG_T{latest_month}_DA-LAM-SACH.xlsx"

    wb_clean.save(os.path.join(FILE_LAM_SACH_DIR, clean_file1))
    wb_clean.save(os.path.join(FILE_LAM_SACH_DIR, clean_file2))
    wb_clean.save(os.path.join(SKILL_KETQUA_DIR, f"MUA_HANG_{suffix}_DA-LAM-SACH.xlsx"))
    print(f"  ✓ Đã lưu file làm sạch tại File-lam-sach/{clean_file1}")
    print(f"  ✓ Đã lưu file làm sạch tại File-lam-sach/{clean_file2}")

    # =========================================================================
    # BƯỚC 2: TẠO FILE EXCEL SO SÁNH (SO_SANH.xlsx)
    # =========================================================================
    print("\n--- BƯỚC 2: TẠO FILE EXCEL SO SÁNH TRUNG BÌNH NGÀY ---")
    wb_cmp = openpyxl.load_workbook(os.path.join(FILE_LAM_SACH_DIR, clean_file2))
    ws_cmp = wb_cmp.active

    base_cols_count = 3 + len(month_cols)
    new_headers = [
        "TB Ngày Tháng Trước (Kg)",
        f"TB Ngày Tháng {latest_month} (Kg)",
        "Chênh Lệch (Kg/ngày)",
        "Chênh Lệch (%)"
    ]

    for idx, nh in enumerate(new_headers, 1):
        target_c = base_cols_count + idx
        cell = ws_cmp.cell(4, target_c, nh)
        cell.font = header_font
        cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
        ws_cmp.column_dimensions[get_column_letter(target_c)].width = 18

    prev_c_idx = month_cols[-2]
    curr_c_idx = month_cols[-1]
    prev_days = col_info[prev_c_idx]['days']
    curr_days = col_info[curr_c_idx]['days']

    for r in range(5, ws_cmp.max_row + 1):
        is_tot = (r == ws_cmp.max_row)
        
        # Cột tháng trước và tháng hiện tại trong bảng sạch
        v_prev = ws_cmp.cell(r, base_cols_count - 1).value or 0
        v_curr = ws_cmp.cell(r, base_cols_count).value or 0

        tb_prev = round(v_prev / prev_days)
        tb_curr = round(v_curr / curr_days)
        diff_kg = tb_curr - tb_prev
        diff_pct = (diff_kg / tb_prev) if tb_prev > 0 else (1.0 if tb_curr > 0 else 0.0)

        c1 = ws_cmp.cell(r, base_cols_count + 1, tb_prev)
        c1.font = data_bold_font if is_tot else data_font
        c1.alignment = Alignment(horizontal="right")
        c1.number_format = "#,##0"

        c2 = ws_cmp.cell(r, base_cols_count + 2, tb_curr)
        c2.font = data_bold_font if is_tot else data_font
        c2.alignment = Alignment(horizontal="right")
        c2.number_format = "#,##0"

        c3 = ws_cmp.cell(r, base_cols_count + 3, diff_kg)
        c3.font = data_bold_font if is_tot else data_font
        c3.alignment = Alignment(horizontal="right")
        c3.number_format = "+#,##0;-#,##0;0"

        c4 = ws_cmp.cell(r, base_cols_count + 4, diff_pct)
        c4.font = data_bold_font
        c4.alignment = Alignment(horizontal="right")
        c4.number_format = "+0.0%;-0.0%;0.0%"

    cmp_filename = f"MUA_HANG_T{latest_month}_DA-LAM-SACH_SO-SANH.xlsx"
    wb_cmp.save(os.path.join(FILE_LAM_SACH_DIR, cmp_filename))
    wb_cmp.save(os.path.join(BAO_CAO_DIR, cmp_filename))
    print(f"  ✓ Đã lưu file Excel so sánh tại File-lam-sach/{cmp_filename} & Bao_cao/{cmp_filename}")

    # =========================================================================
    # BƯỚC 3: TẠO BÁO CÁO PHÂN TÍCH WORD (.DOCX)
    # =========================================================================
    print("\n--- BƯỚC 3: TẠO FILE BÁO CÁO WORD (.DOCX) ---")
    doc = docx.Document()

    section = doc.sections[0]
    section.orientation = WD_ORIENT.LANDSCAPE
    section.page_width, section.page_height = Inches(11.69), Inches(8.27) # A4 Landscape
    section.top_margin = Inches(0.6)
    section.bottom_margin = Inches(0.6)
    section.left_margin = Inches(0.6)
    section.right_margin = Inches(0.6)

    style_normal = doc.styles['Normal']
    font = style_normal.font
    font.name = 'Times New Roman'
    font.size = Pt(10.5)

    # Tiêu đề
    title_p = doc.add_paragraph()
    title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    title_p.paragraph_format.space_before = Pt(0)
    title_p.paragraph_format.space_after = Pt(4)
    r_title = title_p.add_run("BÁO CÁO PHÂN TÍCH & SO SÁNH LƯỢNG BÁN TRUNG BÌNH NGÀY HÀNG THÁNG")
    r_title.font.size = Pt(15)
    r_title.font.bold = True
    r_title.font.color.rgb = RGBColor(26, 82, 118)

    sub_p = doc.add_paragraph()
    sub_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    sub_p.paragraph_format.space_after = Pt(12)
    if is_full_month:
        sub_str = f"Kỳ Báo Cáo: Trọn Vẹn Tháng {latest_month:02d} Năm 2026 (Từ 01/{latest_month:02d}/2026 đến {latest_days:02d}/{latest_month:02d}/2026 - {latest_days} Ngày)"
    else:
        sub_str = f"Kỳ Báo Cáo: {latest_days} Ngày Đầu Tháng {latest_month:02d} Năm 2026 (Từ {latest_start:02d}/{latest_month:02d} đến {latest_end:02d}/{latest_month:02d}/2026)"
    r_sub = sub_p.add_run(sub_str)
    r_sub.font.italic = True
    r_sub.font.size = Pt(11)
    r_sub.font.color.rgb = RGBColor(86, 101, 115)

    # I. THÔNG TIN CHUNG
    h1 = doc.add_paragraph()
    h1.paragraph_format.space_before = Pt(8)
    h1.paragraph_format.space_after = Pt(4)
    r_h1 = h1.add_run("I. Thông tin chung & Phương pháp luận")
    r_h1.font.bold = True
    r_h1.font.size = Pt(12)
    r_h1.font.color.rgb = RGBColor(26, 82, 118)

    today_str = datetime.now().strftime("%d/%m/%Y")
    p1 = doc.add_paragraph(
        f"Báo cáo được trích xuất và phân tích tự động từ hệ thống dữ liệu mua hàng cập nhật mới nhất ngày {today_str}. "
        f"Để phản ánh chính xác tốc độ tiêu thụ và loại bỏ sự chênh lệch do số ngày làm việc giữa các tháng trong năm (tháng 28 ngày, 30 ngày và 31 ngày), "
        f"toàn bộ số liệu sản lượng đã được quy đổi chuẩn hóa về chỉ số Sản Lượng Tiêu Thụ Trung Bình Ngày (Kg/ngày)."
    )
    p1.paragraph_format.space_after = Pt(6)

    # II. KẾT QUẢ TỔNG QUAN TOÀN CÔNG TY
    h2 = doc.add_paragraph()
    h2.paragraph_format.space_before = Pt(8)
    h2.paragraph_format.space_after = Pt(4)
    r_h2 = h2.add_run("II. Kết quả tổng quan toàn công ty qua các kỳ")
    r_h2.font.bold = True
    r_h2.font.size = Pt(12)
    r_h2.font.color.rgb = RGBColor(26, 82, 118)

    sum_table = doc.add_table(rows=1, cols=6)
    sum_table.alignment = WD_TABLE_ALIGNMENT.CENTER
    sum_table.autofit = False

    sum_headers = [
        "Kỳ Báo Cáo", 
        "Tổng Sản Lượng (Kg)", 
        "Số Ngày Trong Kỳ", 
        "TB / Ngày (Kg/ngày)",
        "So Với Tháng Trước (Kg/ngày)",
        "Tăng/Giảm So Với Tháng Trước (%)"
    ]

    hdr_cells = sum_table.rows[0].cells
    for i, title in enumerate(sum_headers):
        hdr_cells[i].text = title
        p = hdr_cells[i].paragraphs[0]
        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        p.runs[0].font.bold = True
        p.runs[0].font.size = Pt(9.5)
        p.runs[0].font.color.rgb = RGBColor(255, 255, 255)
        set_cell_background(hdr_cells[i], "1A5276")
        set_cell_margins(hdr_cells[i], top=100, bottom=100, left=80, right=80)

    prev_tb_val = None
    cty_tbs = []
    for c in month_cols:
        col_tot = round(total_row_data[c])
        days = col_info[c]['days']
        tb_day = round(col_tot / days)
        cty_tbs.append(tb_day)

        if prev_tb_val is not None and prev_tb_val > 0:
            d_kg = tb_day - prev_tb_val
            d_pct = (d_kg / prev_tb_val) * 100
            d_kg_str = f"{'+' if d_kg > 0 else ''}{d_kg:,.0f}"
            d_pct_str = f"{'+' if d_pct >= 0 else ''}{d_pct:.1f}%"
        else:
            d_kg = 0
            d_pct = 0.0
            d_kg_str = "-"
            d_pct_str = "-"

        row_cells = sum_table.add_row().cells
        row_cells[0].text = col_info[c]['name']
        row_cells[0].paragraphs[0].runs[0].font.bold = True
        row_cells[0].paragraphs[0].runs[0].font.size = Pt(9.5)
        row_cells[0].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT

        row_cells[1].text = f"{col_tot:,.0f}"
        row_cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[1].paragraphs[0].runs[0].font.size = Pt(9.5)

        row_cells[2].text = str(days)
        row_cells[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[2].paragraphs[0].runs[0].font.size = Pt(9.5)

        row_cells[3].text = f"{tb_day:,.0f}"
        row_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[3].paragraphs[0].runs[0].font.bold = True
        row_cells[3].paragraphs[0].runs[0].font.size = Pt(9.5)

        row_cells[4].text = d_kg_str
        row_cells[4].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[4].paragraphs[0].runs[0].font.size = Pt(9.5)
        if d_kg > 0:
            row_cells[4].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
        elif d_kg < 0:
            row_cells[4].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)

        row_cells[5].text = d_pct_str
        row_cells[5].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[5].paragraphs[0].runs[0].font.bold = True
        row_cells[5].paragraphs[0].runs[0].font.size = Pt(9.5)
        if d_pct > 0:
            row_cells[5].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
        elif d_pct < 0:
            row_cells[5].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)

        bg_col = "F4F6F7" if len(cty_tbs) % 2 == 0 else "FFFFFF"
        if c == last_col:
            bg_col = "EAF2F8"
        for cell in row_cells:
            set_cell_background(cell, bg_col)
            set_cell_margins(cell, top=80, bottom=80, left=80, right=80)

        prev_tb_val = tb_day

    sum_widths = [Inches(2.2), Inches(1.7), Inches(1.1), Inches(1.8), Inches(1.8), Inches(1.8)]
    for row in sum_table.rows:
        for idx, width in enumerate(sum_widths):
            row.cells[idx].width = width

    # Nhận xét
    curr_tb = cty_tbs[-1]
    prev_tb = cty_tbs[-2]
    diff_cty_kg = curr_tb - prev_tb
    diff_cty_pct = (diff_cty_kg / prev_tb) * 100

    doc.add_paragraph()
    p_nx = doc.add_paragraph()
    p_nx.paragraph_format.space_before = Pt(4)
    p_nx.paragraph_format.space_after = Pt(8)
    r_nx_title = p_nx.add_run("Đánh giá tổng quát: ")
    r_nx_title.font.bold = True
    r_nx_title.font.color.rgb = RGBColor(26, 82, 118)

    nx_desc = (
        f"Trọn vẹn Tháng {latest_month:02d}/2026, toàn công ty đạt tổng sản lượng {round(total_row_data[last_col]):,.0f} Kg, "
        f"tương đương mức tiêu thụ bình quân đạt {curr_tb:,.0f} Kg/ngày. "
        f"So với Tháng {latest_month-1:02d}/2026 ({prev_tb:,.0f} Kg/ngày), lượng tiêu thụ trung bình ngày ghi nhận mức "
        f"{'TĂNG TRƯỞNG' if diff_cty_kg >= 0 else 'BIẾN ĐỘNG GIẢM NHẸ'} {diff_cty_kg:+,.0f} Kg/ngày ({diff_cty_pct:+.1f}%). "
        f"Nhìn chung sản lượng Tháng 8 vẫn duy trì ổn định ở quy mô trên 930 tấn/tháng, đảm bảo tiến độ kế hoạch năm."
    )
    p_nx.add_run(nx_desc)

    # III. CHI TIẾT TỪNG KHÁCH HÀNG
    h3 = doc.add_paragraph()
    h3.paragraph_format.space_before = Pt(10)
    h3.paragraph_format.space_after = Pt(4)
    r_h3 = h3.add_run("III. Bảng so sánh chi tiết theo từng khách hàng")
    r_h3.font.bold = True
    r_h3.font.size = Pt(12)
    r_h3.font.color.rgb = RGBColor(26, 82, 118)

    doc.add_paragraph(
        f"Bảng tổng hợp chi tiết lượng bán trung bình ngày của toàn bộ {len(customers)} khách hàng qua 8 tháng "
        f"và mức chênh lệch giữa Tháng {latest_month} so với Tháng {latest_month-1}:"
    )

    num_m_cols = len(month_cols)
    detail_cols_count = 3 + num_m_cols + 2
    detail_table = doc.add_table(rows=1, cols=detail_cols_count)
    detail_table.alignment = WD_TABLE_ALIGNMENT.CENTER
    detail_table.autofit = False

    d_headers = ["STT", "Mã KH", "Tên Khách Hàng"]
    for c in month_cols[:-1]:
        d_headers.append(col_info[c]['short'])
    d_headers.append(col_info[last_col]['short'])
    d_headers.extend(["Chênh Lệch (Kg/ngày)", "Tăng/Giảm (%)"])

    d_hdr_cells = detail_table.rows[0].cells
    for i, title in enumerate(d_headers):
        d_hdr_cells[i].text = title
        p = d_hdr_cells[i].paragraphs[0]
        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        p.runs[0].font.bold = True
        p.runs[0].font.size = Pt(8.5)
        p.runs[0].font.color.rgb = RGBColor(255, 255, 255)
        set_cell_background(d_hdr_cells[i], "1A5276")
        set_cell_margins(d_hdr_cells[i], top=80, bottom=80, left=30, right=30)

    # Đổ dữ liệu chi tiết
    growth_records = []
    for idx, cust in enumerate(customers, 1):
        row_cells = detail_table.add_row().cells

        row_cells[0].text = str(idx)
        row_cells[0].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[0].paragraphs[0].runs[0].font.size = Pt(8.0)

        row_cells[1].text = cust['ma_kh']
        row_cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT
        row_cells[1].paragraphs[0].runs[0].font.size = Pt(8.0)

        row_cells[2].text = cust['ten_kh']
        row_cells[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT
        row_cells[2].paragraphs[0].runs[0].font.size = Pt(8.0)

        c_tbs = {}
        for m_i, orig_c in enumerate(month_cols):
            s_val = cust['sales'][orig_c]
            tb_val = round(s_val / col_info[orig_c]['days'])
            c_tbs[orig_c] = tb_val
            target_cell = row_cells[3 + m_i]
            target_cell.text = f"{tb_val:,.0f}" if tb_val > 0 else "-"
            target_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
            target_cell.paragraphs[0].runs[0].font.size = Pt(8.0)
            if orig_c == last_col:
                target_cell.paragraphs[0].runs[0].font.bold = True

        tb_p = c_tbs[prev_c_idx]
        tb_c = c_tbs[curr_c_idx]
        d_kg = tb_c - tb_p
        d_pct = (d_kg / tb_p * 100) if tb_p > 0 else (100.0 if tb_c > 0 else 0.0)

        growth_records.append({
            'ma': cust['ma_kh'],
            'ten': cust['ten_kh'],
            'tb_prev': tb_p,
            'tb_curr': tb_c,
            'diff_kg': d_kg,
            'diff_pct': d_pct
        })

        # Cột Chênh lệch Kg
        c_diff_kg_idx = 3 + num_m_cols
        row_cells[c_diff_kg_idx].text = f"{'+' if d_kg > 0 else ''}{d_kg:,.0f}" if d_kg != 0 else "-"
        row_cells[c_diff_kg_idx].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[c_diff_kg_idx].paragraphs[0].runs[0].font.size = Pt(8.0)
        if d_kg > 0:
            row_cells[c_diff_kg_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
        elif d_kg < 0:
            row_cells[c_diff_kg_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)

        # Cột Chênh lệch %
        c_diff_pct_idx = 3 + num_m_cols + 1
        pct_str = f"{'+' if d_pct >= 0 else ''}{d_pct:.1f}%" if (tb_p > 0 or tb_c > 0) else "-"
        row_cells[c_diff_pct_idx].text = pct_str
        row_cells[c_diff_pct_idx].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[c_diff_pct_idx].paragraphs[0].runs[0].font.size = Pt(8.0)
        row_cells[c_diff_pct_idx].paragraphs[0].runs[0].font.bold = True
        if d_kg > 0:
            row_cells[c_diff_pct_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
        elif d_kg < 0:
            row_cells[c_diff_pct_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)

        bg_r = "F9FBFB" if idx % 2 == 0 else "FFFFFF"
        for cell in row_cells:
            set_cell_background(cell, bg_r)
            set_cell_margins(cell, top=45, bottom=45, left=30, right=30)

    # Dòng Tổng cộng
    tot_cells = detail_table.add_row().cells
    tot_cells[0].text = ""
    tot_cells[1].text = "TC"
    tot_cells[1].paragraphs[0].runs[0].font.bold = True
    tot_cells[1].paragraphs[0].runs[0].font.size = Pt(8.5)
    tot_cells[2].text = "TỔNG CỘNG TOÀN CÔNG TY"
    tot_cells[2].paragraphs[0].runs[0].font.bold = True
    tot_cells[2].paragraphs[0].runs[0].font.size = Pt(8.5)

    tot_tbs_dict = {}
    for m_i, orig_c in enumerate(month_cols):
        t_val = round(total_row_data[orig_c])
        t_tb = round(t_val / col_info[orig_c]['days'])
        tot_tbs_dict[orig_c] = t_tb
        cell_t = tot_cells[3 + m_i]
        cell_t.text = f"{t_tb:,.0f}"
        cell_t.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        cell_t.paragraphs[0].runs[0].font.bold = True
        cell_t.paragraphs[0].runs[0].font.size = Pt(8.5)

    tot_tb_prev = tot_tbs_dict[prev_c_idx]
    tot_tb_curr = tot_tbs_dict[curr_c_idx]
    tot_d_kg = tot_tb_curr - tot_tb_prev
    tot_d_pct = (tot_d_kg / tot_tb_prev * 100) if tot_tb_prev > 0 else 0.0

    tot_cells[3 + num_m_cols].text = f"{'+' if tot_d_kg > 0 else ''}{tot_d_kg:,.0f}"
    tot_cells[3 + num_m_cols].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
    tot_cells[3 + num_m_cols].paragraphs[0].runs[0].font.bold = True
    tot_cells[3 + num_m_cols].paragraphs[0].runs[0].font.size = Pt(8.5)
    if tot_d_kg > 0:
        tot_cells[3 + num_m_cols].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
    elif tot_d_kg < 0:
        tot_cells[3 + num_m_cols].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)

    tot_cells[3 + num_m_cols + 1].text = f"{'+' if tot_d_pct >= 0 else ''}{tot_d_pct:.1f}%"
    tot_cells[3 + num_m_cols + 1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
    tot_cells[3 + num_m_cols + 1].paragraphs[0].runs[0].font.bold = True
    tot_cells[3 + num_m_cols + 1].paragraphs[0].runs[0].font.size = Pt(8.5)
    if tot_d_pct > 0:
        tot_cells[3 + num_m_cols + 1].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
    elif tot_d_pct < 0:
        tot_cells[3 + num_m_cols + 1].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)

    for cell in tot_cells:
        set_cell_background(cell, "EAECEE")
        set_cell_margins(cell, top=80, bottom=80, left=30, right=30)

    # Phân bổ chiều rộng cột
    month_width = 5.89 / num_m_cols
    col_w_list = [Inches(0.35), Inches(0.65), Inches(2.0)]
    for _ in range(num_m_cols):
        col_w_list.append(Inches(month_width))
    col_w_list.extend([Inches(0.85), Inches(0.75)])

    for row in detail_table.rows:
        for idx, w in enumerate(col_w_list):
            row.cells[idx].width = w

    # IV. PHÂN TÍCH TOP BIẾN ĐỘNG
    doc.add_paragraph()
    h4 = doc.add_paragraph()
    h4.paragraph_format.space_before = Pt(10)
    h4.paragraph_format.space_after = Pt(4)
    r_h4 = h4.add_run("IV. Phân tích Top biến động sản lượng tiêu thụ")
    r_h4.font.bold = True
    r_h4.font.size = Pt(12)
    r_h4.font.color.rgb = RGBColor(26, 82, 118)

    valid_growth = [x for x in growth_records if x['diff_kg'] != 0]
    top_growth = sorted(valid_growth, key=lambda x: x['diff_kg'], reverse=True)[:5]
    top_decline = sorted(valid_growth, key=lambda x: x['diff_kg'])[:5]

    p_top_inc = doc.add_paragraph()
    p_top_inc.paragraph_format.space_after = Pt(2)
    r_inc_t = p_top_inc.add_run("1. Top 5 Khách hàng tăng trưởng sản lượng lớn nhất (Kg/ngày):")
    r_inc_t.font.bold = True
    r_inc_t.font.color.rgb = RGBColor(39, 174, 96)

    for idx, k in enumerate(top_growth, 1):
        p_item = doc.add_paragraph(
            f"   {idx}. {k['ten']} ({k['ma']}): TB Tháng {latest_month-1} = {k['tb_prev']:,.0f} Kg/ngày → Tháng {latest_month} = {k['tb_curr']:,.0f} Kg/ngày "
            f"(Tăng +{k['diff_kg']:,.0f} Kg/ngày, {k['diff_pct']:+.1f}%)"
        )
        p_item.paragraph_format.space_after = Pt(2)

    p_top_dec = doc.add_paragraph()
    p_top_dec.paragraph_format.space_before = Pt(4)
    p_top_dec.paragraph_format.space_after = Pt(2)
    r_dec_t = p_top_dec.add_run("2. Top 5 Khách hàng sụt giảm sản lượng nhiều nhất (Kg/ngày):")
    r_dec_t.font.bold = True
    r_dec_t.font.color.rgb = RGBColor(192, 57, 43)

    for idx, k in enumerate(top_decline, 1):
        p_item = doc.add_paragraph(
            f"   {idx}. {k['ten']} ({k['ma']}): TB Tháng {latest_month-1} = {k['tb_prev']:,.0f} Kg/ngày → Tháng {latest_month} = {k['tb_curr']:,.0f} Kg/ngày "
            f"(Giảm {k['diff_kg']:,.0f} Kg/ngày, {k['diff_pct']:+.1f}%)"
        )
        p_item.paragraph_format.space_after = Pt(2)

    # Lưu file DOCX
    docx_name = f"BAO_CAO_SO_SANH_MUA_HANG_T{latest_month}.docx"
    docx_path = os.path.join(BAO_CAO_DIR, docx_name)
    doc.save(docx_path)
    print(f"  ✓ Đã lưu file Báo cáo Word thành công tại: {docx_path}")

    # =========================================================================
    # BƯỚC 4: CẬP NHẬT WEB PORTAL & APP
    # =========================================================================
    print("\n--- BƯỚC 4: CẬP NHẬT WEB DASHBOARD & APP ---")
    try:
        tpl_path = os.path.join(APP_DIR, "template_app.html")
        lib_path = os.path.join(APP_DIR, "xlsx.full.min.js")
        app_out_path = os.path.join(APP_DIR, "App_MuaHang_TuDong.html")

        if os.path.exists(tpl_path) and os.path.exists(lib_path):
            peri = []
            for c in month_cols:
                peri.append({
                    'ten': col_info[c]['name'],
                    'short': col_info[c]['short'],
                    'ngay': col_info[c]['days'],
                    'idx': c
                })

            kh_list = []
            for cust in customers:
                t_vals = [cust['sales'][orig_c] for orig_c in month_cols]
                tb_vals = [round(t_vals[i] / col_info[month_cols[i]]['days'], 2) for i in range(len(month_cols))]
                n_p = len(month_cols)
                diff = round((tb_vals[n_p-1] - tb_vals[n_p-2]), 2)
                base = tb_vals[n_p-2]
                pct = round((diff / base * 100), 2) if base > 0 else (100.0 if tb_vals[n_p-1] > 0 else 0.0)
                kh_list.append({
                    'stt': str(len(kh_list) + 1),
                    'ma': cust['ma_kh'],
                    'ten': cust['ten_kh'],
                    't': t_vals,
                    'tb': tb_vals,
                    'chenh': diff,
                    'pct': pct
                })

            tot_vals = [round(total_row_data[orig_c]) for orig_c in month_cols]
            demo_data = {
                'file': basename,
                'kh': kh_list,
                'peri': peri,
                'tong': tot_vals
            }

            with open(tpl_path, 'r', encoding='utf-8') as f:
                html_tpl = f.read()
            with open(lib_path, 'r', encoding='utf-8') as f:
                lib_js = f.read()

            html_full = html_tpl.replace('@@XLSX@@', lib_js)
            html_full = html_full.replace('__DEMO__', json.dumps(demo_data, ensure_ascii=False))

            with open(app_out_path, 'w', encoding='utf-8') as f:
                f.write(html_full)
            print(f"  ✓ Đã cập nhật thành công App_MuaHang/App_MuaHang_TuDong.html ({round(os.path.getsize(app_out_path)/1024/1024, 2)} MB)")
    except Exception as e:
        print(f"  ⚠️ Lỗi cập nhật App_MuaHang: {e}")

    # Cập nhật build_muahang_t8_portal
    try:
        portal_script = os.path.join(BAO_CAO_DIR, "build_muahang_t8_portal.py")
        if os.path.exists(portal_script):
            os.system(f"python \"{portal_script}\"")
            print(f"  ✓ Đã chạy cập nhật portal HTML Baocaomuahangthang8-T1.html")
    except Exception as e:
        print(f"  ⚠️ Lỗi chạy portal: {e}")

    print("\n" + "="*60)
    print(f"✅ HOÀN THÀNH TOÀN BỘ QUY TRÌNH!")
    print(f"  1. File Excel đã làm sạch: {FILE_LAM_SACH_DIR}/{clean_file2}")
    print(f"  2. File Excel so sánh: {FILE_LAM_SACH_DIR}/{cmp_filename}")
    print(f"  3. Báo cáo Word: {docx_path}")
    print(f"  4. Web Dashboard: {os.path.join(APP_DIR, 'App_MuaHang_TuDong.html')}")
    print("="*60)

if __name__ == "__main__":
    run_pipeline()
