#!/usr/bin/env python3
"""加氢订单按合同编号匹配客户名称，并生成「月份-客户-项目」汇总子表。"""

from __future__ import annotations

import argparse
from pathlib import Path

import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Alignment


def _line_total_yuan(row: pd.Series) -> float:
    """单行金额：对客费用非 0 时取对客费用，否则取成本费用（与台账常见口径一致）。"""
    c = row.get("对客费用(元)")
    if pd.notna(c) and float(c) != 0:
        return float(c)
    v = row.get("成本费用(元)")
    return float(v) if pd.notna(v) else 0.0


def _merge_month_customer_cells(
    workbook_path: Path,
    sheet_name: str = "月度客户项目汇总",
    col_month: int = 1,
    col_customer: int = 2,
    header_rows: int = 1,
) -> None:
    """对「月份」「客户名称」列：连续且（月份、客户名称）均相同的行做纵向合并。"""
    wb = load_workbook(workbook_path)
    if sheet_name not in wb.sheetnames:
        wb.close()
        raise SystemExit(f"工作簿中未找到工作表: {sheet_name}")
    ws = wb[sheet_name]
    max_r = ws.max_row
    data_start = header_rows + 1
    if max_r < data_start:
        wb.save(workbook_path)
        wb.close()
        return

    align_m = Alignment(vertical="center", horizontal="center", wrap_text=True)
    align_c = Alignment(vertical="center", horizontal="left", wrap_text=True)

    def norm(v) -> str:
        if v is None:
            return ""
        return str(v).strip()

    r = data_start
    while r <= max_r:
        m0 = norm(ws.cell(r, col_month).value)
        c0 = norm(ws.cell(r, col_customer).value)
        start = r
        r += 1
        while r <= max_r:
            if norm(ws.cell(r, col_month).value) != m0 or norm(ws.cell(r, col_customer).value) != c0:
                break
            r += 1
        end = r - 1
        if end > start:
            ws.merge_cells(
                start_row=start,
                start_column=col_month,
                end_row=end,
                end_column=col_month,
            )
            ws.merge_cells(
                start_row=start,
                start_column=col_customer,
                end_row=end,
                end_column=col_customer,
            )
            ws.cell(start, col_month).alignment = align_m
            ws.cell(start, col_customer).alignment = align_c
    wb.save(workbook_path)
    wb.close()


def run(
    orders_path: Path,
    contract_map_path: Path,
    out_path: Path,
    orders_sheet: str = "加氢订单",
    map_sheet: str = "Sheet1",
    merge_summary_cells: bool = True,
) -> None:
    orders = pd.read_excel(orders_path, sheet_name=orders_sheet)
    cmap = pd.read_excel(contract_map_path, sheet_name=map_sheet)

    need_o = {"合同编号", "项目名称", "加氢时间", "加氢量(kg)", "对客费用(元)", "成本费用(元)", "订单编号"}
    miss_o = need_o - set(orders.columns)
    if miss_o:
        raise SystemExit(f"加氢订单表缺少列: {miss_o}")

    need_m = {"contract_no", "customer_name"}
    miss_m = need_m - set(cmap.columns)
    if miss_m:
        raise SystemExit(f"合同映射表缺少列: {miss_m}，当前为 {list(cmap.columns)}")

    cmap = cmap[["contract_no", "customer_name"]].copy()
    cmap["contract_no"] = cmap["contract_no"].astype(str).str.strip()

    o = orders.copy()
    o["_合同键"] = o["合同编号"].astype(str).str.strip()

    merged = o.merge(
        cmap,
        left_on="_合同键",
        right_on="contract_no",
        how="left",
        suffixes=("", "_映射表"),
    )
    merged["客户名称"] = merged["customer_name"].fillna("")
    merged = merged.drop(columns=["customer_name", "contract_no"], errors="ignore")

    # 月份
    ts = pd.to_datetime(merged["加氢时间"], errors="coerce")
    merged["月份"] = ts.dt.strftime("%Y-%m")
    merged.loc[ts.isna(), "月份"] = ""

    merged["行加氢总额（元）"] = merged.apply(_line_total_yuan, axis=1)

    # 汇总：月份、客户名称、项目名称、加氢次数、加气量（kg）、加氢总额（元）
    gcols = ["月份", "客户名称", "项目名称"]
    sub = (
        merged.groupby(gcols, dropna=False)
        .agg(
            加氢次数=("订单编号", "count"),
            **{"加气量（kg）": ("加氢量(kg)", "sum")},
            **{"加氢总额（元）": ("行加氢总额（元）", "sum")},
        )
        .reset_index()
    )
    sub = sub.sort_values(gcols).reset_index(drop=True)
    sub["客户名称"] = sub["客户名称"].fillna("").astype(str)
    sub["项目名称"] = sub["项目名称"].fillna("").astype(str)
    sub["月份"] = sub["月份"].fillna("").astype(str)
    drop_from_detail = {"_合同键", "行加氢总额（元）", "月份"}
    base = [c for c in merged.columns if c not in drop_from_detail and c != "客户名称"]
    if "项目名称" in base:
        i = base.index("项目名称") + 1
        detail_out = base[:i] + ["客户名称"] + base[i:]
    else:
        detail_out = base + ["客户名称"]

    detail_df = merged[detail_out].copy()
    detail_df["客户名称"] = detail_df["客户名称"].fillna("").astype(str)

    with pd.ExcelWriter(out_path, engine="openpyxl") as w:
        detail_df.to_excel(w, sheet_name=orders_sheet, index=False)
        sub.to_excel(w, sheet_name="月度客户项目汇总", index=False)

    if merge_summary_cells:
        _merge_month_customer_cells(out_path, sheet_name="月度客户项目汇总")

    print(f"已写入: {out_path}")
    print(f"  明细行数: {len(detail_df)}，已匹配客户名称: {(detail_df['客户名称'] != '').sum()} 行")
    print(f"  汇总行数: {len(sub)}")


def main() -> None:
    ap = argparse.ArgumentParser()
    ap.add_argument("--orders", type=Path, required=True)
    ap.add_argument("--contracts", type=Path, required=True)
    ap.add_argument("-o", "--out", type=Path, required=True)
    ap.add_argument(
        "--no-merge-summary-cells",
        action="store_true",
        help="不对「月度客户项目汇总」做月份/客户名称列合并",
    )
    args = ap.parse_args()
    run(
        args.orders.resolve(),
        args.contracts.resolve(),
        args.out.resolve(),
        merge_summary_cells=not args.no_merge_summary_cells,
    )


if __name__ == "__main__":
    main()
