# -*- coding: utf-8 -*-
"""
Tự động làm sạch và tạo báo cáo so sánh lượng bán trung bình ngày (DOCX)
Hỗ trợ động tất cả các cột tháng và tự động lưu tên file theo tháng hiện tại.
"""
import openpyxl
import os
import re
import sys
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__))
OUTPUT_DIR = os.path.join(BASE_DIR, "Bao_cao")

os.makedirs(OUTPUT_DIR, exist_ok=True)

# Thiết lập số ngày chuẩn các tháng năm 2026
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
}

# Các hàm định dạng màu nền bảng trong Word (XML)
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 parse_header_days(header_text, current_month=8):
    text = str(header_text or "").replace("\n", " ").strip()
    # Tìm kỳ hiện tại dạng "Từ 1-> 13" hoặc "Từ 1-> 4"
    match_range = re.search(r"Từ\s*(\d+)\s*->\s*(\d+)", text, re.IGNORECASE)
    if match_range:
        return int(match_range.group(2)) - int(match_range.group(1)) + 1
    # Tìm tháng
    match_month = re.search(r"(?:Tháng|T)\s*(\d+)", text, re.IGNORECASE)
    if match_month:
        m = int(match_month.group(1))
        return DAYS_IN_MONTH.get(m, 30)
    return 30

def find_latest_excel():
    excel_files = [f for f in os.listdir(BASE_DIR) if f.startswith("MUA HÀNG") and f.endswith(".xlsx") and not f.startswith("~$")]
    if not excel_files:
        excel_files = [f for f in os.listdir(BASE_DIR) if 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") # fallback

def generate_report():
    input_file = find_latest_excel()
    print(f"Đọc dữ liệu từ file Excel mới nhất: {input_file}")
    wb = openpyxl.load_workbook(input_file, data_only=True)
    
    sheet_name = None
    for sn in wb.sheetnames:
        if 'FILE GỐC' in sn.upper() or 'FILE GOC' in sn.upper():
            sheet_name = sn
            break
    if not sheet_name:
        sheet_name = max(wb.sheetnames, key=lambda s: wb[s].max_row)
        
    ws = wb[sheet_name]
    max_row = ws.max_row
    max_col = ws.max_column
    
    # Phân tích thông tin kỳ hiện tại (cột cuối)
    last_header = ws.cell(4, max_col).value
    last_header_clean = str(last_header or "").replace("\n", " ").strip()
    
    range_match = re.search(r"(?:Từ|tu)\s*(\d+)\s*->\s*(\d+)", last_header_clean, re.IGNORECASE)
    month_match = re.search(r"(?:Tháng|T)\s*(\d+)", last_header_clean, re.IGNORECASE)
    year_match = re.search(r"(?:20\d{2})", last_header_clean)
    
    start_day = 1
    end_day = 8  # mặc định
    month = 8
    year = 2026
    
    if month_match:
        month = int(month_match.group(1))
    if year_match:
        year = int(year_match.group(0))
        
    if range_match:
        start_day = int(range_match.group(1))
        end_day = int(range_match.group(2))
        current_days = end_day - start_day + 1
        subtitle_str = f"Kỳ Báo Cáo: {current_days} Ngày Đầu Tháng {month} Năm {year} (Từ {start_day:02d}/{month:02d}/{year} đến {end_day:02d}/{month:02d}/{year})"
    else:
        current_days = DAYS_IN_MONTH.get(month, 30)
        end_day = current_days
        subtitle_str = f"Kỳ Báo Cáo: Tháng {month} Năm {year} ({current_days} ngày - Từ {start_day:02d}/{month:02d}/{year} đến {end_day:02d}/{month:02d}/{year})"
        
    OUTPUT_DOCX = os.path.join(OUTPUT_DIR, f"BAO_CAO_SO_SANH_MUA_HANG_T{month}.docx")
    
    # Lấy các cột tháng và kỳ hiện tại
    col_days = {}
    col_names = {}
    for c in range(4, max_col + 1):
        header_val = ws.cell(4, c).value
        col_days[c] = parse_header_days(header_val, month)
        header_clean = str(header_val or "").replace("\n", " ").strip()
        if "Từ" in header_clean or "->" in header_clean:
            col_names[c] = f"Kỳ T{month} ({start_day}-{end_day})"
        else:
            match_m = re.search(r"(?:Tháng|T)\s*(\d+)", header_clean, re.IGNORECASE)
            col_names[c] = f"Tháng {int(match_m.group(1))}" if match_m else header_clean
            
    print("Thông tin các cột số liệu:")
    for c in range(4, max_col + 1):
        print(f"  - Cột {c}: {col_names[c]} ({col_days[c]} ngày)")
        
    # Đọc dữ liệu chi tiết và dòng tổng cộng
    customers_data = []
    total_row = None
    
    for r in range(5, max_row + 1):
        stt = ws.cell(r, 1).value
        ma_kh = ws.cell(r, 2).value
        ten_kh = ws.cell(r, 3).value
        
        sales = {}
        for c in range(4, max_col + 1):
            val = ws.cell(r, c).value
            if val is not None:
                try:
                    sales[c] = int(float(str(val).replace(",", "").strip()))
                except ValueError:
                    sales[c] = 0
            else:
                sales[c] = 0
                
        row_dict = {
            'stt': stt,
            'ma_kh': ma_kh,
            'ten_kh': ten_kh,
            'sales': sales
        }
        
        ten_kh_str = str(ten_kh or "").strip().lower()
        if "tổng cộng" in ten_kh_str or "tong cong" in ten_kh_str or r == max_row:
            total_row = row_dict
        else:
            customers_data.append(row_dict)
            
    doc = docx.Document()
    
    section = doc.sections[0]
    section.orientation = WD_ORIENT.LANDSCAPE
    new_width, new_height = section.page_height, section.page_width
    section.page_width = new_width
    section.page_height = new_height
    section.top_margin = Inches(0.75)
    section.bottom_margin = Inches(0.75)
    section.left_margin = Inches(0.75)
    section.right_margin = Inches(0.75)
    
    style_normal = doc.styles['Normal']
    font = style_normal.font
    font.name = 'Times New Roman'
    font.size = Pt(11)
    
    title_p = doc.add_paragraph()
    title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    title_run = 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")
    title_run.font.size = Pt(16)
    title_run.font.bold = True
    title_run.font.color.rgb = RGBColor(26, 82, 118)
    
    sub_p = doc.add_paragraph()
    sub_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    sub_run = sub_p.add_run(subtitle_str)
    sub_run.font.italic = True
    sub_run.font.size = Pt(11)
    
    h1 = doc.add_paragraph()
    h1_run = h1.add_run("I. Thông tin chung")
    h1_run.font.bold = True
    h1_run.font.size = Pt(13)
    h1_run.font.color.rgb = RGBColor(26, 82, 118)
    
    p_info = doc.add_paragraph(
        "Báo cáo này được tự động phân tích từ dữ liệu mua hàng gốc. Mục tiêu nhằm quy đổi sản lượng bán "
        f"các tháng (từ {col_names[4]} đến {col_names[max_col-1]}) và kỳ báo cáo mới nhất ({col_names[max_col]}) "
        "về chỉ số sản lượng bán trung bình ngày (Kg/ngày). Thông qua đó đưa ra so sánh khách quan và chính xác "
        "về tốc độ tiêu thụ hàng hóa giữa kỳ mới nhất và các kỳ trước đó."
    )
    
    h2 = doc.add_paragraph()
    h2_run = h2.add_run("II. Kết quả tổng quan toàn công ty")
    h2_run.font.bold = True
    h2_run.font.size = Pt(13)
    h2_run.font.color.rgb = RGBColor(26, 82, 118)
    
    doc.add_paragraph(
        "Dưới đây là bảng số liệu tổng lượng bán và lượng bán trung bình ngày qua các kỳ của toàn công ty:"
    )
    
    sum_table = doc.add_table(rows=1, cols=5)
    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ỳ", 
        "Trung bình / Ngày (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
        hdr_cells[i].paragraphs[0].runs[0].font.bold = True
        hdr_cells[i].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        set_cell_background(hdr_cells[i], "1A5276")
        hdr_cells[i].paragraphs[0].runs[0].font.color.rgb = RGBColor(255, 255, 255)
        set_cell_margins(hdr_cells[i], top=120, bottom=120)
        
    prev_tb_ngay = None
    for c in range(4, max_col + 1):
        col_total_sales = total_row['sales'][c]
        days = col_days[c]
        tb_ngay = round(col_total_sales / days)
        
        if prev_tb_ngay is not None and prev_tb_ngay > 0:
            diff_pct = (tb_ngay - prev_tb_ngay) / prev_tb_ngay * 100
            diff_str = f"{'+' if diff_pct >= 0 else ''}{diff_pct:.1f}%"
        else:
            diff_str = "-"
            
        row_cells = sum_table.add_row().cells
        row_cells[0].text = col_names[c]
        row_cells[0].paragraphs[0].runs[0].font.bold = True
        row_cells[1].text = f"{col_total_sales:,.0f}"
        row_cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[2].text = str(days)
        row_cells[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[3].text = f"{tb_ngay:,.0f}"
        row_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[3].paragraphs[0].runs[0].font.bold = True
        row_cells[4].text = diff_str
        row_cells[4].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        
        fill_color = "F2F4F4" if c % 2 == 0 else "FFFFFF"
        for cell in row_cells:
            set_cell_background(cell, fill_color)
            set_cell_margins(cell, top=100, bottom=100)
            
        prev_tb_ngay = tb_ngay
        
    sum_widths = [Inches(1.8), Inches(1.8), Inches(1.2), Inches(2.2), Inches(2.2)]
    for row in sum_table.rows:
        for idx, width in enumerate(sum_widths):
            row.cells[idx].width = width
            
    doc.add_paragraph()
    
    h3 = doc.add_paragraph()
    h3_run = h3.add_run("III. Chi tiết so sánh theo từng khách hàng")
    h3_run.font.bold = True
    h3_run.font.size = Pt(13)
    h3_run.font.color.rgb = RGBColor(26, 82, 118)
    
    doc.add_paragraph(
        "Bảng chi tiết lượng bán trung bình ngày qua các tháng của từng khách hàng và chênh lệch giữa "
        f"kỳ mới nhất ({col_names[max_col]}) so với {col_names[max_col-1]} ngay trước đó:"
    )
    
    # Số cột của bảng chi tiết: 3 (STT, Mã, Tên) + (max_col - 4 + 1) tháng + 2 (Chênh lệch) = max_col + 2
    total_table_cols = max_col + 2
    detail_table = doc.add_table(rows=1, cols=total_table_cols)
    detail_table.alignment = WD_TABLE_ALIGNMENT.CENTER
    detail_table.autofit = False
    
    d_headers = ["STT", "Mã KH", "Tên Khách Hàng"]
    # Các cột tháng trước
    for c in range(4, max_col):
        cname = col_names[c]
        if 'Tháng' in cname:
            match = re.search(r'Tháng (\d+)', cname)
            m_num = int(match.group(1)) if match else c
            d_headers.append(f"TB T{m_num}")
        else:
            d_headers.append(cname)
    # Cột tháng mới nhất
    d_headers.append(f"TB T{month} ({current_days} ngày)")
    d_headers.extend(["Chênh Lệch (Kg/ngày)", "Chênh Lệch (%)"])
    
    d_hdr_cells = detail_table.rows[0].cells
    for i, title in enumerate(d_headers):
        d_hdr_cells[i].text = title
        d_hdr_cells[i].paragraphs[0].runs[0].font.bold = True
        d_hdr_cells[i].paragraphs[0].runs[0].font.size = Pt(9.5)
        d_hdr_cells[i].paragraphs[0].runs[0].font.color.rgb = RGBColor(255, 255, 255)
        d_hdr_cells[i].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        set_cell_background(d_hdr_cells[i], "1A5276")
        set_cell_margins(d_hdr_cells[i], top=120, bottom=120, left=40, right=40)
        
    row_count = 0
    for cust in customers_data:
        row_count += 1
        row_cells = detail_table.add_row().cells
        
        row_cells[0].text = str(cust['stt'] or row_count)
        row_cells[0].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[1].text = str(cust['ma_kh'] or "")
        row_cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT
        row_cells[2].text = str(cust['ten_kh'] or "")
        row_cells[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT
        
        tb_values = {}
        for idx, c in enumerate(range(4, max_col)):
            sales_val = cust['sales'][c]
            tb_val = round(sales_val / col_days[c])
            tb_values[c] = tb_val
            
            row_cells[3 + idx].text = f"{tb_val:,.0f}" if tb_val > 0 else "-"
            row_cells[3 + idx].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
            row_cells[3 + idx].paragraphs[0].runs[0].font.size = Pt(9.0)
            
        curr_sales = cust['sales'][max_col]
        tb_t_curr = round(curr_sales / col_days[max_col])
        tb_values[max_col] = tb_t_curr
        row_cells[max_col - 1].text = f"{tb_t_curr:,.0f}" if tb_t_curr > 0 else "-"
        row_cells[max_col - 1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[max_col - 1].paragraphs[0].runs[0].font.bold = True
        row_cells[max_col - 1].paragraphs[0].runs[0].font.size = Pt(9.0)
        
        tb_prev_month = tb_values[max_col - 1]
        diff_kg = tb_t_curr - tb_prev_month
        if tb_prev_month > 0:
            diff_pct = (diff_kg / tb_prev_month) * 100
            diff_pct_str = f"{'+' if diff_pct >= 0 else ''}{diff_pct:.1f}%"
        else:
            diff_pct_str = "+100.0%" if tb_t_curr > 0 else "0.0%"
            
        # Ghi cột Chênh Lệch Kg
        col_diff_kg_idx = max_col
        row_cells[col_diff_kg_idx].text = f"{'+' if diff_kg > 0 else ''}{diff_kg:,.0f}" if diff_kg != 0 else "-"
        row_cells[col_diff_kg_idx].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        row_cells[col_diff_kg_idx].paragraphs[0].runs[0].font.size = Pt(9.0)
        if diff_kg > 0:
            row_cells[col_diff_kg_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
        elif diff_kg < 0:
            row_cells[col_diff_kg_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)
            
        # Ghi cột Chênh Lệch %
        col_diff_pct_idx = max_col + 1
        row_cells[col_diff_pct_idx].text = diff_pct_str
        row_cells[col_diff_pct_idx].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        row_cells[col_diff_pct_idx].paragraphs[0].runs[0].font.bold = True
        row_cells[col_diff_pct_idx].paragraphs[0].runs[0].font.size = Pt(9.0)
        if diff_kg > 0:
            row_cells[col_diff_pct_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(39, 174, 96)
        elif diff_kg < 0:
            row_cells[col_diff_pct_idx].paragraphs[0].runs[0].font.color.rgb = RGBColor(192, 57, 43)
            
        bg_color = "F9FBFB" if row_count % 2 == 0 else "FFFFFF"
        for cell in row_cells:
            set_cell_background(cell, bg_color)
            set_cell_margins(cell, top=60, bottom=60, left=40, right=40)
            
    # Thêm dòng Tổng cộng ở cuối
    total_cells = detail_table.add_row().cells
    total_cells[0].text = ""
    total_cells[1].text = "TC"
    total_cells[1].paragraphs[0].runs[0].font.bold = True
    total_cells[2].text = "TỔNG CỘNG TOÀN CÔNG TY"
    total_cells[2].paragraphs[0].runs[0].font.bold = True
    
    tb_totals = {}
    for idx, c in enumerate(range(4, max_col)):
        total_sales_val = total_row['sales'][c]
        tb_val = round(total_sales_val / col_days[c])
        tb_totals[c] = tb_val
        total_cells[3 + idx].text = f"{tb_val:,.0f}"
        total_cells[3 + idx].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
        total_cells[3 + idx].paragraphs[0].runs[0].font.bold = True
        total_cells[3 + idx].paragraphs[0].runs[0].font.size = Pt(9.0)
        
    total_sales_curr = total_row['sales'][max_col]
    tb_curr_total = round(total_sales_curr / col_days[max_col])
    tb_totals[max_col] = tb_curr_total
    total_cells[max_col - 1].text = f"{tb_curr_total:,.0f}"
    total_cells[max_col - 1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
    total_cells[max_col - 1].paragraphs[0].runs[0].font.bold = True
    total_cells[max_col - 1].paragraphs[0].runs[0].font.size = Pt(9.0)
    
    tb_prev_total = tb_totals[max_col - 1]
    diff_kg_total = tb_curr_total - tb_prev_total
    diff_pct_total = (diff_kg_total / tb_prev_total) * 100 if tb_prev_total > 0 else 0
    
    total_cells[max_col].text = f"{'+' if diff_kg_total > 0 else ''}{diff_kg_total:,.0f}"
    total_cells[max_col].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
    total_cells[max_col].paragraphs[0].runs[0].font.bold = True
    total_cells[max_col].paragraphs[0].runs[0].font.size = Pt(9.0)
    
    total_cells[max_col + 1].text = f"{'+' if diff_pct_total >= 0 else ''}{diff_pct_total:.1f}%"
    total_cells[max_col + 1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
    total_cells[max_col + 1].paragraphs[0].runs[0].font.bold = True
    total_cells[max_col + 1].paragraphs[0].runs[0].font.size = Pt(9.0)
    
    for cell in total_cells:
        set_cell_background(cell, "EAECEE")
        set_cell_margins(cell, top=100, bottom=100, left=40, right=40)
        
    # Tính toán chiều rộng động
    # STT(0.4), Mã KH(0.7), Tên KH(2.2), Chênh lệch Kg(0.9), Chênh lệch %(0.8)
    # Phần còn lại dành cho các cột tháng: (9.5 - 0.4 - 0.7 - 2.2 - 0.9 - 0.8) = 4.5 inches chia đều.
    col_widths = [Inches(0.4), Inches(0.7), Inches(2.2)]
    num_month_cols = max_col - 3
    month_col_w = 4.5 / num_month_cols
    for _ in range(num_month_cols):
        col_widths.append(Inches(month_col_w))
    col_widths.extend([Inches(0.9), Inches(0.8)])
    
    for row in detail_table.rows:
        for idx, width in enumerate(col_widths):
            row.cells[idx].width = width
            
    doc.save(OUTPUT_DOCX)
    print(f"Đã tạo báo cáo Word thành công tại: {OUTPUT_DOCX}")

if __name__ == "__main__":
    generate_report()
