from __future__ import annotations

import hashlib
import secrets
import tkinter as tk
import json
from copy import copy, deepcopy
from datetime import datetime
from pathlib import Path
from tkinter import filedialog, messagebox, ttk
from urllib.parse import quote, urlparse, urlsplit, urlunsplit
from urllib.request import Request

from openpyxl import Workbook, load_workbook
from openpyxl.utils import get_column_letter
from PIL import ImageTk

from app_core.paths import DATA_DIR, DB_PATH, DEBUG_DIR, PROJECT_DIR
from app_core.http_client import open_url
from app_core.server_api import fetch_app_setting, save_app_setting
from app_core.ui_helpers import configure_striped_treeview, create_contained_photo
from database import get_app_setting, list_order_records, normalize_style_identifier, set_app_setting


PRODUCTION_APP_SETTING_KEY = "production_order_records"
PRODUCTION_FACTORY_APP_SETTING_KEY = "production_factory_records"
PRODUCTION_PACKING_LIST_ASSETS_KEY = "production_packing_list_assets"
PRODUCTION_CARTON_STICKER_ASSETS_KEY = "production_carton_sticker_assets"
PRODUCTION_TREE_THUMBNAIL_LIMIT = 80
PRODUCTION_TREE_RENDER_LIMIT = 500
_PRODUCTION_DEBUG_LOG_PATH = DEBUG_DIR / "production_debug.log"
try:
    if _PRODUCTION_DEBUG_LOG_PATH.exists():
        _PRODUCTION_DEBUG_LOG_PATH.unlink()
except Exception:
    pass


def _append_production_debug_log(message: str) -> None:
    try:
        DEBUG_DIR.mkdir(parents=True, exist_ok=True)
        with _PRODUCTION_DEBUG_LOG_PATH.open("a", encoding="utf-8") as handle:
            handle.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {message}\n")
    except Exception:
        pass

PRODUCTION_COLUMNS = (
    "select_flag",
    "created_at",
    "production_order",
    "factory",
    "mr_pic",
    "buyer",
    "style",
    "parent",
    "season",
    "po_number",
    "po_date",
    "po_time",
    "ship_date",
    "cancel_date",
    "ex_fty_date_plan",
    "actual_ex_fty",
    "color",
    "size_range",
    "size_scale",
    "order_qty",
    "ship_qty",
    "status",
    "over_short_ship_qty",
    "over_short_ship_percent",
    "final_inspection_date",
    "carton_qty",
    "odd_carton_qty",
    "cbm",
    "net_weight",
    "gross_weight",
    "updated_at",
    "latest_user",
)

PRODUCTION_FIELD_LABELS = {
    "select_flag": "Export",
    "created_at": "Create Time",
    "production_order": "Production Order",
    "factory": "Factory",
    "mr_pic": "MR P.I.C",
    "buyer": "Buyer",
    "style": "Style",
    "parent": "Parent",
    "season": "Season",
    "po_number": "PO Number",
    "dept_number": "Dept Number",
    "store_number": "Store",
    "po_date": "PO date",
    "po_time": "PO time",
    "ship_date": "Ship date",
    "cancel_date": "Cancel date",
    "ex_fty_date_plan": "Ex-fty date Plan",
    "actual_ex_fty": "ACTUAL EX-FTY",
    "color": "Color",
    "size_range": "Size Range",
    "size_scale": "Size Scale",
    "order_qty": "Order Qty",
    "ship_qty": "Ship Qty",
    "status": "Status",
    "over_short_ship_qty": "Over/Short ship qty",
    "over_short_ship_percent": "Over/Short ship %",
    "final_inspection_date": "Final inspection date",
    "carton_qty": "Carton Qty",
    "odd_carton_qty": "ODD CARTON QTY",
    "unit_per_carton": "Unit per carton",
    "carton_dimension": "Carton dimension",
    "odd_carton_dimension": "ODD carton dimension",
    "cbm": "CBM",
    "net_weight": "Net weight",
    "gross_weight": "Gross weight",
    "updated_at": "Revised time",
    "latest_user": "Latest User",
}

PRODUCTION_SORT_KEY_OPTIONS = [
    ("created_at", "Create Time"),
    ("production_order", "Production Order"),
    ("factory", "Factory"),
    ("mr_pic", "MR P.I.C"),
    ("buyer", "Buyer"),
    ("style", "Style"),
    ("parent", "Parent"),
    ("season", "Season"),
    ("po_number", "PO Number"),
    ("po_date", "PO date"),
    ("ship_date", "Ship date"),
    ("cancel_date", "Cancel date"),
    ("ex_fty_date_plan", "Ex-fty date Plan"),
    ("actual_ex_fty", "ACTUAL EX-FTY"),
    ("color", "Color"),
    ("order_qty", "Order Qty"),
    ("ship_qty", "Ship Qty"),
    ("status", "Status"),
    ("final_inspection_date", "Final inspection date"),
    ("updated_at", "Revised time"),
]

PRODUCTION_FILTER_FIELD_OPTIONS = [("__all__", "All")] + [
    ("image_path", "Image"),
    *[
    (key, PRODUCTION_FIELD_LABELS[key])
    for key in PRODUCTION_COLUMNS
    if key != "select_flag"
    ],
]

PRODUCTION_DATE_FILTER_FIELDS = {
    "created_at",
    "po_date",
    "ship_date",
    "cancel_date",
    "ex_fty_date_plan",
    "actual_ex_fty",
    "final_inspection_date",
    "updated_at",
}

PRODUCTION_NUMERIC_SORT_FIELDS = {
    "order_qty",
    "ship_qty",
    "over_short_ship_qty",
    "over_short_ship_percent",
    "carton_qty",
    "odd_carton_qty",
    "cbm",
    "net_weight",
    "gross_weight",
}

PRODUCTION_STATUS_OPTIONS = ["draft", "checking", "approved", "shipped", "closed"]
PRODUCTION_CARTON_DIMENSION_OPTIONS = [
    "60 x 48 x 25 (cm)",
    "60 x 48 x 15 (cm)",
]
PRODUCTION_PACKING_LIST_TEMPLATE_PATH = PROJECT_DIR / "assets" / "templates" / "packing_list_form.xlsx"
PRODUCTION_PACKING_LIST_TEMPLATE_FALLBACK_PATH = r"C:\Users\ADMIN\Desktop\Packing list form.xlsx"
PRODUCTION_PACKING_LIST_TEMPLATE_URL = "https://texmind.xyz/shared/packing-list-assets/packing_list_form.xlsx"
PRODUCTION_CARTON_STICKER_TEMPLATE_PATH = PROJECT_DIR / "assets" / "templates" / "Bealls_Carton_Label_Sticker_TAG.xlsx"
PRODUCTION_CARTON_STICKER_TEMPLATE_FALLBACK_PATH = r"C:\Users\ADMIN\Desktop\Bealls_Carton_Label_Sticker_TAG.xlsx"
PRODUCTION_CARTON_STICKER_TEMPLATE_URL = "https://texmind.xyz/shared/carton-sticker-assets/20260727/e572a1c5a646458e8cc18129f6a5f7ed/Bealls_Carton_Label_Sticker_TAG.xlsx"
PRODUCTION_SAVED_DETAIL_KEYS = (
    "record_id",
    "source_type",
    "source_order_id",
    "source_item_key",
    "production_order",
    "style",
    "season",
    "po_number",
    "factory",
    "mr_pic",
    "ex_fty_date_plan",
    "actual_ex_fty",
    "ship_qty",
    "status",
    "final_inspection_date",
    "carton_qty",
    "odd_carton_qty",
    "unit_per_carton",
    "carton_dimension",
    "odd_carton_dimension",
    "cbm",
    "net_weight",
    "gross_weight",
    "updated_at",
    "latest_user",
    "notes",
)
PRODUCTION_STYLE_SEASON_SHARED_KEYS = {
    "factory",
    "mr_pic",
    "unit_per_carton",
}
PRODUCTION_FACTORY_STATUS_OPTIONS = ["Active", "Inactive", "Draft", "Blocked"]
PRODUCTION_FACTORY_COLUMNS = (
    "factory_code",
    "factory_name",
    "contact_person",
    "phone",
    "email",
    "country",
    "status",
    "updated_at",
)
PRODUCTION_PO_LINE_ITEM_COLUMNS = (
    "sku",
    "mfg_style",
    "mfg_color",
    "size_desc",
    "description",
    "upc",
    "cost_unit",
    "comp",
    "retail",
    "pack_qty",
    "total_packs",
    "total_units",
)
PRODUCTION_FACTORY_DEMO_ROWS = [
    {
        "factory_code": "SUN-VN01",
        "factory_name": "Sunny Apparel Vietnam",
        "short_name": "Sunny VN",
        "contact_person": "Ms. Lan",
        "phone": "+84 28 5555 0101",
        "email": "factory.vn@sunny.example",
        "country": "Vietnam",
        "city": "Ho Chi Minh",
        "address_line": "Lot A1, Garment Industrial Park",
        "capacity_month": "120000",
        "status": "Active",
        "note": "Demo factory for woven and knit production.",
    },
    {
        "factory_code": "SUN-CN02",
        "factory_name": "Sunny Garment Shenzhen",
        "short_name": "Sunny SZ",
        "contact_person": "Mr. Chen",
        "phone": "+86 755 5555 0202",
        "email": "factory.sz@sunny.example",
        "country": "China",
        "city": "Shenzhen",
        "address_line": "No. 88 Textile Road",
        "capacity_month": "180000",
        "status": "Active",
        "note": "Demo factory for high-volume programs.",
    },
    {
        "factory_code": "SUN-BD03",
        "factory_name": "Sunny Apparel Dhaka",
        "short_name": "Sunny BD",
        "contact_person": "Mr. Rahman",
        "phone": "+880 2 5555 0303",
        "email": "factory.bd@sunny.example",
        "country": "Bangladesh",
        "city": "Dhaka",
        "address_line": "Sector 7, Export Processing Zone",
        "capacity_month": "150000",
        "status": "Active",
        "note": "Demo factory for value programs.",
    },
]


def _production_now_text() -> str:
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


def _safe_float_value(value: object) -> float:
    text = str(value or "").strip().replace(",", "").replace("%", "")
    if not text:
        return 0.0
    try:
        return float(text)
    except Exception:
        return 0.0


def _format_number(value: float) -> str:
    numeric = round(float(value or 0.0), 4)
    if abs(numeric - round(numeric)) < 1e-9:
        return str(int(round(numeric)))
    return f"{numeric:.4f}".rstrip("0").rstrip(".")


def _excel_number(value: object) -> int | float | str:
    numeric = round(_safe_float_value(value), 4)
    if abs(numeric) < 1e-9:
        return 0
    if abs(numeric - round(numeric)) < 1e-9:
        return int(round(numeric))
    return numeric


def default_production_order_payload() -> dict:
    return {
        "record_id": "",
        "source_type": "",
        "source_order_id": "",
        "source_item_key": "",
        "image_path": "",
        "created_at": "",
        "production_order": "",
        "factory": "",
        "mr_pic": "",
        "buyer": "",
        "style": "",
        "parent": "",
        "season": "",
        "po_number": "",
        "dept_number": "",
        "store_number": "",
        "po_date": "",
        "po_time": "",
        "ship_date": "",
        "cancel_date": "",
        "ex_fty_date_plan": "",
        "actual_ex_fty": "",
        "color": "",
        "size_range": "",
        "size_scale": "",
        "order_qty": "",
        "ship_qty": "",
        "status": "draft",
        "over_short_ship_qty": "",
        "over_short_ship_percent": "",
        "final_inspection_date": "",
        "carton_qty": "",
        "odd_carton_qty": "",
        "unit_per_carton": "",
        "carton_dimension": "",
        "odd_carton_dimension": "",
        "cbm": "",
        "net_weight": "",
        "gross_weight": "",
        "color_quantity_json": "",
        "updated_at": "",
        "latest_user": "",
        "notes": "",
    }


def default_production_factory_payload() -> dict:
    return {
        "factory_id": "",
        "factory_code": "",
        "factory_name": "",
        "short_name": "",
        "contact_person": "",
        "phone": "",
        "email": "",
        "country": "",
        "city": "",
        "address_line": "",
        "capacity_month": "",
        "status": "Active",
        "created_at": "",
        "updated_at": "",
        "note": "",
    }


def normalize_production_factory_row(payload: object) -> dict | None:
    if not isinstance(payload, dict):
        return None
    normalized = default_production_factory_payload()
    for key in normalized:
        normalized[key] = str(payload.get(key, normalized[key]) or "").strip()
    normalized["factory_id"] = normalized["factory_id"] or secrets.token_hex(16)
    normalized["factory_code"] = normalized["factory_code"].upper()
    status = normalized["status"].strip().lower()
    status_map = {item.lower(): item for item in PRODUCTION_FACTORY_STATUS_OPTIONS}
    normalized["status"] = status_map.get(status, "Active")
    if not normalized["created_at"]:
        normalized["created_at"] = _production_now_text()
    if not normalized["updated_at"]:
        normalized["updated_at"] = normalized["created_at"]
    return normalized


def _normalize_production_factory_rows(payload: object) -> list[dict]:
    if not isinstance(payload, list):
        return []
    rows: list[dict] = []
    for item in payload:
        normalized = normalize_production_factory_row(item)
        if isinstance(normalized, dict):
            rows.append(normalized)
    return rows


def _production_demo_factory_rows() -> list[dict]:
    rows: list[dict] = []
    for item in PRODUCTION_FACTORY_DEMO_ROWS:
        normalized = normalize_production_factory_row(item)
        if isinstance(normalized, dict):
            rows.append(normalized)
    return rows


def default_production_packing_list_assets() -> dict[str, object]:
    return {"template_url": PRODUCTION_PACKING_LIST_TEMPLATE_URL}


def default_production_carton_sticker_assets() -> dict[str, object]:
    return {"template_url": PRODUCTION_CARTON_STICKER_TEMPLATE_URL}


def normalize_production_order_row(payload: object) -> dict | None:
    if not isinstance(payload, dict):
        return None
    normalized = default_production_order_payload()
    for key in normalized:
        normalized[key] = str(payload.get(key, normalized[key]) or "").strip()
    normalized["record_id"] = normalized["record_id"] or secrets.token_hex(16)
    normalized["style"] = normalize_style_identifier(normalized.get("style"))
    normalized["status"] = str(normalized.get("status") or "draft").strip().lower() or "draft"
    if normalized["status"] not in PRODUCTION_STATUS_OPTIONS:
        normalized["status"] = "draft"
    if not normalized["created_at"]:
        normalized["created_at"] = _production_now_text()
    if not normalized["updated_at"]:
        normalized["updated_at"] = normalized["created_at"]
    if not normalized["production_order"]:
        normalized["production_order"] = f"PROD-{normalized['record_id'][:8].upper()}"
    _recalculate_production_balance(normalized)
    _recalculate_production_packing(normalized)
    return normalized


def _recalculate_production_balance(row: dict) -> None:
    order_qty = _safe_float_value(row.get("order_qty"))
    ship_qty = _safe_float_value(row.get("ship_qty"))
    if not order_qty and not ship_qty:
        return
    diff = ship_qty - order_qty
    row["over_short_ship_qty"] = _format_number(diff)
    if order_qty:
        row["over_short_ship_percent"] = f"{_format_number(diff / order_qty * 100)}%"


def _recalculate_production_packing(row: dict) -> None:
    ship_qty = _safe_float_value(row.get("ship_qty"))
    unit_per_carton = _safe_float_value(row.get("unit_per_carton"))
    if ship_qty <= 0 or unit_per_carton <= 0:
        row["carton_qty"] = ""
        row["odd_carton_qty"] = ""
        row["odd_carton_dimension"] = ""
        return
    full_cartons = int(ship_qty // unit_per_carton)
    odd_qty = ship_qty - (full_cartons * unit_per_carton)
    row["carton_qty"] = str(full_cartons)
    row["odd_carton_qty"] = _format_number(odd_qty)
    if odd_qty <= 0:
        row["odd_carton_dimension"] = ""
    elif odd_qty >= unit_per_carton / 2:
        row["odd_carton_dimension"] = "60 x 48 x 25 (cm)"
    else:
        row["odd_carton_dimension"] = "60 x 48 x 15 (cm)"


def _normalize_production_rows(payload: object) -> list[dict]:
    if not isinstance(payload, list):
        return []
    rows: list[dict] = []
    for item in payload:
        normalized = normalize_production_order_row(item)
        if isinstance(normalized, dict):
            rows.append(normalized)
    return rows


def _production_style_season_key(row: dict) -> tuple[str, str]:
    style = normalize_style_identifier(row.get("style"))
    season = " ".join(str(row.get("season", "") or "").strip().lower().split())
    return (style, season)


def _production_row_updated_sort_value(row: dict) -> str:
    return str(row.get("updated_at", "") or row.get("created_at", "") or "").strip()


def _production_shared_fields_from_row(row: dict) -> dict[str, str]:
    return {
        key: str(row.get(key, "") or "").strip()
        for key in PRODUCTION_STYLE_SEASON_SHARED_KEYS
    }


def _apply_production_shared_fields(row: dict, shared_values: dict[str, str], *, updated_at: str = "") -> dict:
    merged = dict(row)
    for key in PRODUCTION_STYLE_SEASON_SHARED_KEYS:
        merged[key] = str(shared_values.get(key, "") or "").strip()
    if updated_at:
        merged["updated_at"] = updated_at
    _recalculate_production_packing(merged)
    return normalize_production_order_row(merged) or merged


def _production_saved_shared_fields_by_style_season(saved_rows: list[dict]) -> dict[tuple[str, str], dict[str, str]]:
    grouped: dict[tuple[str, str], dict[str, str]] = {}
    for row in sorted(saved_rows, key=_production_row_updated_sort_value):
        style_season_key = _production_style_season_key(row)
        if not style_season_key[0]:
            continue
        values = _production_shared_fields_from_row(row)
        if any(values.values()):
            grouped[style_season_key] = values
    return grouped


def load_production_rows_from_source(self) -> list[dict]:
    self.production_source_initialized = False
    _append_production_debug_log(
        "load-source start "
        f"use_server={self.should_use_server_data_source()} "
        f"data_mode={getattr(self, 'server_settings', {}).get('data_mode', '') if isinstance(getattr(self, 'server_settings', {}), dict) else ''} "
        f"db_path={DB_PATH}"
    )
    if self.should_use_server_data_source():
        try:
            payload = fetch_app_setting(self.server_settings, PRODUCTION_APP_SETTING_KEY, None)
            self.production_source_initialized = isinstance(payload, list)
            rows = _normalize_production_rows(payload)
            _append_production_debug_log(
                f"load-source server initialized={self.production_source_initialized} rows={len(rows)} payload_type={type(payload).__name__}"
            )
            if rows:
                return rows
            local_payload = get_app_setting(DB_PATH, PRODUCTION_APP_SETTING_KEY, None)
            local_rows = _normalize_production_rows(local_payload)
            _append_production_debug_log(
                f"load-source server empty fallback local initialized={isinstance(local_payload, list)} "
                f"rows={len(local_rows)} payload_type={type(local_payload).__name__}"
            )
            if local_rows:
                self.production_source_initialized = True
                self.production_source_is_local_fallback = True
                return local_rows
        except Exception as exc:
            _append_production_debug_log(f"load-source server failed: {exc}")
    payload = get_app_setting(DB_PATH, PRODUCTION_APP_SETTING_KEY, None)
    self.production_source_initialized = isinstance(payload, list)
    rows = _normalize_production_rows(payload)
    _append_production_debug_log(
        f"load-source local initialized={self.production_source_initialized} rows={len(rows)} payload_type={type(payload).__name__}"
    )
    return rows


def save_production_rows_to_source(self, rows: list[dict]) -> list[dict]:
    normalized_rows = _normalize_production_rows(rows)
    self.production_source_initialized = True
    _append_production_debug_log(
        f"save-source start rows={len(normalized_rows)} use_server={self.should_use_server_data_source()}"
    )
    if self.should_use_server_data_source():
        saved = _normalize_production_rows(save_app_setting(self.server_settings, PRODUCTION_APP_SETTING_KEY, normalized_rows))
        _append_production_debug_log(f"save-source server done rows={len(saved)}")
        return saved
    saved = _normalize_production_rows(set_app_setting(DB_PATH, PRODUCTION_APP_SETTING_KEY, normalized_rows))
    _append_production_debug_log(f"save-source local done rows={len(saved)}")
    return saved


def _compact_production_saved_detail_row(row: dict) -> dict:
    compact: dict[str, str] = {}
    for key in PRODUCTION_SAVED_DETAIL_KEYS:
        value = str(row.get(key, "") or "").strip()
        if value or key == "record_id":
            compact[key] = value
    return compact


def save_production_saved_detail_rows_to_source(self, rows: list[dict]) -> list[dict]:
    compact_rows = [
        _compact_production_saved_detail_row(row)
        for row in list(rows or [])
        if isinstance(row, dict) and str(row.get("record_id", "") or "").strip()
    ]
    _append_production_debug_log(
        f"save-detail-overlays start rows={len(compact_rows)} use_server={self.should_use_server_data_source()}"
    )
    if self.should_use_server_data_source():
        saved = _normalize_production_rows(save_app_setting(self.server_settings, PRODUCTION_APP_SETTING_KEY, compact_rows))
        _append_production_debug_log(f"save-detail-overlays server done rows={len(saved)}")
        return saved
    saved = _normalize_production_rows(set_app_setting(DB_PATH, PRODUCTION_APP_SETTING_KEY, compact_rows))
    _append_production_debug_log(f"save-detail-overlays local done rows={len(saved)}")
    return saved


def save_production_detail_row_to_source(self, row: dict) -> dict:
    normalized = normalize_production_order_row(row)
    if not isinstance(normalized, dict):
        return {}
    record_id = str(normalized.get("record_id", "") or "").strip()
    if not record_id:
        return {}
    style_season_key = _production_style_season_key(normalized)
    shared_values = _production_shared_fields_from_row(normalized)
    updated_at = str(normalized.get("updated_at", "") or "").strip() or _production_now_text()
    current_rows = self.load_production_rows_from_source()
    known_rows_by_id: dict[str, dict] = {}
    for source_row in list(getattr(self, "production_rows", []) or []) + list(current_rows or []):
        if not isinstance(source_row, dict):
            continue
        source_id = str(source_row.get("record_id", "") or "").strip()
        if source_id:
            known_rows_by_id[source_id] = dict(source_row)
    known_rows_by_id[record_id] = dict(normalized)
    merged_rows: list[dict] = []
    written_ids: set[str] = set()
    for existing_row in list(current_rows or []):
        existing_id = str(existing_row.get("record_id", "") or "").strip()
        if not existing_id:
            continue
        if existing_id == record_id:
            merged_rows.append(normalized)
            written_ids.add(existing_id)
            continue
        if style_season_key[0] and _production_style_season_key(existing_row) == style_season_key:
            merged_rows.append(_apply_production_shared_fields(dict(existing_row), shared_values, updated_at=updated_at))
            written_ids.add(existing_id)
        else:
            merged_rows.append(dict(existing_row))
            written_ids.add(existing_id)
    for known_id, known_row in known_rows_by_id.items():
        if known_id in written_ids:
            continue
        if known_id == record_id:
            merged_rows.append(normalized)
            written_ids.add(known_id)
            continue
        if style_season_key[0] and _production_style_season_key(known_row) == style_season_key:
            merged_rows.append(_apply_production_shared_fields(dict(known_row), shared_values, updated_at=updated_at))
            written_ids.add(known_id)
    if record_id not in written_ids:
        merged_rows.append(normalized)
    saved_rows = self.save_production_saved_detail_rows_to_source(merged_rows)
    return next((dict(item) for item in saved_rows if str(item.get("record_id", "") or "").strip() == record_id), normalized)


def delete_production_detail_rows_from_source(self, record_ids: set[str]) -> None:
    target_ids = {str(item or "").strip() for item in record_ids if str(item or "").strip()}
    if not target_ids:
        return
    remaining_rows = [
        row
        for row in self.load_production_rows_from_source()
        if str(row.get("record_id", "") or "").strip() not in target_ids
    ]
    self.save_production_saved_detail_rows_to_source(remaining_rows)


def load_production_factory_rows_from_source(self) -> list[dict]:
    rows: list[dict] = []
    if self.should_use_server_data_source():
        try:
            payload = fetch_app_setting(self.server_settings, PRODUCTION_FACTORY_APP_SETTING_KEY, [])
            rows = _normalize_production_factory_rows(payload)
        except Exception:
            rows = []
    if not rows:
        payload = get_app_setting(DB_PATH, PRODUCTION_FACTORY_APP_SETTING_KEY, [])
        rows = _normalize_production_factory_rows(payload)
    if rows:
        return rows
    demo_rows = _production_demo_factory_rows()
    if demo_rows:
        return save_production_factory_rows_to_source(self, demo_rows)
    return []


def save_production_factory_rows_to_source(self, rows: list[dict]) -> list[dict]:
    normalized_rows = _normalize_production_factory_rows(rows)
    if self.should_use_server_data_source():
        try:
            saved = _normalize_production_factory_rows(
                save_app_setting(self.server_settings, PRODUCTION_FACTORY_APP_SETTING_KEY, normalized_rows)
            )
            if saved:
                return saved
        except Exception:
            pass
    return _normalize_production_factory_rows(set_app_setting(DB_PATH, PRODUCTION_FACTORY_APP_SETTING_KEY, normalized_rows))


def save_production_factory_row_to_source(self, row: dict) -> dict:
    normalized = normalize_production_factory_row(row)
    if not isinstance(normalized, dict):
        return {}
    current_rows = self.load_production_factory_rows_from_source()
    factory_id = str(normalized.get("factory_id", "")).strip()
    rows: list[dict] = []
    replaced = False
    for existing_row in current_rows:
        if str(existing_row.get("factory_id", "")).strip() == factory_id:
            rows.append(normalized)
            replaced = True
        else:
            rows.append(dict(existing_row))
    if not replaced:
        rows.append(normalized)
    saved_rows = self.save_production_factory_rows_to_source(rows)
    return next((dict(item) for item in saved_rows if str(item.get("factory_id", "")).strip() == factory_id), normalized)


def delete_production_factory_row_from_source(self, factory_id: str) -> None:
    normalized_id = str(factory_id or "").strip()
    if not normalized_id:
        return
    remaining = [
        row
        for row in self.load_production_factory_rows_from_source()
        if str(row.get("factory_id", "")).strip() != normalized_id
    ]
    self.save_production_factory_rows_to_source(remaining)


def get_active_production_factory_names(self) -> list[str]:
    rows = list(getattr(self, "production_factory_rows", []) or [])
    if not rows:
        rows = self.load_production_factory_rows_from_source()
        self.production_factory_rows = rows
    names = []
    seen: set[str] = set()
    for row in rows:
        if str(row.get("status", "")).strip().lower() != "active":
            continue
        name = str(row.get("factory_name", "") or row.get("short_name", "") or row.get("factory_code", "") or "").strip()
        if not name or name.lower() in seen:
            continue
        seen.add(name.lower())
        names.append(name)
    return sorted(names, key=str.lower)


def _production_saved_row_map(self) -> dict[str, dict]:
    rows = self.load_production_rows_from_source()
    return {
        str(row.get("record_id", "")).strip(): dict(row)
        for row in rows
        if str(row.get("record_id", "")).strip()
    }


def _merge_production_saved_fields(row: dict, saved_row: dict | None) -> dict:
    if not isinstance(saved_row, dict):
        return row
    merged = dict(row)
    merge_keys = {
        "factory",
        "mr_pic",
        "ex_fty_date_plan",
        "actual_ex_fty",
        "ship_qty",
        "status",
        "final_inspection_date",
        "carton_qty",
        "odd_carton_qty",
        "unit_per_carton",
        "carton_dimension",
        "odd_carton_dimension",
        "cbm",
        "net_weight",
        "gross_weight",
        "color_quantity_json",
        "notes",
    }
    for key in merge_keys:
        saved_value = str(saved_row.get(key, "") or "").strip()
        if saved_value:
            merged[key] = saved_value
    if str(saved_row.get("updated_at", "") or "").strip():
        merged["updated_at"] = str(saved_row.get("updated_at", "") or "").strip()
    _recalculate_production_balance(merged)
    return merged


def _production_order_line_items(order: dict) -> list[dict]:
    raw_payload = order.get("raw_json")
    parsed_payload = {}
    if isinstance(raw_payload, str) and raw_payload.strip():
        try:
            parsed_payload = json.loads(raw_payload)
        except Exception:
            parsed_payload = {}
    if not isinstance(parsed_payload, dict):
        return []
    for key in ("items", "line_items"):
        items = parsed_payload.get(key, [])
        if isinstance(items, list):
            return [dict(item) for item in items if isinstance(item, dict)]
    return []


def _production_items_for_style(order: dict, style: str) -> list[dict]:
    target_style = normalize_style_identifier(style)
    items = _production_order_line_items(order)
    if not target_style:
        return items
    matched_items = [
        item
        for item in items
        if normalize_style_identifier(item.get("mfg_style") or item.get("style_code")) == target_style
    ]
    return matched_items or items


def _production_style_size_summary(self, order: dict, style: str) -> tuple[str, str]:
    items = [
        item
        for item in _production_items_for_style(order, style)
        if str(item.get("size_desc", "") or "").strip()
    ]
    if not items:
        return (str(order.get("size_range", "") or ""), str(order.get("size_scale", "") or ""))
    raw_sizes = [str(item.get("size_desc", "") or "").strip() for item in items]
    if hasattr(self, "sort_size_codes"):
        ordered_sizes = self.sort_size_codes(raw_sizes)
    else:
        ordered_sizes = []
        seen: set[str] = set()
        for raw_size in raw_sizes:
            size_code = str(raw_size or "").strip().upper().replace(" ", "")
            if size_code and size_code not in seen:
                seen.add(size_code)
                ordered_sizes.append(size_code)
    size_ratio_map: dict[str, str] = {}
    for item in items:
        size_code = self.normalize_size_code(item.get("size_desc")) if hasattr(self, "normalize_size_code") else str(item.get("size_desc", "") or "").strip().upper().replace(" ", "")
        if not size_code or size_code in size_ratio_map:
            continue
        size_ratio_map[size_code] = str(item.get("pack_qty", "") or "").strip() or "-"
    return (
        "-".join(ordered_sizes),
        "-".join(size_ratio_map.get(size_code, "-") for size_code in ordered_sizes),
    )


def _production_style_color_summary(order: dict, style: str) -> str:
    colors: list[str] = []
    seen: set[str] = set()
    for item in _production_items_for_style(order, style):
        color = str(item.get("mfg_color") or item.get("color") or item.get("color_label") or "").strip()
        if not color or color.lower() in seen:
            continue
        seen.add(color.lower())
        colors.append(color)
    return ", ".join(colors)


def _production_style_order_qty(order: dict, style: str) -> str:
    total = 0.0
    has_total = False
    for item in _production_items_for_style(order, style):
        item_total = _safe_float_value(item.get("total_units"))
        if item_total:
            total += item_total
            has_total = True
    if has_total:
        return _format_number(total)
    return str(order.get("total_qty", "") or "").strip()


def _production_detail_order_payload(self, production_row: dict) -> dict:
    source_order_id = str(production_row.get("source_order_id", "") or "").strip()
    if source_order_id and source_order_id.isdigit() and hasattr(self, "fetch_order_detail_from_source"):
        try:
            detail = self.fetch_order_detail_from_source(int(source_order_id))
            if isinstance(detail, dict):
                return detail
        except Exception:
            pass
    po_number = str(production_row.get("po_number", "") or "").strip()
    for candidate in list(getattr(self, "all_order_versions", []) or []) + list(getattr(self, "all_orders", []) or []):
        if not isinstance(candidate, dict):
            continue
        if source_order_id and str(candidate.get("id", "") or "").strip() == source_order_id:
            return {"header": dict(candidate), "items": _production_order_line_items(candidate)}
        if po_number and str(candidate.get("po_number", "") or "").strip() == po_number:
            return {"header": dict(candidate), "items": _production_order_line_items(candidate)}
    cached_payload = self.load_main_ui_session_cache("purchase_order") if hasattr(self, "load_main_ui_session_cache") else None
    if isinstance(cached_payload, dict):
        for payload_key in ("all_order_versions", "order_versions", "all_orders"):
            for candidate in list(cached_payload.get(payload_key, []) or []):
                if not isinstance(candidate, dict):
                    continue
                if source_order_id and str(candidate.get("id", "") or "").strip() == source_order_id:
                    return {"header": dict(candidate), "items": _production_order_line_items(candidate)}
                if po_number and str(candidate.get("po_number", "") or "").strip() == po_number:
                    return {"header": dict(candidate), "items": _production_order_line_items(candidate)}
    return {"header": dict(production_row), "items": []}


def get_production_po_detail_line_items(self, production_row: dict) -> list[dict]:
    detail = _production_detail_order_payload(self, production_row)
    items = [dict(item) for item in list(detail.get("items", []) or []) if isinstance(item, dict)]
    style = normalize_style_identifier(production_row.get("style"))
    if not style:
        return items
    matched = [
        item
        for item in items
        if normalize_style_identifier(item.get("mfg_style") or item.get("style_code")) == style
    ]
    return matched or items


def production_unit_per_pack(self, production_row: dict) -> str:
    total = 0.0
    has_value = False
    for item in self.get_production_po_detail_line_items(production_row):
        value = _safe_float_value(item.get("pack_qty"))
        if value:
            total += value
            has_value = True
    return _format_number(total) if has_value else "0"


def _production_is_missing_text(value: object) -> bool:
    text = str(value or "").strip()
    return not text or text in {"-", "--", "N/A", "n/a"}


def _production_resolve_season(self, order: dict, style: str) -> str:
    for key in ("season", "season_display"):
        value = str(order.get(key, "") or "").strip()
        if not _production_is_missing_text(value):
            return value
    if hasattr(self, "get_style_season"):
        value = str(self.get_style_season(style) or "").strip()
        if not _production_is_missing_text(value):
            return value
    cached_lookup = self.build_cached_style_season_lookup() if hasattr(self, "build_cached_style_season_lookup") else {}
    if isinstance(cached_lookup, dict):
        value = str(cached_lookup.get(normalize_style_identifier(style), "") or "").strip()
        if not _production_is_missing_text(value):
            return value
    return ""


def _production_parent_from_tech_pack_row(row: dict, normalized_style: str) -> str:
    parent_summary = str(row.get("parent_summary", "") or "").strip()
    if parent_summary:
        return parent_summary
    overview_data = row.get("overview_data", {})
    if not isinstance(overview_data, dict):
        overview_data = {}
    lead_style_value = str(overview_data.get("lead_style_no", "") or "").strip()
    normalized_lead_style = normalize_style_identifier(lead_style_value)
    if lead_style_value.lower() == "lead" or normalized_lead_style == normalized_style:
        return "Lead"
    return normalized_lead_style


def _production_cached_style_parent_lookup(self) -> dict[str, str]:
    lookup: dict[str, str] = {}

    def add(row: dict) -> None:
        if not isinstance(row, dict):
            return
        style_code = normalize_style_identifier(row.get("style_code"))
        if not style_code or style_code in lookup:
            return
        parent = _production_parent_from_tech_pack_row(row, style_code)
        if parent:
            lookup[style_code] = parent

    for payload_key in ("tech_pack_rows", "tech_pack_library"):
        for row in list(getattr(self, payload_key, []) or []):
            add(row)

    if hasattr(self, "load_main_ui_session_cache"):
        for cache_scope in ("tech_pack", "production", "bom"):
            cached_payload = self.load_main_ui_session_cache(cache_scope)
            if not isinstance(cached_payload, dict):
                continue
            for payload_key in ("tech_pack_rows", "tech_pack_library"):
                for row in list(cached_payload.get(payload_key, []) or []):
                    add(row)

    if not lookup and hasattr(self, "load_tech_pack_library_from_source"):
        try:
            rows = [dict(row) for row in list(self.load_tech_pack_library_from_source() or []) if isinstance(row, dict)]
            if rows and not getattr(self, "tech_pack_library", None):
                self.tech_pack_library = rows
            for row in rows:
                add(row)
        except Exception as exc:
            _append_production_debug_log(f"parent lookup load tech-pack source failed: {exc}")

    return lookup


def _production_resolve_parent(self, style: str, parent_lookup: dict[str, str] | None = None) -> str:
    normalized_style = normalize_style_identifier(style)
    if not normalized_style:
        return ""
    lookup = parent_lookup if isinstance(parent_lookup, dict) else _production_cached_style_parent_lookup(self)
    return str(lookup.get(normalized_style, "") or "").strip()


def _production_po_display_source_rows(self) -> list[dict]:
    if getattr(self, "all_orders", None):
        rows = [dict(item) for item in list(getattr(self, "all_orders", []) or []) if isinstance(item, dict)]
        _append_production_debug_log(f"build-from-po using current all_orders rows={len(rows)}")
        return rows

    cached_payload = self.load_main_ui_session_cache("purchase_order") if hasattr(self, "load_main_ui_session_cache") else None
    active_prefixes = self.get_active_collection_prefixes() if hasattr(self, "get_active_collection_prefixes") else set()
    if isinstance(cached_payload, dict):
        if isinstance(cached_payload.get("all_order_versions"), list):
            version_rows = [
                dict(row)
                for row in list(cached_payload.get("all_order_versions", []) or [])
                if isinstance(row, dict)
            ]
            rows = self.build_purchase_order_style_display_rows(self.extract_latest_purchase_order_versions(version_rows))
            _append_production_debug_log(f"build-from-po using purchase_order cache all_order_versions={len(version_rows)} rows={len(rows)}")
            return rows
        if isinstance(cached_payload.get("order_versions"), list):
            source_rows = [
                dict(row)
                for row in list(cached_payload.get("order_versions", []) or [])
                if isinstance(row, dict)
            ]
            version_rows = [self.enrich_order_row(row, active_prefixes=active_prefixes) for row in source_rows]
            rows = self.build_purchase_order_style_display_rows(self.extract_latest_purchase_order_versions(version_rows))
            _append_production_debug_log(f"build-from-po using purchase_order cache order_versions={len(source_rows)} rows={len(rows)}")
            return rows
        if isinstance(cached_payload.get("all_orders"), list):
            rows = [
                dict(row)
                for row in list(cached_payload.get("all_orders", []) or [])
                if isinstance(row, dict)
            ]
            _append_production_debug_log(f"build-from-po using purchase_order cache all_orders rows={len(rows)}")
            return rows

    if hasattr(self, "fetch_order_records_from_source"):
        try:
            source_rows = [dict(item) for item in self.fetch_order_records_from_source() if isinstance(item, dict)]
            version_rows = [self.enrich_order_row(row, active_prefixes=active_prefixes) for row in source_rows]
            rows = self.build_purchase_order_style_display_rows(self.extract_latest_purchase_order_versions(version_rows))
            _append_production_debug_log(f"build-from-po fetched source_order_versions={len(source_rows)} rows={len(rows)}")
            return rows
        except Exception as exc:
            _append_production_debug_log(f"build-from-po fetch_order_records_from_source failed: {exc}")

    try:
        source_rows = [dict(item) for item in list_order_records(DB_PATH)]
        version_rows = [self.enrich_order_row(row, active_prefixes=active_prefixes) for row in source_rows]
        rows = self.build_purchase_order_style_display_rows(self.extract_latest_purchase_order_versions(version_rows))
        _append_production_debug_log(f"build-from-po local fallback source_order_versions={len(source_rows)} rows={len(rows)}")
        return rows
    except Exception as exc:
        _append_production_debug_log(f"build-from-po local fallback failed: {exc}")
        return []


def _build_production_row_from_po(self, order: dict, line_index: int, parent_lookup: dict[str, str] | None = None) -> dict:
    header = dict(order)
    style = normalize_style_identifier(header.get("style"))
    base_order_id = self.po_base_order_id(header) if hasattr(self, "po_base_order_id") else int(header.get("id", 0) or 0)
    display_id = str(header.get("po_display_row_id", "") or "").strip() or str(base_order_id or header.get("po_number", "") or line_index)
    safe_style_key = style or str(line_index)
    record_id = f"po-{base_order_id}-{safe_style_key}"
    po_number = str(header.get("po_number", "") or "").strip()
    size_range, size_scale = _production_style_size_summary(self, header, style)
    return normalize_production_order_row(
        {
            "record_id": record_id,
            "source_type": "purchase_order",
            "source_order_id": str(base_order_id or header.get("id", "") or "").strip(),
            "source_item_key": display_id,
            "created_at": str(header.get("created_at", "") or ""),
            "production_order": f"PROD-{po_number}-{style or line_index}",
            "buyer": str(header.get("buyer_name", "") or header.get("buyer", "") or ""),
            "style": style,
            "parent": _production_resolve_parent(self, style, parent_lookup),
            "season": _production_resolve_season(self, header, style),
            "po_number": po_number,
            "dept_number": str(header.get("dept_number", "") or ""),
            "store_number": str(header.get("store_number", "") or ""),
            "po_date": str(header.get("po_date", "") or ""),
            "po_time": str(header.get("po_time", "") or ""),
            "ship_date": str(header.get("ship_date", "") or ""),
            "cancel_date": str(header.get("cancel_date", "") or ""),
            "color": _production_style_color_summary(header, style),
            "size_range": size_range,
            "size_scale": size_scale,
            "order_qty": _production_style_order_qty(header, style),
            "status": str(header.get("status", "") or "draft"),
            "updated_at": str(header.get("updated_at", "") or ""),
        }
    ) or {}


def build_production_rows_from_purchase_orders(self) -> list[dict]:
    source_orders = _production_po_display_source_rows(self)
    _append_production_debug_log(f"build-from-po start po_display_rows={len(source_orders)}")
    saved_rows_by_id = _production_saved_row_map(self)
    saved_shared_by_style_season = _production_saved_shared_fields_by_style_season(list(saved_rows_by_id.values()))
    parent_lookup = _production_cached_style_parent_lookup(self)
    _append_production_debug_log(f"build-from-po parent_lookup={len(parent_lookup)}")
    rows: list[dict] = []
    for line_index, order in enumerate(source_orders, start=1):
        if not isinstance(order, dict):
            continue
        row = _build_production_row_from_po(self, order, line_index, parent_lookup)
        if row:
            merged = _merge_production_saved_fields(row, saved_rows_by_id.get(str(row.get("record_id", "")).strip()))
            shared_values = saved_shared_by_style_season.get(_production_style_season_key(merged))
            if shared_values:
                merged = _apply_production_shared_fields(merged, shared_values)
            rows.append(merged)
    _append_production_debug_log(f"build-from-po done rows={len(rows)}")
    return rows


def refresh_production_module(self) -> None:
    _append_production_debug_log("refresh-module start")
    self.production_rows = self.build_production_rows_from_purchase_orders()
    _append_production_debug_log(f"refresh-module built from purchase_order rows={len(self.production_rows)}")
    for row in self.production_rows:
        row["latest_user"] = self.get_entity_latest_user_display("production", row.get("record_id", "")) if hasattr(self, "get_entity_latest_user_display") else row.get("latest_user", "")
    self.apply_production_filter()
    _append_production_debug_log(
        f"refresh-module done production_rows={len(getattr(self, 'production_rows', []) or [])} "
        f"filtered={len(getattr(self, 'filtered_production_rows', []) or [])}"
    )


def _build_production_module(self, parent: ttk.Frame) -> None:
    _append_production_debug_log("build-ui start")
    parent.columnconfigure(0, weight=1)
    parent.rowconfigure(3, weight=1)

    toolbar = ttk.Frame(parent)
    toolbar.grid(row=0, column=0, sticky="ew")
    self.widget_text["production_edit_button"] = ttk.Button(toolbar, text="Edit", command=self.edit_selected_production_order)
    self.widget_text["production_edit_button"].pack(side="left")
    self.register_permission_widget("action.production.edit", self.widget_text["production_edit_button"])
    self.widget_text["production_delete_button"] = ttk.Button(toolbar, text="Delete", command=self.delete_selected_production_order)
    self.widget_text["production_delete_button"].pack(side="left", padx=(8, 0))
    self.register_permission_widget("action.production.delete", self.widget_text["production_delete_button"])
    self.widget_text["production_export_button"] = ttk.Button(toolbar, text="Export report", command=self.export_production_report)
    self.widget_text["production_export_button"].pack(side="left", padx=(8, 0))
    self.register_permission_widget("action.production.export_report", self.widget_text["production_export_button"])
    self.widget_text["production_packing_list_button"] = ttk.Button(toolbar, text="Packing List", command=self.export_selected_production_packing_list)
    self.widget_text["production_packing_list_button"].pack(side="left", padx=(8, 0))
    self.register_permission_widget("action.production.packing_list", self.widget_text["production_packing_list_button"])
    self.widget_text["production_carton_sticker_button"] = ttk.Button(toolbar, text="Carton sticker", command=self.export_selected_production_carton_stickers)
    self.widget_text["production_carton_sticker_button"].pack(side="left", padx=(8, 0))
    self.register_permission_widget("action.production.packing_list", self.widget_text["production_carton_sticker_button"])
    self.widget_text["production_factory_list_button"] = ttk.Button(toolbar, text="Factory list", command=self.open_production_factory_list_window)
    self.widget_text["production_factory_list_button"].pack(side="left", padx=(8, 0))
    self.register_permission_widget("action.production.factory_list", self.widget_text["production_factory_list_button"])

    meta = ttk.Frame(parent)
    meta.grid(row=1, column=0, sticky="ew", pady=(12, 14))
    meta.columnconfigure(8, weight=1)
    ttk.Label(meta, text="Select").grid(row=0, column=0, sticky="w", padx=(0, 6))
    self.production_filter_field_combo = ttk.Combobox(meta, textvariable=self.production_filter_field_var, state="readonly", width=24)
    self.production_filter_field_combo.grid(row=0, column=1, sticky="w")
    self.production_filter_field_combo.bind("<<ComboboxSelected>>", self.on_production_filter_field_changed)
    ttk.Label(meta, text="Value").grid(row=0, column=2, sticky="w", padx=(12, 6))
    self.production_search_entry = ttk.Entry(meta, textvariable=self.production_search_var, width=36)
    self.production_search_entry.grid(row=0, column=3, sticky="w")
    self.production_search_entry.bind("<Return>", self.on_production_search_submit)
    self.production_search_entry.bind("<KP_Enter>", self.on_production_search_submit)
    ttk.Label(meta, text="From").grid(row=0, column=4, sticky="w", padx=(12, 6))
    self.production_date_from_entry = ttk.Entry(meta, textvariable=self.production_date_from_var, width=12)
    self.production_date_from_entry.grid(row=0, column=5, sticky="w", padx=(0, 12))
    self.bind_date_entry_picker(self.production_date_from_entry, self.production_date_from_var)
    self.production_date_from_var.trace_add("write", lambda *_args: self.apply_production_filter())
    ttk.Label(meta, text="To").grid(row=0, column=6, sticky="w", padx=(0, 6))
    self.production_date_to_entry = ttk.Entry(meta, textvariable=self.production_date_to_var, width=12)
    self.production_date_to_entry.grid(row=0, column=7, sticky="w")
    self.bind_date_entry_picker(self.production_date_to_entry, self.production_date_to_var)
    self.production_date_to_var.trace_add("write", lambda *_args: self.apply_production_filter())
    ttk.Label(meta, text="Sort by").grid(row=1, column=0, sticky="w", pady=(8, 0), padx=(0, 6))
    self.production_sort_key_combo = ttk.Combobox(meta, textvariable=self.production_sort_key_var, state="readonly", width=22)
    self.production_sort_key_combo.grid(row=1, column=1, sticky="w", pady=(8, 0))
    self.production_sort_key_combo.bind("<<ComboboxSelected>>", self.on_production_sort_key_changed)
    ttk.Label(meta, text="Order").grid(row=1, column=2, sticky="w", pady=(8, 0), padx=(12, 6))
    self.production_sort_order_combo = ttk.Combobox(meta, textvariable=self.production_sort_order_var, state="readonly", width=12)
    self.production_sort_order_combo.grid(row=1, column=3, sticky="w", pady=(8, 0))
    self.production_sort_order_combo.bind("<<ComboboxSelected>>", self.on_production_sort_order_changed)

    ttk.Label(parent, text="Production Orders", style="Section.TLabel").grid(row=2, column=0, sticky="nw", pady=(0, 8))

    table_frame = ttk.Frame(parent)
    table_frame.grid(row=3, column=0, sticky="nsew")
    table_frame.columnconfigure(0, weight=1)
    table_frame.rowconfigure(0, weight=1)

    self.production_tree = ttk.Treeview(table_frame, columns=PRODUCTION_COLUMNS, show="tree headings", selectmode="browse", style="Costing.Treeview", height=12)
    self.production_tree.column("#0", width=96, minwidth=96, anchor="center", stretch=False)
    self.production_tree.heading("#0", text="Image")
    column_widths = {
        "select_flag": 60,
        "created_at": 125,
        "production_order": 150,
        "factory": 120,
        "mr_pic": 120,
        "buyer": 110,
        "style": 100,
        "parent": 100,
        "season": 95,
        "po_number": 115,
        "po_date": 95,
        "po_time": 80,
        "ship_date": 95,
        "cancel_date": 95,
        "ex_fty_date_plan": 120,
        "actual_ex_fty": 120,
        "color": 100,
        "size_range": 105,
        "size_scale": 105,
        "order_qty": 90,
        "ship_qty": 90,
        "status": 95,
        "over_short_ship_qty": 135,
        "over_short_ship_percent": 135,
        "final_inspection_date": 135,
        "carton_qty": 95,
        "odd_carton_qty": 120,
        "cbm": 80,
        "net_weight": 100,
        "gross_weight": 110,
        "updated_at": 125,
        "latest_user": 140,
    }
    for column_key in PRODUCTION_COLUMNS:
        anchor = "center" if column_key in {"select_flag", "po_date", "po_time", "ship_date", "cancel_date", "ex_fty_date_plan", "actual_ex_fty", "final_inspection_date", "status"} else "w"
        self.production_tree.column(column_key, width=column_widths[column_key], anchor=anchor, stretch=False)
        self.production_tree.heading(
            column_key,
            text=PRODUCTION_FIELD_LABELS.get(column_key, column_key),
            command=lambda key=column_key: self.on_production_heading_click(key),
        )
    configure_striped_treeview(self.production_tree)
    scroll_y = ttk.Scrollbar(table_frame, orient="vertical", command=self.production_tree.yview)
    scroll_x = ttk.Scrollbar(table_frame, orient="horizontal", command=self.production_tree.xview)
    self.production_tree.configure(yscrollcommand=scroll_y.set, xscrollcommand=scroll_x.set)
    self.production_tree.grid(row=0, column=0, sticky="nsew")
    scroll_y.grid(row=0, column=1, sticky="ns")
    scroll_x.grid(row=1, column=0, sticky="ew")
    self.production_tree.bind("<Button-1>", self.on_production_tree_click)
    self.production_tree.bind("<Double-1>", self.on_production_double_click)

    self.production_status_label = ttk.Label(
        parent,
        textvariable=self.status_var,
        relief="sunken",
        anchor="w",
        justify="left",
        padding=8,
        wraplength=1180,
    )
    self.production_status_label.grid(row=4, column=0, sticky="ew", pady=(12, 0))
    self.configure_production_filter_options()
    self.update_production_filter_input_state()
    _append_production_debug_log("build-ui done")


def configure_production_filter_options(self) -> None:
    self.production_filter_label_to_key = {label: key for key, label in PRODUCTION_FILTER_FIELD_OPTIONS}
    self.production_filter_key_to_label = {key: label for key, label in PRODUCTION_FILTER_FIELD_OPTIONS}
    self.production_sort_label_to_key = {label: key for key, label in PRODUCTION_SORT_KEY_OPTIONS}
    self.production_sort_key_to_label = {key: label for key, label in PRODUCTION_SORT_KEY_OPTIONS}
    self.production_filter_field_combo.configure(values=[label for _key, label in PRODUCTION_FILTER_FIELD_OPTIONS])
    self.production_sort_key_combo.configure(values=[label for _key, label in PRODUCTION_SORT_KEY_OPTIONS])
    self.production_sort_order_combo.configure(values=["Ascending", "Descending"])
    self.production_filter_field_var.set(self.production_filter_key_to_label.get(self.production_filter_field_internal, "All"))
    self.production_sort_key_var.set(self.production_sort_key_to_label.get(self.production_sort_key_internal, "Create Time"))
    self.production_sort_order_var.set("Descending" if self.production_sort_order_internal == "desc" else "Ascending")


def update_production_filter_input_state(self, *, clear_irrelevant: bool = False) -> None:
    filter_field = getattr(self, "production_filter_field_internal", "__all__")
    is_date_field = filter_field in PRODUCTION_DATE_FILTER_FIELDS
    if clear_irrelevant:
        if is_date_field:
            self.production_search_var.set("")
            self.production_search_committed_value = ""
        else:
            self.production_date_from_var.set("")
            self.production_date_to_var.set("")
    self.production_search_entry.configure(state="disabled" if is_date_field else "normal")
    self.production_date_from_entry.configure(state="normal" if is_date_field else "disabled")
    self.production_date_to_entry.configure(state="normal" if is_date_field else "disabled")


def apply_production_filter(self) -> None:
    if getattr(self, "_production_filter_update_suspended", False):
        _append_production_debug_log("apply-filter skipped suspended")
        return
    query = str(getattr(self, "production_search_committed_value", self.production_search_var.get()) or "").strip().lower()
    from_text = self.production_date_from_var.get().strip()
    to_text = self.production_date_to_var.get().strip()
    filter_field = getattr(self, "production_filter_field_internal", "__all__")
    filtered = list(getattr(self, "production_rows", []) or [])
    before_count = len(filtered)
    if filter_field in PRODUCTION_DATE_FILTER_FIELDS:
        filtered = [row for row in filtered if self.is_within_date_range(row.get(filter_field), from_text, to_text)]
    elif filter_field == "__all__" and query:
        filtered = [
            row for row in filtered
            if query in " ".join(
                [self.display_value(row.get("image_path"))]
                + [self.display_value(row.get(key)) for key in PRODUCTION_COLUMNS if key != "select_flag"]
            ).lower()
        ]
    elif query:
        filtered = [row for row in filtered if query in self.display_value(row.get(filter_field)).strip().lower()]
    sort_key = self.production_sort_key_internal
    reverse = self.production_sort_order_internal == "desc"

    def sort_value(row: dict) -> object:
        value = row.get(sort_key, "")
        if sort_key in PRODUCTION_DATE_FILTER_FIELDS:
            return self.parse_sort_value(sort_key, str(value or ""))
        if sort_key in PRODUCTION_NUMERIC_SORT_FIELDS:
            return _safe_float_value(value)
        return str(value or "").lower()

    filtered.sort(key=sort_value, reverse=reverse)
    self.filtered_production_rows = filtered
    _append_production_debug_log(
        f"apply-filter rows={before_count} filtered={len(filtered)} field={filter_field} "
        f"query={query!r} from={from_text!r} to={to_text!r} sort={sort_key} reverse={reverse} "
        f"tree_exists={hasattr(self, 'production_tree')}"
    )
    if hasattr(self, "production_tree"):
        self.refresh_production_tree()
    self.update_production_module_status()


def refresh_production_tree(self) -> None:
    _append_production_debug_log(
        f"refresh-tree start rows={len(getattr(self, 'production_rows', []) or [])} "
        f"filtered={len(getattr(self, 'filtered_production_rows', []) or [])}"
    )
    selected_id = self.get_selected_production_record_id()
    self.production_tree.delete(*self.production_tree.get_children())
    self.production_thumbnail_photos = []
    thumbnail_limit = self.get_startup_thumbnail_render_limit("production") if hasattr(self, "get_startup_thumbnail_render_limit") else None
    if thumbnail_limit is None:
        thumbnail_limit = PRODUCTION_TREE_THUMBNAIL_LIMIT
    valid_ids = {str(row.get("record_id", "")).strip() for row in self.production_rows if str(row.get("record_id", "")).strip()}
    self.checked_production_ids.intersection_update(valid_ids)
    inserted_count = 0
    insert_error_count = 0
    visible_rows = list(self.filtered_production_rows[:PRODUCTION_TREE_RENDER_LIMIT])
    for index, row in enumerate(visible_rows, start=1):
        record_id = str(row.get("record_id", "")).strip()
        if not record_id:
            continue
        thumbnail_photo = None
        if thumbnail_limit is None or index <= thumbnail_limit:
            thumbnail_photo = self.create_production_thumbnail(row)
            if thumbnail_photo is not None:
                self.production_thumbnail_photos.append(thumbnail_photo)
        values = []
        for key in PRODUCTION_COLUMNS:
            if key == "select_flag":
                values.append("[x]" if record_id in self.checked_production_ids else "[ ]")
            else:
                values.append(self.display_value(row.get(key)))
        insert_kwargs = {
            "iid": record_id,
            "text": "",
            "values": tuple(values),
            "tags": ("odd_row" if index % 2 == 1 else "even_row",),
        }
        if thumbnail_photo is not None:
            insert_kwargs["image"] = thumbnail_photo
        try:
            self.production_tree.insert("", "end", **insert_kwargs)
            inserted_count += 1
        except Exception as exc:
            insert_error_count += 1
            if insert_error_count <= 5:
                _append_production_debug_log(f"refresh-tree insert failed record_id={record_id} error={exc}")
    if selected_id and self.production_tree.exists(selected_id):
        self.production_tree.selection_set(selected_id)
        self.production_tree.focus(selected_id)
        self.production_tree.see(selected_id)
    if hasattr(self, "note_startup_thumbnail_render_state"):
        self.note_startup_thumbnail_render_state(
            "production",
            total_rows=len(visible_rows),
            rendered_rows=min(len(visible_rows), thumbnail_limit) if thumbnail_limit is not None else len(visible_rows),
        )
    self.update_production_module_status()
    child_count = 0
    try:
        child_count = len(self.production_tree.get_children())
    except Exception:
        pass
    _append_production_debug_log(
        f"refresh-tree done inserted={inserted_count} errors={insert_error_count} tree_children={child_count} "
        f"render_limit={PRODUCTION_TREE_RENDER_LIMIT}"
    )


def create_production_thumbnail(self, row: dict, target_width: int = 84, target_height: int = 84) -> ImageTk.PhotoImage | None:
    image_path = str(row.get("image_path", "") or "").strip()
    if not image_path:
        style = normalize_style_identifier(row.get("style"))
        for source_row in list(getattr(self, "tech_pack_library", []) or []):
            if normalize_style_identifier(source_row.get("style_code")) == style:
                image_path = str(source_row.get("image_path") or source_row.get("preview_image_path") or "").strip()
                break
    if not image_path:
        return None
    try:
        return create_contained_photo(image_path, target_width=target_width, target_height=target_height)
    except Exception:
        return None


def update_production_module_status(self) -> None:
    total = len(getattr(self, "production_rows", []) or [])
    shown = len(getattr(self, "filtered_production_rows", []) or [])
    checked = len(getattr(self, "checked_production_ids", set()) or set())
    order_qty = sum(_safe_float_value(row.get("order_qty")) for row in getattr(self, "filtered_production_rows", []) or [])
    ship_qty = sum(_safe_float_value(row.get("ship_qty")) for row in getattr(self, "filtered_production_rows", []) or [])
    rendered = min(shown, PRODUCTION_TREE_RENDER_LIMIT)
    suffix = f" | Showing first {rendered}" if shown > rendered else ""
    self.set_status(
        f"Production: {shown}/{total} | Export checked: {checked} | Order Qty: {_format_number(order_qty)} | Ship Qty: {_format_number(ship_qty)}{suffix}"
    )
    _append_production_debug_log(f"status total={total} shown={shown} checked={checked}")


def get_selected_production_record_id(self) -> str:
    if not hasattr(self, "production_tree"):
        return ""
    selection = self.production_tree.selection()
    return str(selection[0]).strip() if selection else ""


def get_selected_production_row(self) -> dict | None:
    record_id = self.get_selected_production_record_id()
    if not record_id:
        return None
    for row in getattr(self, "production_rows", []) or []:
        if str(row.get("record_id", "")).strip() == record_id:
            return dict(row)
    return None


def on_production_heading_click(self, key: str) -> None:
    if key == "select_flag":
        visible_ids = [str(row.get("record_id", "")).strip() for row in self.filtered_production_rows if str(row.get("record_id", "")).strip()]
        checked_visible = [record_id for record_id in visible_ids if record_id in self.checked_production_ids]
        if checked_visible and len(checked_visible) == len(visible_ids):
            self.checked_production_ids.difference_update(visible_ids)
        else:
            self.checked_production_ids.update(visible_ids)
        self.update_production_tree_check_cell()
        if visible_ids:
            self.production_tree.selection_set(visible_ids[0])
            self.production_tree.focus(visible_ids[0])
        self.update_production_module_status()
        return
    if self.production_sort_key_internal == key:
        self.production_sort_order_internal = "asc" if self.production_sort_order_internal == "desc" else "desc"
    else:
        self.production_sort_key_internal = key
    self.production_sort_key_var.set(self.production_sort_key_to_label.get(self.production_sort_key_internal, key))
    self.production_sort_order_var.set("Descending" if self.production_sort_order_internal == "desc" else "Ascending")
    self.apply_production_filter()


def update_production_tree_check_cell(self, row_id: str | None = None) -> None:
    target_ids = [row_id] if row_id else list(self.production_tree.get_children())
    for record_id in target_ids:
        if self.production_tree.exists(record_id):
            self.production_tree.set(record_id, "select_flag", "[x]" if record_id in self.checked_production_ids else "[ ]")


def on_production_tree_click(self, event: tk.Event) -> None:
    region = self.production_tree.identify("region", event.x, event.y)
    if region != "cell":
        return
    column_id = self.production_tree.identify_column(event.x)
    try:
        column_index = int(column_id.replace("#", "")) - 1
    except Exception:
        return
    if column_index < 0 or column_index >= len(PRODUCTION_COLUMNS):
        return
    if PRODUCTION_COLUMNS[column_index] != "select_flag":
        return
    row_id = self.production_tree.identify_row(event.y)
    if not row_id:
        return
    if row_id in self.checked_production_ids:
        self.checked_production_ids.remove(row_id)
    else:
        self.checked_production_ids.add(row_id)
        self.production_tree.selection_set(row_id)
        self.production_tree.focus(row_id)
    self.update_production_tree_check_cell(row_id)
    self.update_production_module_status()
    return "break"


def on_production_double_click(self, _event: object | None = None) -> None:
    self.edit_selected_production_order()


def on_production_filter_field_changed(self, _event: object | None = None) -> None:
    label = self.production_filter_field_var.get()
    self.production_filter_field_internal = self.production_filter_label_to_key.get(label, "__all__")
    self._production_filter_update_suspended = True
    try:
        self.update_production_filter_input_state(clear_irrelevant=True)
    finally:
        self._production_filter_update_suspended = False
    self.apply_production_filter()


def on_production_sort_key_changed(self, _event: object | None = None) -> None:
    self.production_sort_key_internal = self.production_sort_label_to_key.get(self.production_sort_key_var.get(), "created_at")
    self.apply_production_filter()


def on_production_sort_order_changed(self, _event: object | None = None) -> None:
    self.production_sort_order_internal = "desc" if self.production_sort_order_var.get().lower().startswith("desc") else "asc"
    self.apply_production_filter()


def on_production_search_submit(self, _event: object | None = None) -> str:
    self.production_search_committed_value = self.production_search_var.get().strip()
    self.apply_production_filter()
    return "break"


def edit_selected_production_order(self) -> None:
    row = self.get_selected_production_row()
    if not isinstance(row, dict):
        messagebox.showwarning(self.t("warning_title"), "Please select one Production Order first.")
        return
    self.open_production_order_detail_window(row)


def delete_selected_production_order(self) -> None:
    target_ids = set(self.checked_production_ids)
    selected_id = self.get_selected_production_record_id()
    if not target_ids and selected_id:
        target_ids.add(selected_id)
    if not target_ids:
        messagebox.showwarning(self.t("warning_title"), "Please select at least one Production Order first.")
        return
    if not messagebox.askyesno(self.t("warning_title"), f"Delete {len(target_ids)} selected Production Order row(s)?"):
        return
    remaining = [row for row in self.production_rows if str(row.get("record_id", "")).strip() not in target_ids]
    self.delete_production_detail_rows_from_source(target_ids)
    self.production_rows = remaining
    self.checked_production_ids.difference_update(target_ids)
    self.apply_production_filter()


def _selected_production_rows_for_packing(self) -> list[dict]:
    checked_ids = set(getattr(self, "checked_production_ids", set()) or set())
    visible_rows = list(getattr(self, "filtered_production_rows", []) or [])
    if checked_ids:
        rows = [dict(row) for row in visible_rows if str(row.get("record_id", "")).strip() in checked_ids]
        existing_ids = {str(row.get("record_id", "")).strip() for row in rows}
        rows.extend(
            dict(row)
            for row in list(getattr(self, "production_rows", []) or [])
            if str(row.get("record_id", "")).strip() in checked_ids and str(row.get("record_id", "")).strip() not in existing_ids
        )
        return rows
    selected_row = self.get_selected_production_row()
    return [dict(selected_row)] if isinstance(selected_row, dict) else []


def load_production_packing_list_assets_from_source(self) -> dict[str, object]:
    default_value = default_production_packing_list_assets()
    if self.should_use_server_data_source():
        if self.is_local_data_mode():
            self.ensure_local_server_running()
        try:
            payload = fetch_app_setting(self.server_settings, PRODUCTION_PACKING_LIST_ASSETS_KEY, default_value)
            merged = dict(default_value)
            if isinstance(payload, dict):
                merged.update(payload)
            return merged
        except Exception:
            pass
    payload = get_app_setting(DB_PATH, PRODUCTION_PACKING_LIST_ASSETS_KEY, default_value)
    merged = dict(default_value)
    if isinstance(payload, dict):
        merged.update(payload)
    return merged


def save_production_packing_list_assets_to_source(self, payload: dict[str, object]) -> dict[str, object]:
    normalized = dict(default_production_packing_list_assets())
    normalized.update(payload if isinstance(payload, dict) else {})
    if self.should_use_server_data_source():
        if self.is_local_data_mode():
            self.ensure_local_server_running()
        saved = save_app_setting(self.server_settings, PRODUCTION_PACKING_LIST_ASSETS_KEY, normalized)
        return dict(saved) if isinstance(saved, dict) else normalized
    saved = set_app_setting(DB_PATH, PRODUCTION_PACKING_LIST_ASSETS_KEY, normalized)
    return dict(saved) if isinstance(saved, dict) else normalized


def load_production_carton_sticker_assets_from_source(self) -> dict[str, object]:
    default_value = default_production_carton_sticker_assets()
    if self.should_use_server_data_source():
        if self.is_local_data_mode():
            self.ensure_local_server_running()
        try:
            payload = fetch_app_setting(self.server_settings, PRODUCTION_CARTON_STICKER_ASSETS_KEY, default_value)
            merged = dict(default_value)
            if isinstance(payload, dict):
                merged.update(payload)
            return merged
        except Exception:
            pass
    payload = get_app_setting(DB_PATH, PRODUCTION_CARTON_STICKER_ASSETS_KEY, default_value)
    merged = dict(default_value)
    if isinstance(payload, dict):
        merged.update(payload)
    return merged


def save_production_carton_sticker_assets_to_source(self, payload: dict[str, object]) -> dict[str, object]:
    normalized = dict(default_production_carton_sticker_assets())
    normalized.update(payload if isinstance(payload, dict) else {})
    if self.should_use_server_data_source():
        if self.is_local_data_mode():
            self.ensure_local_server_running()
        saved = save_app_setting(self.server_settings, PRODUCTION_CARTON_STICKER_ASSETS_KEY, normalized)
        return dict(saved) if isinstance(saved, dict) else normalized
    saved = set_app_setting(DB_PATH, PRODUCTION_CARTON_STICKER_ASSETS_KEY, normalized)
    return dict(saved) if isinstance(saved, dict) else normalized


def resolve_production_packing_list_template_asset(self, value: str, *, fallback_suffix: str = ".xlsx") -> Path | None:
    raw_value = str(value or "").strip()
    if not raw_value:
        return None
    candidate = Path(raw_value)
    if candidate.exists() and candidate.is_file():
        return candidate
    if raw_value.lower().startswith(("http://", "https://")):
        try:
            split = urlsplit(raw_value)
            normalized_url = urlunsplit(
                (
                    split.scheme,
                    split.netloc,
                    quote(split.path, safe="/:@"),
                    quote(split.query, safe="=&?/:@"),
                    quote(split.fragment, safe="=&?/:@"),
                )
            )
            parsed = urlparse(normalized_url)
            suffix = Path(parsed.path).suffix or fallback_suffix
            cache_dir = DATA_DIR / ("carton_sticker_assets" if fallback_suffix == ".carton-sticker.xlsx" else "packing_list_assets")
            cache_dir.mkdir(parents=True, exist_ok=True)
            target_path = cache_dir / f"{hashlib.sha1(raw_value.encode('utf-8')).hexdigest()}{suffix}"
            if target_path.exists() and target_path.is_file():
                return target_path
            request = Request(normalized_url, headers={"User-Agent": "CitiFoxERPApp/desktop"})
            with open_url(request, timeout=20) as response:
                target_path.write_bytes(response.read())
            return target_path if target_path.exists() else None
        except Exception:
            return None
    return None


def ensure_production_packing_list_template_asset(self) -> Path:
    assets = self.load_production_packing_list_assets_from_source()
    template_url = str(assets.get("template_url", "") or "").strip()
    template_path = self.resolve_production_packing_list_template_asset(template_url)
    if template_path is not None:
        return template_path
    for candidate in (PRODUCTION_PACKING_LIST_TEMPLATE_PATH, PRODUCTION_PACKING_LIST_TEMPLATE_FALLBACK_PATH):
        candidate_path = Path(str(candidate or "").strip())
        if candidate_path.exists() and candidate_path.is_file():
            return candidate_path
    raise FileNotFoundError(f"Packing List template was not found. Expected: {PRODUCTION_PACKING_LIST_TEMPLATE_PATH}")


def _safe_production_sheet_title(raw_title: object, used_titles: set[str]) -> str:
    title = str(raw_title or "").strip() or "Packing List"
    for char in r'[]:*?/\\':
        title = title.replace(char, "-")
    title = " ".join(title.split())[:31].strip() or "Packing List"
    base = title
    counter = 2
    while title in used_titles:
        suffix = f" {counter}"
        title = f"{base[:31 - len(suffix)]}{suffix}".strip()
        counter += 1
    used_titles.add(title)
    return title


def _production_excel_carton_dimension(value: object) -> str:
    text = str(value or "").strip()
    if not text:
        return ""
    lower_text = text.lower().replace("(cm)", "").replace("cm", "")
    parts = [part.strip() for part in lower_text.replace("*", "x").split("x") if part.strip()]
    if len(parts) >= 3:
        return "*".join(parts[:3])
    return text


def _production_carton_cbm_formula(row_index: int, carton_column: str, dimension: object) -> str:
    dimension_text = _production_excel_carton_dimension(dimension)
    parts: list[float] = []
    for raw_part in dimension_text.split("*"):
        value = _safe_float_value(raw_part)
        if value > 0:
            parts.append(value / 100)
    if len(parts) != 3:
        return ""
    return f"={carton_column}{row_index}*{parts[0]}*{parts[1]}*{parts[2]}"


def _production_carton_cbm_value(cartons: float, dimension: object) -> float:
    dimension_text = _production_excel_carton_dimension(dimension)
    parts: list[float] = []
    for raw_part in dimension_text.split("*"):
        value = _safe_float_value(raw_part)
        if value > 0:
            parts.append(value / 100)
    if len(parts) != 3 or cartons <= 0:
        return 0.0
    return cartons * parts[0] * parts[1] * parts[2]


def _copy_production_cell_style(source_cell, target_cell) -> None:
    if source_cell.has_style:
        target_cell.font = copy(source_cell.font)
        target_cell.fill = copy(source_cell.fill)
        target_cell.border = copy(source_cell.border)
        target_cell.alignment = copy(source_cell.alignment)
        target_cell.number_format = source_cell.number_format
        target_cell.protection = copy(source_cell.protection)


def _production_packing_size_label(self, value: object) -> str:
    if hasattr(self, "normalize_size_code"):
        size_code = self.normalize_size_code(value)
    else:
        size_code = str(value or "").strip().upper().replace(" ", "")
    petite_map = {
        "PETXS": "PXS",
        "PETSM": "PS",
        "PETS": "PS",
        "PETMD": "PM",
        "PETM": "PM",
        "PETLG": "PL",
        "PETL": "PL",
        "PETXL": "PXL",
    }
    return petite_map.get(size_code, size_code)


PRODUCTION_SIZE_SYSTEM_ORDER = {
    "petite": ["PXS", "PS", "PM", "PL", "PXL"],
    "missy": ["XS", "S", "M", "L", "XL"],
    "women": ["1X", "2X", "3X"],
}


def _production_size_system_for_labels(size_labels: list[str]) -> str:
    normalized = {str(size or "").strip().upper() for size in size_labels if str(size or "").strip()}
    for system_key, ordered_sizes in PRODUCTION_SIZE_SYSTEM_ORDER.items():
        if normalized and normalized.issubset(set(ordered_sizes)):
            return system_key
    if any(size.startswith("P") for size in normalized):
        return "petite"
    if any(size.endswith("X") and size[:1].isdigit() for size in normalized):
        return "women"
    return "missy"


def _production_order_sizes_for_system(size_labels: list[str]) -> list[str]:
    system_key = _production_size_system_for_labels(size_labels)
    ordered_sizes = PRODUCTION_SIZE_SYSTEM_ORDER.get(system_key, PRODUCTION_SIZE_SYSTEM_ORDER["missy"])
    existing = {str(size or "").strip().upper() for size in size_labels if str(size or "").strip()}
    extras = sorted(size for size in existing if size not in set(ordered_sizes))
    ordered = [size for size in ordered_sizes if size in existing]
    return ordered + extras


def _production_ordered_size_labels(self, items: list[dict]) -> list[str]:
    raw_sizes = [str(item.get("size_desc", "") or "").strip() for item in items if str(item.get("size_desc", "") or "").strip()]
    if not raw_sizes:
        return []
    if hasattr(self, "sort_size_codes"):
        raw_sizes = list(self.sort_size_codes(raw_sizes))
    ordered: list[str] = []
    seen: set[str] = set()
    for raw_size in raw_sizes:
        size_code = _production_packing_size_label(self, raw_size)
        if size_code and size_code not in seen:
            seen.add(size_code)
            ordered.append(size_code)
    return _production_order_sizes_for_system(ordered)


def _production_size_breakdown(self, row: dict) -> tuple[list[str], dict[str, float], dict[str, float]]:
    items = self.get_production_po_detail_line_items(row)
    return _production_size_breakdown_from_items(self, items)


def _production_size_breakdown_from_items(self, items: list[dict]) -> tuple[list[str], dict[str, float], dict[str, float]]:
    size_labels = _production_ordered_size_labels(self, items)
    pack_qty_by_size = {size: 0.0 for size in size_labels}
    order_qty_by_size = {size: 0.0 for size in size_labels}
    for item in items:
        size = _production_packing_size_label(self, item.get("size_desc"))
        if not size:
            continue
        if size not in pack_qty_by_size:
            size_labels.append(size)
            pack_qty_by_size[size] = 0.0
            order_qty_by_size[size] = 0.0
        pack_qty_by_size[size] += _safe_float_value(item.get("pack_qty"))
        order_qty_by_size[size] += _safe_float_value(item.get("total_units"))
    ordered_labels = _production_order_sizes_for_system(size_labels)
    return ordered_labels, pack_qty_by_size, order_qty_by_size


def _allocate_production_quantity_by_size(total_qty: float, basis_by_size: dict[str, float], size_labels: list[str]) -> dict[str, float]:
    total_qty_int = int(round(total_qty))
    basis_total = sum(max(0.0, basis_by_size.get(size, 0.0)) for size in size_labels)
    if total_qty_int <= 0 or basis_total <= 0:
        return {size: 0.0 for size in size_labels}
    allocations: dict[str, float] = {}
    fractions: list[tuple[float, str]] = []
    assigned = 0
    for size in size_labels:
        exact = total_qty_int * max(0.0, basis_by_size.get(size, 0.0)) / basis_total
        whole = int(exact)
        allocations[size] = float(whole)
        assigned += whole
        fractions.append((exact - whole, size))
    for _fraction, size in sorted(fractions, reverse=True)[: max(0, total_qty_int - assigned)]:
        allocations[size] += 1.0
    return allocations


def _prepare_production_packing_sheet_columns(sheet, size_count: int) -> tuple[int, int, int, int, int, int]:
    display_size_count = max(3, size_count)
    if display_size_count > 3:
        extra_columns = display_size_count - 3
        sheet.insert_cols(13, extra_columns)
        for column_index in range(13, 13 + extra_columns):
            source_column = column_index - 1
            sheet.column_dimensions[get_column_letter(column_index)].width = sheet.column_dimensions[get_column_letter(source_column)].width
            for row_index in range(1, 40):
                _copy_production_cell_style(sheet.cell(row=row_index, column=source_column), sheet.cell(row=row_index, column=column_index))
    unit_col = 10 + display_size_count
    qty_per_ctn_col = unit_col + 1
    total_qty_col = unit_col + 2
    box_col = unit_col + 3
    cbm_col = unit_col + 4
    remark_col = unit_col + 5
    return unit_col, qty_per_ctn_col, total_qty_col, box_col, cbm_col, remark_col


def _fill_production_packing_sheet(self, sheet, row: dict) -> None:
    working_row = dict(row)
    _recalculate_production_packing(working_row)
    color_items = working_row.get("_packing_color_items")
    if isinstance(color_items, list):
        size_labels, pack_qty_by_size, order_qty_by_size = _production_size_breakdown_from_items(self, [dict(item) for item in color_items if isinstance(item, dict)])
    else:
        size_labels, pack_qty_by_size, order_qty_by_size = _production_size_breakdown(self, working_row)
    if not size_labels:
        size_labels = [str(working_row.get("size_range", "") or "").strip() or "SIZE"]
        pack_qty_by_size = {size_labels[0]: _safe_float_value(self.production_unit_per_pack(working_row))}
        order_qty_by_size = {size_labels[0]: _safe_float_value(working_row.get("order_qty"))}

    unit_col, qty_per_ctn_col, total_qty_col, box_col, cbm_col, remark_col = _prepare_production_packing_sheet_columns(sheet, len(size_labels))
    total_qty_letter = get_column_letter(total_qty_col)
    cbm_letter = get_column_letter(cbm_col)

    sheet["R2"] = datetime.now()
    sheet["R2"].number_format = "m/d/yyyy"
    for index, size in enumerate(size_labels, start=10):
        sheet.cell(row=4, column=index).value = size
        sheet.cell(row=13, column=index).value = size
    for index in range(10 + len(size_labels), 10 + max(3, len(size_labels))):
        sheet.cell(row=4, column=index).value = ""
        sheet.cell(row=13, column=index).value = ""

    style = str(working_row.get("style", "") or "").strip()
    po_number = str(working_row.get("po_number", "") or "").strip()
    store = str(working_row.get("store_number", "") or "").strip()
    dept = str(working_row.get("dept_number", "") or "").strip()
    color = str(working_row.get("_packing_color_label") or working_row.get("color", "") or "").strip()
    unit_per_pack = sum(pack_qty_by_size.get(size, 0.0) for size in size_labels)
    unit_per_carton = _safe_float_value(working_row.get("unit_per_carton"))
    ship_qty = _safe_float_value(working_row.get("ship_qty"))
    order_qty = _safe_float_value(working_row.get("order_qty")) or sum(order_qty_by_size.get(size, 0.0) for size in size_labels)
    carton_qty = int(_safe_float_value(working_row.get("carton_qty")))
    odd_qty = _safe_float_value(working_row.get("odd_carton_qty"))

    packing_total_cartons = 0.0
    packing_total_qty = 0.0
    packing_total_cbm = 0.0

    def fill_carton_row(row_index: int, carton_from: int | str, cartons: float, total_units: float, box_dimension: str, ppk_qty: float) -> None:
        nonlocal packing_total_cartons, packing_total_qty, packing_total_cbm
        sheet.cell(row=row_index, column=1).value = carton_from
        sheet.cell(row=row_index, column=2).value = f"=A{row_index}+C{row_index}-1" if carton_from and cartons else ""
        sheet.cell(row=row_index, column=3).value = _excel_number(cartons) if cartons else ""
        sheet.cell(row=row_index, column=4).value = _excel_number(ppk_qty) if ppk_qty else ""
        sheet.cell(row=row_index, column=5).value = style
        sheet.cell(row=row_index, column=6).value = po_number
        sheet.cell(row=row_index, column=7).value = store
        sheet.cell(row=row_index, column=8).value = dept
        sheet.cell(row=row_index, column=9).value = color
        for offset, size in enumerate(size_labels):
            sheet.cell(row=row_index, column=10 + offset).value = _excel_number(pack_qty_by_size.get(size, 0.0))
        sheet.cell(row=row_index, column=unit_col).value = _excel_number(unit_per_pack)
        sheet.cell(row=row_index, column=qty_per_ctn_col).value = _excel_number(total_units / cartons) if cartons else ""
        sheet.cell(row=row_index, column=total_qty_col).value = _excel_number(total_units)
        sheet.cell(row=row_index, column=box_col).value = box_dimension
        cbm_value = _production_carton_cbm_value(cartons, box_dimension)
        sheet.cell(row=row_index, column=cbm_col).value = _excel_number(cbm_value) if cbm_value else ""
        packing_total_cartons += cartons
        packing_total_qty += total_units
        packing_total_cbm += cbm_value

    for row_index in (5, 6, 7):
        for column_index in range(1, remark_col + 1):
            sheet.cell(row=row_index, column=column_index).value = None

    next_carton = 1
    wrote_main_row = False
    if carton_qty > 0 and unit_per_carton > 0:
        fill_carton_row(
            5,
            next_carton,
            carton_qty,
            carton_qty * unit_per_carton,
            _production_excel_carton_dimension(working_row.get("carton_dimension")),
            unit_per_carton / unit_per_pack if unit_per_pack else 0,
        )
        wrote_main_row = True
        next_carton += carton_qty
    if not wrote_main_row:
        fill_carton_row(
            5,
            "",
            0,
            ship_qty or order_qty,
            _production_excel_carton_dimension(working_row.get("carton_dimension")),
            0,
        )
    if odd_qty > 0:
        fill_carton_row(
            6,
            next_carton,
            1,
            odd_qty,
            _production_excel_carton_dimension(working_row.get("odd_carton_dimension")),
            odd_qty / unit_per_pack if unit_per_pack else 0,
        )

    sheet.cell(row=8, column=3).value = _excel_number(packing_total_cartons) if packing_total_cartons else 0
    sheet.cell(row=8, column=total_qty_col).value = _excel_number(packing_total_qty) if packing_total_qty else 0
    sheet.cell(row=8, column=cbm_col).value = _excel_number(packing_total_cbm) if packing_total_cbm else 0

    shipped_by_size = _allocate_production_quantity_by_size(ship_qty, order_qty_by_size, size_labels)
    total_ship_qty = sum(shipped_by_size.get(size, 0.0) for size in size_labels)
    total_order_qty = sum(order_qty_by_size.get(size, 0.0) for size in size_labels)
    total_over_short_qty = total_ship_qty - total_order_qty
    total_over_short_percent = total_over_short_qty / total_order_qty if total_order_qty else 0
    for offset, size in enumerate(size_labels):
        column_index = 10 + offset
        shipped_size_qty = shipped_by_size.get(size, 0.0)
        order_size_qty = order_qty_by_size.get(size, 0.0)
        over_short_size_qty = shipped_size_qty - order_size_qty
        sheet.cell(row=14, column=column_index).value = _excel_number(shipped_size_qty)
        sheet.cell(row=15, column=column_index).value = _excel_number(order_size_qty)
        sheet.cell(row=16, column=column_index).value = _excel_number(over_short_size_qty)
        sheet.cell(row=17, column=column_index).value = over_short_size_qty / order_size_qty if order_size_qty else 0
        sheet.cell(row=17, column=column_index).number_format = "0.00%"
    summary_values = {
        14: total_ship_qty,
        15: total_order_qty,
        16: total_over_short_qty,
        17: total_over_short_percent,
        18: total_ship_qty,
        19: total_order_qty,
        20: total_over_short_qty,
        21: total_over_short_percent,
    }
    for row_index, value in summary_values.items():
        sheet.cell(row=row_index, column=unit_col).value = value if row_index in (17, 21) else _excel_number(value)
        if row_index in (17, 21):
            sheet.cell(row=row_index, column=unit_col).number_format = "0.00%"
    sheet.cell(row=23, column=10).value = _excel_number(packing_total_cartons) if packing_total_cartons else 0
    sheet.cell(row=24, column=10).value = _excel_number(packing_total_qty) if packing_total_qty else 0
    if str(working_row.get("net_weight", "") or "").strip():
        sheet.cell(row=24, column=unit_col).value = working_row.get("net_weight")
    if str(working_row.get("gross_weight", "") or "").strip():
        sheet.cell(row=24, column=unit_col + 1).value = working_row.get("gross_weight")


def export_selected_production_packing_list(self) -> None:
    rows = _selected_production_rows_for_packing(self)
    if not rows:
        messagebox.showwarning(self.t("warning_title"), "Please select at least one Production Order row first.")
        return
    try:
        template_path = self.ensure_production_packing_list_template_asset()
    except Exception as exc:
        messagebox.showwarning(
            self.t("warning_title"),
            f"Packing List template was not found.\n\n{exc}",
        )
        return
    target_path = filedialog.asksaveasfilename(
        title="Export Packing List",
        defaultextension=".xlsx",
        filetypes=[("Excel Workbook", "*.xlsx")],
        initialfile=f"packing_list_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx",
    )
    if not target_path:
        return
    try:
        workbook = load_workbook(template_path)
        template_sheet = workbook.worksheets[0]
        used_titles: set[str] = set()
        created_sheets = []
        for production_row in rows:
            color_summaries = _production_color_summaries(self, production_row)
            if not color_summaries:
                color_summaries = [
                    {
                        "color_label": str(production_row.get("color", "") or "No Color"),
                        "items": self.get_production_po_detail_line_items(production_row),
                        "ship_qty": str(production_row.get("ship_qty", "") or ""),
                    }
                ]
            for color_summary in color_summaries:
                color_label = str(color_summary.get("color_label", "") or "No Color")
                color_row = dict(production_row)
                color_row["color"] = color_label
                color_row["ship_qty"] = str(color_summary.get("ship_qty", "") or production_row.get("ship_qty", "") or "")
                color_row["_packing_color_label"] = color_label
                color_row["_packing_color_items"] = list(color_summary.get("items", []) or [])
                _recalculate_production_packing(color_row)
                sheet = workbook.copy_worksheet(template_sheet)
                sheet.title = _safe_production_sheet_title(
                    f"{production_row.get('style', '')} {production_row.get('po_number', '')} {color_label}",
                    used_titles,
                )
                _fill_production_packing_sheet(self, sheet, color_row)
                created_sheets.append(sheet)
        workbook.remove(template_sheet)
        workbook.active = 0
        try:
            workbook.calculation.calcMode = "auto"
            workbook.calculation.fullCalcOnLoad = True
            workbook.calculation.forceFullCalc = True
        except Exception:
            pass
        workbook.save(target_path)
    except Exception as exc:
        messagebox.showerror(self.t("error_title"), f"Could not export Packing List:\n{exc}")
        return
    self.set_status(f"Exported Packing List: {target_path}")
    messagebox.showinfo("Packing List", f"Exported {len(created_sheets)} sheet(s).")


def ensure_production_carton_sticker_template_asset(self) -> Path:
    assets = self.load_production_carton_sticker_assets_from_source()
    template_url = str(assets.get("template_url", "") or "").strip()
    template_path = self.resolve_production_packing_list_template_asset(template_url, fallback_suffix=".carton-sticker.xlsx")
    if template_path is not None:
        return template_path
    for candidate in (PRODUCTION_CARTON_STICKER_TEMPLATE_PATH, PRODUCTION_CARTON_STICKER_TEMPLATE_FALLBACK_PATH):
        candidate_path = Path(str(candidate or "").strip())
        if candidate_path.exists() and candidate_path.is_file():
            return candidate_path
    raise FileNotFoundError(f"Carton sticker template was not found. Expected: {PRODUCTION_CARTON_STICKER_TEMPLATE_PATH}")


def _normalize_production_store_code(value: object) -> str:
    digits = "".join(ch for ch in str(value or "").strip() if ch.isdigit())
    return digits.lstrip("0") or digits


def _production_store_template_sheet(workbook, store_value: object):
    target_store = _normalize_production_store_code(store_value)
    if not target_store:
        return None
    for sheet in workbook.worksheets:
        title = str(sheet.title or "").strip()
        if not title.upper().startswith("STORE"):
            continue
        if _normalize_production_store_code(title) == target_store:
            return sheet
    return None


def _production_carton_sticker_sheet_title(row: dict, color_label: str, used_titles: set[str]) -> str:
    return _safe_production_sheet_title(
        f"Store {row.get('store_number', '')} {row.get('po_number', '')} {row.get('style', '')} {color_label}",
        used_titles,
    )


def _production_carton_sticker_pack_text(unit_per_carton: float, unit_per_pack: float) -> str:
    carton_units = _format_number(unit_per_carton) if unit_per_carton else ""
    pack_units = _format_number(unit_per_pack) if unit_per_pack else ""
    pack_count = _format_number(unit_per_carton / unit_per_pack) if unit_per_carton and unit_per_pack else ""
    if carton_units and pack_units and pack_count:
        return f"Master carton: {carton_units}pcs\nInner packs: {pack_units}pcs/{pack_count}ppk"
    if carton_units:
        return f"Master carton: {carton_units}pcs"
    return "Master carton:"


def _fill_production_carton_sticker_sheet(self, sheet, row: dict, color_summary: dict[str, object]) -> None:
    color_label = str(color_summary.get("color_label", "") or row.get("color", "") or "").strip()
    items = [dict(item) for item in list(color_summary.get("items", []) or []) if isinstance(item, dict)]
    size_labels, pack_qty_by_size, order_qty_by_size = _production_size_breakdown_from_items(self, items)
    if not size_labels:
        size_labels = [
            item.strip()
            for item in str(row.get("size_range", "") or "").replace("/", "-").split("-")
            if item.strip()
        ]
    if not size_labels:
        size_labels = ["SIZE"]
        pack_qty_by_size = {"SIZE": _safe_float_value(self.production_unit_per_pack(row))}
        order_qty_by_size = {"SIZE": _safe_float_value(row.get("order_qty"))}

    working_row = dict(row)
    working_row["color"] = color_label
    working_row["ship_qty"] = str(color_summary.get("ship_qty", "") or row.get("ship_qty", "") or "")
    _recalculate_production_packing(working_row)

    po_number = str(working_row.get("po_number", "") or "").strip()
    sheet["A3"] = f"PO#: {po_number}\nCOLOR: {color_label}\nSize:"
    sheet["A9"] = "=A3"

    visible_sizes = size_labels[:4]
    for offset in range(4):
        column_index = 1 + offset
        size = visible_sizes[offset] if offset < len(visible_sizes) else ""
        sheet.cell(row=4, column=column_index).value = size
        sheet.cell(row=5, column=column_index).value = _excel_number(pack_qty_by_size.get(size, 0.0)) if size else ""
        sheet.cell(row=10, column=column_index).value = size
    unit_per_pack = sum(_safe_float_value(pack_qty_by_size.get(size, 0.0)) for size in size_labels)
    if unit_per_pack <= 0:
        unit_per_pack = _safe_float_value(self.production_unit_per_pack(working_row))
    unit_per_carton = _safe_float_value(working_row.get("unit_per_carton"))
    carton_qty = _safe_float_value(working_row.get("carton_qty"))
    odd_qty = _safe_float_value(working_row.get("odd_carton_qty"))
    sheet["E5"] = _excel_number(carton_qty) if carton_qty else ""
    sheet["A6"] = _production_carton_sticker_pack_text(unit_per_carton, unit_per_pack)

    if odd_qty > 0:
        for offset, size in enumerate(visible_sizes):
            sheet.cell(row=11, column=1 + offset).value = _excel_number(pack_qty_by_size.get(size, 0.0))
        sheet["E11"] = 1
        sheet["A12"] = _production_carton_sticker_pack_text(odd_qty, unit_per_pack)
    else:
        for offset in range(4):
            sheet.cell(row=11, column=1 + offset).value = ""
        sheet["E11"] = ""
        sheet["A12"] = ""


def export_selected_production_carton_stickers(self) -> None:
    rows = _selected_production_rows_for_packing(self)
    if not rows:
        messagebox.showwarning(self.t("warning_title"), "Please select at least one Production Order row first.")
        return
    try:
        template_path = self.ensure_production_carton_sticker_template_asset()
    except Exception as exc:
        messagebox.showwarning(
            self.t("warning_title"),
            f"Carton sticker template was not found.\n\n{exc}",
        )
        return
    target_path = filedialog.asksaveasfilename(
        title="Export Carton Sticker",
        defaultextension=".xlsx",
        filetypes=[("Excel Workbook", "*.xlsx")],
        initialfile=f"carton_sticker_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx",
    )
    if not target_path:
        return
    try:
        workbook = load_workbook(template_path)
        used_titles: set[str] = set()
        created_sheets = []
        missing_stores: set[str] = set()
        original_sheets = list(workbook.worksheets)
        for production_row in rows:
            template_sheet = _production_store_template_sheet(workbook, production_row.get("store_number"))
            if template_sheet is None:
                missing_stores.add(str(production_row.get("store_number", "") or "-").strip() or "-")
                continue
            color_summaries = _production_color_summaries(self, production_row)
            if not color_summaries:
                color_summaries = [
                    {
                        "color_label": str(production_row.get("color", "") or "No Color"),
                        "items": self.get_production_po_detail_line_items(production_row),
                        "ship_qty": str(production_row.get("ship_qty", "") or ""),
                    }
                ]
            for color_summary in color_summaries:
                color_label = str(color_summary.get("color_label", "") or "No Color")
                sheet = workbook.copy_worksheet(template_sheet)
                sheet.title = _production_carton_sticker_sheet_title(production_row, color_label, used_titles)
                _fill_production_carton_sticker_sheet(self, sheet, production_row, color_summary)
                created_sheets.append(sheet)
        if not created_sheets:
            missing_text = ", ".join(sorted(missing_stores)) if missing_stores else "-"
            raise ValueError(f"No carton sticker sheet was created. Missing store template(s): {missing_text}")
        for sheet in original_sheets:
            if sheet in workbook.worksheets and len(workbook.worksheets) > len(created_sheets):
                workbook.remove(sheet)
        workbook.active = 0
        try:
            workbook.calculation.calcMode = "auto"
            workbook.calculation.fullCalcOnLoad = True
            workbook.calculation.forceFullCalc = True
        except Exception:
            pass
        workbook.save(target_path)
    except Exception as exc:
        messagebox.showerror(self.t("error_title"), f"Could not export Carton Sticker:\n{exc}")
        return
    self.set_status(f"Exported Carton Sticker: {target_path}")
    message = f"Exported {len(created_sheets)} carton sticker sheet(s)."
    if missing_stores:
        message += "\n\nMissing store template(s): " + ", ".join(sorted(missing_stores))
    messagebox.showinfo("Carton Sticker", message)


def get_selected_production_factory_id(self) -> str:
    tree = getattr(self, "production_factory_tree", None)
    if tree is None:
        return ""
    selection = tree.selection()
    return str(selection[0]).strip() if selection else ""


def get_selected_production_factory_row(self) -> dict | None:
    factory_id = self.get_selected_production_factory_id()
    if not factory_id:
        return None
    for row in getattr(self, "production_factory_rows", []) or []:
        if str(row.get("factory_id", "")).strip() == factory_id:
            return dict(row)
    return None


def refresh_production_factory_tree(self) -> None:
    tree = getattr(self, "production_factory_tree", None)
    if tree is None:
        return
    selected_id = self.get_selected_production_factory_id()
    tree.delete(*tree.get_children())
    for index, row in enumerate(getattr(self, "filtered_production_factory_rows", []) or [], start=1):
        factory_id = str(row.get("factory_id", "")).strip()
        if not factory_id:
            continue
        values = tuple(self.display_value(row.get(key)) for key in PRODUCTION_FACTORY_COLUMNS)
        tree.insert("", "end", iid=factory_id, values=values, tags=("odd_row" if index % 2 == 1 else "even_row",))
    if selected_id and tree.exists(selected_id):
        tree.selection_set(selected_id)
        tree.focus(selected_id)
    self.on_production_factory_row_selected()
    status_var = getattr(self, "production_factory_status_var", None)
    if isinstance(status_var, tk.StringVar):
        status_var.set(
            f"Factories: {len(getattr(self, 'filtered_production_factory_rows', []) or [])}/"
            f"{len(getattr(self, 'production_factory_rows', []) or [])}"
        )


def apply_production_factory_filter(self) -> None:
    query = str(getattr(self, "production_factory_search_committed_value", getattr(self, "production_factory_search_var", tk.StringVar(value="")).get()) or "").strip().lower()
    rows = list(getattr(self, "production_factory_rows", []) or [])
    if query:
        filtered: list[dict] = []
        for row in rows:
            haystack = " ".join(
                self.display_value(row.get(key))
                for key in (
                    "factory_code",
                    "factory_name",
                    "short_name",
                    "contact_person",
                    "phone",
                    "email",
                    "country",
                    "city",
                    "status",
                )
            ).lower()
            if query in haystack:
                filtered.append(row)
        rows = filtered
    rows.sort(key=lambda item: (str(item.get("factory_name", "")).lower(), str(item.get("factory_code", "")).lower()))
    self.filtered_production_factory_rows = rows
    self.refresh_production_factory_tree()


def refresh_production_factory_list_window(self) -> None:
    self.production_factory_rows = [row for row in self.load_production_factory_rows_from_source() if isinstance(row, dict)]
    self.apply_production_factory_filter()


def on_production_factory_search_submit(self, _event: object | None = None) -> str:
    self.production_factory_search_committed_value = self.production_factory_search_var.get().strip()
    self.apply_production_factory_filter()
    return "break"


def open_production_factory_detail_window(self, row: dict | None = None) -> None:
    is_new = row is None
    source_row = deepcopy(row) if isinstance(row, dict) else default_production_factory_payload()
    dialog = tk.Toplevel(self.root)
    dialog.title("New Factory" if is_new else "Edit Factory")
    dialog.resizable(True, True)
    dialog.geometry("920x600")
    dialog.minsize(820, 520)

    frame = ttk.Frame(dialog, padding=16)
    frame.pack(fill="both", expand=True)
    frame.columnconfigure(0, weight=1)
    frame.rowconfigure(1, weight=1)
    ttk.Label(frame, text=dialog.title(), style="Section.TLabel").grid(row=0, column=0, sticky="w")

    content = ttk.Frame(frame)
    content.grid(row=1, column=0, sticky="nsew", pady=(12, 0))
    content.columnconfigure(0, weight=1)
    content.columnconfigure(1, weight=1)
    content.rowconfigure(6, weight=1)
    vars_map = {key: tk.StringVar(value=str(source_row.get(key, "") or "").strip()) for key in default_production_factory_payload()}
    note_text: tk.Text | None = None

    def add_labeled_entry(row_index: int, column_index: int, label: str, key: str) -> None:
        host = ttk.Frame(content)
        host.grid(row=row_index, column=column_index, sticky="ew", padx=8, pady=(0, 12))
        host.columnconfigure(0, weight=1)
        ttk.Label(host, text=label).grid(row=0, column=0, sticky="w", pady=(0, 4))
        ttk.Entry(host, textvariable=vars_map[key]).grid(row=1, column=0, sticky="ew")

    def add_labeled_combo(row_index: int, column_index: int, label: str, key: str, values: list[str]) -> None:
        host = ttk.Frame(content)
        host.grid(row=row_index, column=column_index, sticky="ew", padx=8, pady=(0, 12))
        host.columnconfigure(0, weight=1)
        ttk.Label(host, text=label).grid(row=0, column=0, sticky="w", pady=(0, 4))
        ttk.Combobox(host, textvariable=vars_map[key], values=values, state="readonly").grid(row=1, column=0, sticky="ew")

    add_labeled_entry(0, 0, "Factory Code", "factory_code")
    add_labeled_entry(0, 1, "Factory Name", "factory_name")
    add_labeled_entry(1, 0, "Short Name", "short_name")
    add_labeled_combo(1, 1, "Status", "status", PRODUCTION_FACTORY_STATUS_OPTIONS)
    add_labeled_entry(2, 0, "Contact Person", "contact_person")
    add_labeled_entry(2, 1, "Phone", "phone")
    add_labeled_entry(3, 0, "Email", "email")
    add_labeled_entry(3, 1, "Capacity / Month", "capacity_month")
    add_labeled_entry(4, 0, "Country", "country")
    add_labeled_entry(4, 1, "City", "city")
    add_labeled_entry(5, 0, "Address", "address_line")

    note_host = ttk.Frame(content)
    note_host.grid(row=6, column=0, columnspan=2, sticky="nsew", padx=8, pady=(0, 12))
    note_host.columnconfigure(0, weight=1)
    note_host.rowconfigure(1, weight=1)
    ttk.Label(note_host, text="Note").grid(row=0, column=0, sticky="w", pady=(0, 4))
    note_text = tk.Text(note_host, height=7, wrap="word", font=("Segoe UI", 10))
    note_text.grid(row=1, column=0, sticky="nsew")
    if str(source_row.get("note", "") or "").strip():
        note_text.insert("1.0", str(source_row.get("note", "") or "").strip())

    actions = ttk.Frame(frame)
    actions.grid(row=2, column=0, sticky="e", pady=(12, 0))

    def save_action() -> None:
        payload = default_production_factory_payload()
        for key in payload:
            payload[key] = vars_map[key].get().strip()
        payload["note"] = note_text.get("1.0", "end-1c").strip() if note_text is not None else ""
        if not payload["factory_code"]:
            messagebox.showwarning(self.t("warning_title"), "Factory Code is required.")
            return
        if not payload["factory_name"]:
            messagebox.showwarning(self.t("warning_title"), "Factory Name is required.")
            return
        existing = normalize_production_factory_row(source_row) or default_production_factory_payload()
        payload["factory_id"] = payload["factory_id"] or str(existing.get("factory_id", "")).strip() or secrets.token_hex(16)
        payload["created_at"] = str(existing.get("created_at", "")).strip() or _production_now_text()
        payload["updated_at"] = _production_now_text()
        saved = self.save_production_factory_row_to_source(payload)
        if not saved:
            messagebox.showerror(self.t("warning_title"), "Could not save factory.")
            return
        self.refresh_production_factory_list_window()
        saved_id = str(saved.get("factory_id", "")).strip()
        if hasattr(self, "production_factory_tree") and saved_id and self.production_factory_tree.exists(saved_id):
            self.production_factory_tree.selection_set(saved_id)
            self.production_factory_tree.focus(saved_id)
        self.set_status(f"Saved factory {saved.get('factory_code', '')}.")
        dialog.destroy()

    ttk.Button(actions, text=self.t("close"), command=dialog.destroy).pack(side="right")
    ttk.Button(actions, text="Save", command=save_action).pack(side="right", padx=(0, 8))


def open_new_production_factory_dialog(self) -> None:
    self.open_production_factory_detail_window(None)


def edit_selected_production_factory_row(self) -> None:
    row = self.get_selected_production_factory_row()
    if row is None:
        messagebox.showwarning(self.t("warning_title"), "Please select one factory first.")
        return
    self.open_production_factory_detail_window(row)


def delete_selected_production_factory_row(self) -> None:
    row = self.get_selected_production_factory_row()
    if row is None:
        messagebox.showwarning(self.t("warning_title"), "Please select one factory first.")
        return
    factory_name = str(row.get("factory_name", "") or row.get("factory_code", "") or "").strip()
    if not messagebox.askyesno(self.t("warning_title"), f"Delete factory '{factory_name}'?"):
        return
    self.delete_production_factory_row_from_source(str(row.get("factory_id", "")).strip())
    self.refresh_production_factory_list_window()
    self.set_status(f"Deleted factory {factory_name}.")


def on_production_factory_row_selected(self, _event: object | None = None) -> None:
    preview_vars = getattr(self, "production_factory_preview_vars", None)
    if not isinstance(preview_vars, dict):
        return
    row = self.get_selected_production_factory_row()
    for key, variable in preview_vars.items():
        if isinstance(variable, tk.StringVar):
            variable.set(self.display_value(row.get(key)) if isinstance(row, dict) else "")


def on_production_factory_row_double_click(self, _event: object | None = None) -> None:
    self.edit_selected_production_factory_row()


def open_production_factory_list_window(self) -> None:
    if not self.is_action_allowed("action.production.factory_list"):
        return
    existing = getattr(self, "production_factory_list_window", None)
    if existing is not None:
        try:
            if existing.winfo_exists():
                existing.deiconify()
                existing.lift()
                existing.focus_force()
                self.refresh_production_factory_list_window()
                return
        except Exception:
            pass

    dialog = tk.Toplevel(self.root)
    dialog.title("Factory List")
    dialog.resizable(True, True)
    dialog.geometry("1120x700")
    dialog.minsize(980, 620)
    self.production_factory_list_window = dialog
    dialog.protocol("WM_DELETE_WINDOW", lambda: close_production_factory_list_window(self))

    frame = ttk.Frame(dialog, padding=16)
    frame.pack(fill="both", expand=True)
    frame.columnconfigure(0, weight=1)
    frame.rowconfigure(3, weight=1)
    ttk.Label(frame, text="Factory List", style="Section.TLabel").grid(row=0, column=0, sticky="w")

    toolbar = ttk.Frame(frame)
    toolbar.grid(row=1, column=0, sticky="ew", pady=(12, 0))
    ttk.Button(toolbar, text="Add", command=self.open_new_production_factory_dialog).pack(side="left")
    ttk.Button(toolbar, text="Edit", command=self.edit_selected_production_factory_row).pack(side="left", padx=(8, 0))
    ttk.Button(toolbar, text="Delete", command=self.delete_selected_production_factory_row).pack(side="left", padx=(8, 0))

    filter_row = ttk.Frame(frame)
    filter_row.grid(row=2, column=0, sticky="ew", pady=(12, 8))
    filter_row.columnconfigure(1, weight=1)
    ttk.Label(filter_row, text="Search").grid(row=0, column=0, sticky="w", padx=(0, 6))
    self.production_factory_search_var = tk.StringVar(value="")
    search_entry = ttk.Entry(filter_row, textvariable=self.production_factory_search_var, width=42)
    search_entry.grid(row=0, column=1, sticky="ew")
    search_entry.bind("<Return>", self.on_production_factory_search_submit)
    search_entry.bind("<KP_Enter>", self.on_production_factory_search_submit)

    table_frame = ttk.Frame(frame)
    table_frame.grid(row=3, column=0, sticky="nsew")
    table_frame.columnconfigure(0, weight=1)
    table_frame.rowconfigure(0, weight=1)
    self.production_factory_tree = ttk.Treeview(
        table_frame,
        columns=PRODUCTION_FACTORY_COLUMNS,
        show="headings",
        selectmode="browse",
        style="Costing.Treeview",
        height=14,
    )
    labels = {
        "factory_code": "Factory Code",
        "factory_name": "Factory Name",
        "contact_person": "Contact Person",
        "phone": "Phone",
        "email": "Email",
        "country": "Country",
        "status": self.t("status"),
        "updated_at": self.t("revised_time_column"),
    }
    widths = {
        "factory_code": 120,
        "factory_name": 240,
        "contact_person": 150,
        "phone": 140,
        "email": 220,
        "country": 120,
        "status": 100,
        "updated_at": 140,
    }
    for column_key in PRODUCTION_FACTORY_COLUMNS:
        self.production_factory_tree.column(column_key, width=widths.get(column_key, 120), anchor="w", stretch=column_key in {"factory_name", "email"})
        self.production_factory_tree.heading(column_key, text=labels.get(column_key, column_key))
    configure_striped_treeview(self.production_factory_tree)
    scroll_y = ttk.Scrollbar(table_frame, orient="vertical", command=self.production_factory_tree.yview)
    scroll_x = ttk.Scrollbar(table_frame, orient="horizontal", command=self.production_factory_tree.xview)
    self.production_factory_tree.configure(yscrollcommand=scroll_y.set, xscrollcommand=scroll_x.set)
    self.production_factory_tree.grid(row=0, column=0, sticky="nsew")
    scroll_y.grid(row=0, column=1, sticky="ns")
    scroll_x.grid(row=1, column=0, sticky="ew")
    self.production_factory_tree.bind("<<TreeviewSelect>>", self.on_production_factory_row_selected)
    self.production_factory_tree.bind("<Double-1>", self.on_production_factory_row_double_click)

    preview = ttk.LabelFrame(frame, text="Basic Information", padding=12)
    preview.grid(row=4, column=0, sticky="ew", pady=(12, 0))
    for column_index in range(4):
        preview.columnconfigure(column_index, weight=1)
    self.production_factory_preview_vars = {
        key: tk.StringVar(value="")
        for key in ("factory_code", "factory_name", "short_name", "status", "contact_person", "phone", "email", "country", "city", "capacity_month", "address_line", "note")
    }

    def add_preview(row_index: int, column_index: int, label: str, key: str, *, columnspan: int = 1) -> None:
        host = ttk.Frame(preview)
        host.grid(row=row_index, column=column_index, columnspan=columnspan, sticky="ew", padx=8, pady=(0, 10))
        host.columnconfigure(0, weight=1)
        ttk.Label(host, text=label).grid(row=0, column=0, sticky="w", pady=(0, 2))
        ttk.Label(host, textvariable=self.production_factory_preview_vars[key], relief="sunken", anchor="w").grid(row=1, column=0, sticky="ew")

    add_preview(0, 0, "Factory Code", "factory_code")
    add_preview(0, 1, "Factory Name", "factory_name", columnspan=2)
    add_preview(0, 3, "Status", "status")
    add_preview(1, 0, "Short Name", "short_name")
    add_preview(1, 1, "Contact Person", "contact_person")
    add_preview(1, 2, "Phone", "phone")
    add_preview(1, 3, "Email", "email")
    add_preview(2, 0, "Country", "country")
    add_preview(2, 1, "City", "city")
    add_preview(2, 2, "Capacity / Month", "capacity_month")
    add_preview(2, 3, "Address", "address_line")
    add_preview(3, 0, "Note", "note", columnspan=4)

    self.production_factory_status_var = tk.StringVar(value="")
    ttk.Label(frame, textvariable=self.production_factory_status_var, relief="sunken", anchor="w", padding=8).grid(row=5, column=0, sticky="ew", pady=(12, 0))

    self.refresh_production_factory_list_window()
    self.apply_permission_state()
    self.center_dialog(dialog, min_width=1120, min_height=700)
    search_entry.focus_set()


def close_production_factory_list_window(self) -> None:
    dialog = getattr(self, "production_factory_list_window", None)
    if dialog is None:
        return
    try:
        dialog.destroy()
    except Exception:
        pass
    self.production_factory_list_window = None


def export_production_report(self) -> None:
    rows = [
        row for row in getattr(self, "filtered_production_rows", []) or []
        if not self.checked_production_ids or str(row.get("record_id", "")).strip() in self.checked_production_ids
    ]
    if not rows:
        messagebox.showwarning(self.t("warning_title"), "There are no Production rows to export.")
        return
    target_path = filedialog.asksaveasfilename(
        title="Export Production Report",
        defaultextension=".xlsx",
        filetypes=[("Excel Workbook", "*.xlsx")],
        initialfile=f"production_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx",
    )
    if not target_path:
        return
    workbook = Workbook()
    sheet = workbook.active
    sheet.title = "Production"
    headers = ["Image"] + [PRODUCTION_FIELD_LABELS.get(key, key) for key in PRODUCTION_COLUMNS]
    sheet.append(headers)
    for row in rows:
        sheet.append([row.get("image_path", "")] + [row.get(key, "") for key in PRODUCTION_COLUMNS])
    for index, header in enumerate(headers, start=1):
        sheet.column_dimensions[sheet.cell(row=1, column=index).column_letter].width = min(max(len(str(header)) + 2, 12), 28)
    workbook.save(target_path)
    self.set_status(f"Exported Production report: {target_path}")


def open_production_order_detail_window(self, row: dict) -> None:
    dialog = tk.Toplevel(self.root)
    dialog.title(f"Production Order Detail - {row.get('production_order', '')}")
    dialog.resizable(True, True)
    dialog.minsize(1180, 760)
    dialog.columnconfigure(0, weight=1)
    dialog.rowconfigure(1, weight=1)

    header = ttk.Frame(dialog, padding=(14, 12))
    header.grid(row=0, column=0, sticky="ew")
    header.columnconfigure(0, weight=1)
    ttk.Label(header, text=str(row.get("production_order", "") or "Production Order"), style="Section.TLabel").grid(row=0, column=0, sticky="w")
    ttk.Label(header, text=f"{row.get('style', '')} | {row.get('po_number', '')} | {row.get('status', '')}", foreground="#5f6b7a").grid(row=1, column=0, sticky="w", pady=(4, 0))

    notebook = ttk.Notebook(dialog)
    notebook.grid(row=1, column=0, sticky="nsew", padx=14, pady=(0, 12))
    tabs = [
        ("overview", "Overview"),
        ("po_quantity", "PO & Quantity"),
        ("ex_factory", "Ex-Factory"),
        ("packing", "Packing"),
        ("inspection", "Inspection"),
        ("materials", "Materials"),
        ("history_notes", "History / Notes"),
    ]
    field_vars: dict[str, tk.StringVar] = {}
    for tab_key, tab_title in tabs:
        frame = ttk.Frame(notebook, padding=14)
        frame.columnconfigure(0, weight=1)
        frame.columnconfigure(1, weight=1)
        notebook.add(frame, text=tab_title)
        if tab_key == "overview":
            _build_production_detail_fields(self, frame, row, field_vars, ["production_order", "factory", "mr_pic", "buyer", "style", "season", "po_number", "dept_number", "store_number", "color", "status"])
        elif tab_key == "po_quantity":
            _build_production_detail_fields(self, frame, row, field_vars, ["po_date", "po_time", "ship_date", "cancel_date"])
            _build_production_po_line_items_section(self, frame, row, field_vars, start_row=4)
        elif tab_key == "ex_factory":
            _build_production_detail_fields(self, frame, row, field_vars, ["ex_fty_date_plan", "actual_ex_fty"])
        elif tab_key == "packing":
            _build_production_detail_fields(self, frame, row, field_vars, ["unit_per_carton", "carton_dimension", "carton_qty", "odd_carton_qty", "odd_carton_dimension", "cbm", "net_weight", "gross_weight"])
        elif tab_key == "inspection":
            _build_production_detail_fields(self, frame, row, field_vars, ["final_inspection_date"])
        elif tab_key == "materials":
            ttk.Label(frame, text="Material readiness will be linked from BOM Production Req in the next step.", foreground="#5f6b7a").grid(row=0, column=0, sticky="w")
        elif tab_key == "history_notes":
            _build_production_detail_fields(self, frame, row, field_vars, ["created_at", "updated_at", "latest_user"])
            ttk.Label(frame, text="Notes").grid(row=4, column=0, sticky="w", pady=(12, 4))
            notes = tk.Text(frame, height=8, wrap="word")
            notes.grid(row=5, column=0, columnspan=2, sticky="nsew")
            notes.insert("1.0", str(row.get("notes", "") or ""))
            field_vars["notes::__text_widget"] = notes

    _setup_production_packing_calculation(field_vars)

    actions = ttk.Frame(dialog, padding=(14, 0, 14, 14))
    actions.grid(row=2, column=0, sticky="ew")
    actions.columnconfigure(0, weight=1)
    ttk.Button(actions, text="Save", command=lambda: self.save_production_detail_window(row, field_vars, dialog)).grid(row=0, column=1, sticky="e", padx=(0, 8))
    ttk.Button(actions, text="Close", command=lambda: self.close_production_detail_window(dialog)).grid(row=0, column=2, sticky="e")

    self.restore_production_detail_window_state(dialog)
    dialog.protocol("WM_DELETE_WINDOW", lambda: self.close_production_detail_window(dialog))


def restore_production_detail_window_state(self, dialog: tk.Toplevel) -> None:
    geometry = str(getattr(self, "ui_state", {}).get("production_detail_window_geometry", "") or "").strip()
    if geometry:
        try:
            dialog.geometry(geometry)
            return
        except Exception:
            pass
    if hasattr(self, "center_dialog"):
        self.center_dialog(dialog, min_width=1180, min_height=760)


def capture_production_detail_window_state(self, dialog: tk.Toplevel) -> None:
    try:
        if not dialog.winfo_exists():
            return
        dialog.update_idletasks()
        geometry = dialog.winfo_geometry()
    except Exception:
        return
    if not geometry:
        return
    try:
        self.ui_state["production_detail_window_geometry"] = geometry
        if hasattr(self, "persist_ui_state"):
            self.persist_ui_state()
    except Exception:
        pass


def close_production_detail_window(self, dialog: tk.Toplevel) -> None:
    self.capture_production_detail_window_state(dialog)
    try:
        dialog.destroy()
    except Exception:
        pass


def _build_production_detail_fields(self, parent: ttk.Frame, row: dict, field_vars: dict[str, tk.StringVar], fields: list[str]) -> None:
    for index, key in enumerate(fields):
        row_index = index // 2 * 2
        column_index = index % 2
        ttk.Label(parent, text=PRODUCTION_FIELD_LABELS.get(key, key)).grid(row=row_index, column=column_index, sticky="w", padx=(0, 12), pady=(0, 4))
        var = tk.StringVar(value=str(row.get(key, "") or ""))
        field_vars[key] = var
        if key in PRODUCTION_DATE_FILTER_FIELDS:
            entry = ttk.Entry(parent, textvariable=var)
            entry.grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))
            self.bind_date_entry_picker(entry, var)
        elif key == "factory":
            values = self.get_active_production_factory_names() if hasattr(self, "get_active_production_factory_names") else []
            combo = ttk.Combobox(parent, textvariable=var, values=values, state="readonly")
            combo.grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))
        elif key == "status":
            combo = ttk.Combobox(parent, textvariable=var, values=PRODUCTION_STATUS_OPTIONS, state="readonly")
            combo.grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))
        elif key == "carton_dimension":
            combo = ttk.Combobox(parent, textvariable=var, values=PRODUCTION_CARTON_DIMENSION_OPTIONS, state="readonly")
            combo.grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))
        elif key in {"carton_qty", "odd_carton_qty", "odd_carton_dimension"}:
            ttk.Entry(parent, textvariable=var, state="readonly").grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))
        else:
            ttk.Entry(parent, textvariable=var).grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))


def _setup_production_packing_calculation(field_vars: dict[str, object]) -> None:
    required_keys = {"unit_per_carton", "carton_qty", "odd_carton_qty", "odd_carton_dimension"}
    if not required_keys.issubset(field_vars):
        return

    def get_text(key: str) -> str:
        variable = field_vars.get(key)
        if hasattr(variable, "get"):
            return str(variable.get() or "").strip()
        return ""

    def set_text(key: str, value: str) -> None:
        variable = field_vars.get(key)
        if hasattr(variable, "set"):
            variable.set(value)

    def recalculate(*_args: object) -> None:
        ship_qty = get_text("ship_qty")
        if not ship_qty:
            total_color_ship_qty = sum(
                _safe_float_value(variable.get())
                for key, variable in field_vars.items()
                if str(key).startswith("color_qty::") and str(key).endswith("::ship_qty") and hasattr(variable, "get")
            )
            ship_qty = _format_number(total_color_ship_qty) if total_color_ship_qty else ""
        row = {
            "ship_qty": ship_qty,
            "unit_per_carton": get_text("unit_per_carton"),
        }
        _recalculate_production_packing(row)
        set_text("carton_qty", str(row.get("carton_qty", "") or ""))
        set_text("odd_carton_qty", str(row.get("odd_carton_qty", "") or ""))
        set_text("odd_carton_dimension", str(row.get("odd_carton_dimension", "") or ""))

    trace_keys = ["unit_per_carton"]
    if "ship_qty" in field_vars:
        trace_keys.append("ship_qty")
    trace_keys.extend(
        key
        for key in field_vars
        if str(key).startswith("color_qty::") and str(key).endswith("::ship_qty")
    )
    for key in trace_keys:
        variable = field_vars.get(key)
        if hasattr(variable, "trace_add"):
            variable.trace_add("write", recalculate)
    recalculate()


def _build_production_po_line_items_section(self, parent: ttk.Frame, row: dict, field_vars: dict[str, tk.StringVar], *, start_row: int) -> None:
    parent.rowconfigure(start_row + 2, weight=1)
    summary = ttk.Frame(parent)
    summary.grid(row=start_row, column=0, columnspan=2, sticky="ew", pady=(12, 8))
    summary.columnconfigure(1, weight=1)
    color_summaries = _production_color_summaries(self, row)
    ttk.Label(summary, text="Color count").grid(row=0, column=0, sticky="w", padx=(0, 8))
    ttk.Label(summary, text=str(len(color_summaries)), relief="sunken", anchor="w", padding=(8, 3)).grid(row=0, column=1, sticky="ew")

    ttk.Label(parent, text="PO Detail Line Items by Color", style="Section.TLabel").grid(row=start_row + 1, column=0, columnspan=2, sticky="w", pady=(0, 6))
    color_notebook = ttk.Notebook(parent)
    color_notebook.grid(row=start_row + 2, column=0, columnspan=2, sticky="nsew")
    if not color_summaries:
        empty_frame = ttk.Frame(color_notebook, padding=12)
        color_notebook.add(empty_frame, text="No Color")
        ttk.Label(empty_frame, text="No PO line item data found.", foreground="#5f6b7a").pack(anchor="w")
        return
    for summary_row in color_summaries:
        color_label = str(summary_row.get("color_label", "") or "No Color")
        table_frame = ttk.Frame(color_notebook, padding=(0, 8, 0, 0))
        color_notebook.add(table_frame, text=color_label[:28] or "No Color")
        _build_production_color_quantity_summary(self, table_frame, summary_row, field_vars)
        _build_production_po_color_line_items_tree(self, table_frame, list(summary_row.get("items", []) or []), start_row=9)


def _production_line_item_color_label(item: dict) -> str:
    color = str(item.get("mfg_color") or item.get("color") or item.get("color_label") or "").strip()
    return color or "No Color"


def _production_group_line_items_by_color(items: list[dict]) -> list[tuple[str, list[dict]]]:
    grouped: dict[str, tuple[str, list[dict]]] = {}
    for item in list(items or []):
        if not isinstance(item, dict):
            continue
        color_label = _production_line_item_color_label(item)
        color_key = color_label.lower()
        if color_key not in grouped:
            grouped[color_key] = (color_label, [])
        grouped[color_key][1].append(dict(item))
    return sorted(grouped.values(), key=lambda pair: pair[0].lower())


def _production_color_storage_key(color_label: object) -> str:
    normalized = " ".join(str(color_label or "No Color").strip().lower().split())
    return normalized or "no color"


def _load_production_color_quantity_map(row: dict) -> dict[str, dict]:
    raw_value = str(row.get("color_quantity_json", "") or "").strip()
    if not raw_value:
        return {}
    try:
        payload = json.loads(raw_value)
    except Exception:
        return {}
    if not isinstance(payload, dict):
        return {}
    normalized: dict[str, dict] = {}
    for key, value in payload.items():
        if isinstance(value, dict):
            normalized[str(key)] = {str(inner_key): str(inner_value or "").strip() for inner_key, inner_value in value.items()}
    return normalized


def _dump_production_color_quantity_map(payload: dict[str, dict]) -> str:
    compact: dict[str, dict[str, str]] = {}
    for color_key, row in dict(payload or {}).items():
        if not isinstance(row, dict):
            continue
        values = {str(key): str(value or "").strip() for key, value in row.items() if str(value or "").strip()}
        if values:
            compact[str(color_key)] = values
    return json.dumps(compact, ensure_ascii=False, separators=(",", ":")) if compact else ""


def _production_color_summary_from_items(self, color_label: str, items: list[dict], row: dict) -> dict[str, object]:
    size_labels, pack_qty_by_size, order_qty_by_size = _production_size_breakdown_from_items(self, items)
    order_qty = sum(order_qty_by_size.get(size, 0.0) for size in size_labels)
    saved_color_map = _load_production_color_quantity_map(row)
    color_key = _production_color_storage_key(color_label)
    saved_row = dict(saved_color_map.get(color_key, {}))
    ship_qty = _safe_float_value(saved_row.get("ship_qty"))
    if ship_qty <= 0:
        ship_qty = order_qty
    diff = ship_qty - order_qty
    return {
        "color_key": color_key,
        "color_label": color_label,
        "items": list(items or []),
        "size_labels": size_labels,
        "pack_qty_by_size": pack_qty_by_size,
        "order_qty_by_size": order_qty_by_size,
        "unit_per_pack": _format_number(sum(pack_qty_by_size.get(size, 0.0) for size in size_labels)),
        "size_range": "-".join(size_labels),
        "size_scale": "-".join(_format_number(pack_qty_by_size.get(size, 0.0)) for size in size_labels),
        "order_qty": _format_number(order_qty),
        "ship_qty": _format_number(ship_qty),
        "over_short_ship_qty": _format_number(diff),
        "over_short_ship_percent": f"{_format_number(diff / order_qty * 100)}%" if order_qty else "",
    }


def _production_color_summaries(self, row: dict) -> list[dict[str, object]]:
    grouped_items = _production_group_line_items_by_color(self.get_production_po_detail_line_items(row))
    return [
        _production_color_summary_from_items(self, color_label, color_items, row)
        for color_label, color_items in grouped_items
    ]


def _build_production_color_quantity_summary(self, parent: ttk.Frame, summary_row: dict[str, object], field_vars: dict[str, tk.StringVar]) -> None:
    color_key = str(summary_row.get("color_key", "") or "")
    fields = [
        ("size_range", "Size Range", True),
        ("size_scale", "Size Scale", True),
        ("order_qty", "Order Qty", True),
        ("ship_qty", "Ship Qty", False),
        ("over_short_ship_qty", "Over/Short ship qty", True),
        ("over_short_ship_percent", "Over/Short ship %", True),
        ("unit_per_pack", "Unit per pack", True),
    ]
    variables: dict[str, tk.StringVar] = {}
    for index, (key, label, readonly) in enumerate(fields):
        row_index = index // 2 * 2
        column_index = index % 2
        parent.columnconfigure(column_index, weight=1)
        ttk.Label(parent, text=label).grid(row=row_index, column=column_index, sticky="w", padx=(0, 12), pady=(0, 4))
        variable = tk.StringVar(value=str(summary_row.get(key, "") or ""))
        variables[key] = variable
        field_vars[f"color_qty::{color_key}::{key}"] = variable
        ttk.Entry(parent, textvariable=variable, state="readonly" if readonly else "normal").grid(row=row_index + 1, column=column_index, sticky="ew", padx=(0, 12), pady=(0, 8))

    def recalculate(*_args: object) -> None:
        order_qty = _safe_float_value(variables["order_qty"].get())
        ship_qty = _safe_float_value(variables["ship_qty"].get())
        diff = ship_qty - order_qty
        variables["over_short_ship_qty"].set(_format_number(diff))
        variables["over_short_ship_percent"].set(f"{_format_number(diff / order_qty * 100)}%" if order_qty else "")

    variables["ship_qty"].trace_add("write", recalculate)
    recalculate()


def _build_production_po_color_line_items_tree(self, table_frame: ttk.Frame, line_items: list[dict], *, start_row: int = 0) -> None:
    table_frame.columnconfigure(0, weight=1)
    table_frame.rowconfigure(start_row, weight=1)

    tree = ttk.Treeview(
        table_frame,
        columns=PRODUCTION_PO_LINE_ITEM_COLUMNS,
        show="headings",
        selectmode="browse",
        style="Costing.Treeview",
        height=7,
    )
    labels = {
        "sku": "SKU",
        "mfg_style": "Style",
        "mfg_color": "Color",
        "size_desc": "Size",
        "description": "Description",
        "upc": "UPC",
        "cost_unit": "Cost",
        "comp": "Comp",
        "retail": "Retail",
        "pack_qty": "Pack Qty",
        "total_packs": "Total Packs",
        "total_units": "Total Units",
    }
    widths = {
        "sku": 90,
        "mfg_style": 90,
        "mfg_color": 150,
        "size_desc": 70,
        "description": 260,
        "upc": 130,
        "cost_unit": 80,
        "comp": 80,
        "retail": 80,
        "pack_qty": 80,
        "total_packs": 95,
        "total_units": 95,
    }
    for column_key in PRODUCTION_PO_LINE_ITEM_COLUMNS:
        tree.column(column_key, width=widths.get(column_key, 100), anchor="w", stretch=column_key == "description")
        tree.heading(column_key, text=labels.get(column_key, column_key))
    configure_striped_treeview(tree)
    scroll_y = ttk.Scrollbar(table_frame, orient="vertical", command=tree.yview)
    scroll_x = ttk.Scrollbar(table_frame, orient="horizontal", command=tree.xview)
    tree.configure(yscrollcommand=scroll_y.set, xscrollcommand=scroll_x.set)
    tree.grid(row=start_row, column=0, columnspan=2, sticky="nsew", pady=(10, 0))
    scroll_y.grid(row=start_row, column=2, sticky="ns", pady=(10, 0))
    scroll_x.grid(row=start_row + 1, column=0, columnspan=2, sticky="ew")
    for index, item in enumerate(line_items, start=1):
        values = tuple(self.display_value(item.get(key)) for key in PRODUCTION_PO_LINE_ITEM_COLUMNS)
        tree.insert("", "end", iid=str(index), values=values, tags=("odd_row" if index % 2 == 1 else "even_row",))


def save_production_detail_window(self, original_row: dict, field_vars: dict[str, object], dialog: tk.Toplevel) -> None:
    record_id = str(original_row.get("record_id", "")).strip()
    updated = dict(original_row)
    for key, var in field_vars.items():
        if key.endswith("::__text_widget"):
            continue
        if key.startswith("color_qty::"):
            continue
        if hasattr(var, "get"):
            updated[key] = str(var.get() or "").strip()
    color_quantity_map: dict[str, dict[str, str]] = {}
    for key, var in field_vars.items():
        if not key.startswith("color_qty::") or not hasattr(var, "get"):
            continue
        parts = key.split("::", 2)
        if len(parts) != 3:
            continue
        _prefix, color_key, field_key = parts
        if field_key not in {"ship_qty"}:
            continue
        color_quantity_map.setdefault(color_key, {})[field_key] = str(var.get() or "").strip()
    if color_quantity_map:
        updated["color_quantity_json"] = _dump_production_color_quantity_map(color_quantity_map)
        total_ship_qty = sum(_safe_float_value(payload.get("ship_qty")) for payload in color_quantity_map.values())
        updated["ship_qty"] = _format_number(total_ship_qty)
    notes_widget = field_vars.get("notes::__text_widget")
    if hasattr(notes_widget, "get"):
        updated["notes"] = str(notes_widget.get("1.0", "end-1c") or "").strip()
    updated["updated_at"] = _production_now_text()
    _recalculate_production_packing(updated)
    normalized = normalize_production_order_row(updated)
    if not isinstance(normalized, dict):
        messagebox.showerror(self.t("warning_title"), "Could not save Production Order.")
        return
    try:
        saved_overlay = self.save_production_detail_row_to_source(normalized)
    except Exception as exc:
        messagebox.showerror(self.t("warning_title"), str(exc))
        return
    style_season_key = _production_style_season_key(normalized)
    shared_values = _production_shared_fields_from_row(normalized)
    updated_at = str(normalized.get("updated_at", "") or "").strip()
    rows = []
    replaced = False
    for row in getattr(self, "production_rows", []) or []:
        row_id = str(row.get("record_id", "")).strip()
        if row_id == record_id:
            rows.append(normalized)
            replaced = True
        elif style_season_key[0] and _production_style_season_key(row) == style_season_key:
            rows.append(_apply_production_shared_fields(dict(row), shared_values, updated_at=updated_at))
        else:
            rows.append(dict(row))
    if not replaced:
        rows.append(normalized)
    self.production_rows = rows
    self.apply_production_filter()
    if hasattr(self, "save_main_ui_local_cache_records_async"):
        self.save_main_ui_local_cache_records_async("production", self.production_rows)
    if hasattr(self, "save_main_ui_session_cache"):
        self.save_main_ui_session_cache(
            "production",
            {
                "tech_pack_library": list(getattr(self, "tech_pack_library", []) or []),
                "production_rows": self.production_rows,
            },
        )
    self.set_status(f"Saved Production Order: {saved_overlay.get('production_order', normalized.get('production_order', ''))}")
    self.close_production_detail_window(dialog)


def bind_production_module(app_cls: type) -> None:
    for name, value in {
        "_build_production_module": _build_production_module,
        "load_production_rows_from_source": load_production_rows_from_source,
        "save_production_rows_to_source": save_production_rows_to_source,
        "save_production_saved_detail_rows_to_source": save_production_saved_detail_rows_to_source,
        "save_production_detail_row_to_source": save_production_detail_row_to_source,
        "delete_production_detail_rows_from_source": delete_production_detail_rows_from_source,
        "load_production_factory_rows_from_source": load_production_factory_rows_from_source,
        "save_production_factory_rows_to_source": save_production_factory_rows_to_source,
        "save_production_factory_row_to_source": save_production_factory_row_to_source,
        "delete_production_factory_row_from_source": delete_production_factory_row_from_source,
        "get_active_production_factory_names": get_active_production_factory_names,
        "get_production_po_detail_line_items": get_production_po_detail_line_items,
        "production_unit_per_pack": production_unit_per_pack,
        "restore_production_detail_window_state": restore_production_detail_window_state,
        "capture_production_detail_window_state": capture_production_detail_window_state,
        "close_production_detail_window": close_production_detail_window,
        "build_production_rows_from_purchase_orders": build_production_rows_from_purchase_orders,
        "refresh_production_module": refresh_production_module,
        "configure_production_filter_options": configure_production_filter_options,
        "update_production_filter_input_state": update_production_filter_input_state,
        "apply_production_filter": apply_production_filter,
        "refresh_production_tree": refresh_production_tree,
        "create_production_thumbnail": create_production_thumbnail,
        "update_production_module_status": update_production_module_status,
        "get_selected_production_record_id": get_selected_production_record_id,
        "get_selected_production_row": get_selected_production_row,
        "on_production_heading_click": on_production_heading_click,
        "update_production_tree_check_cell": update_production_tree_check_cell,
        "on_production_tree_click": on_production_tree_click,
        "on_production_double_click": on_production_double_click,
        "on_production_filter_field_changed": on_production_filter_field_changed,
        "on_production_sort_key_changed": on_production_sort_key_changed,
        "on_production_sort_order_changed": on_production_sort_order_changed,
        "on_production_search_submit": on_production_search_submit,
        "edit_selected_production_order": edit_selected_production_order,
        "delete_selected_production_order": delete_selected_production_order,
        "load_production_packing_list_assets_from_source": load_production_packing_list_assets_from_source,
        "save_production_packing_list_assets_to_source": save_production_packing_list_assets_to_source,
        "load_production_carton_sticker_assets_from_source": load_production_carton_sticker_assets_from_source,
        "save_production_carton_sticker_assets_to_source": save_production_carton_sticker_assets_to_source,
        "resolve_production_packing_list_template_asset": resolve_production_packing_list_template_asset,
        "ensure_production_packing_list_template_asset": ensure_production_packing_list_template_asset,
        "export_selected_production_packing_list": export_selected_production_packing_list,
        "ensure_production_carton_sticker_template_asset": ensure_production_carton_sticker_template_asset,
        "export_selected_production_carton_stickers": export_selected_production_carton_stickers,
        "get_selected_production_factory_id": get_selected_production_factory_id,
        "get_selected_production_factory_row": get_selected_production_factory_row,
        "refresh_production_factory_tree": refresh_production_factory_tree,
        "apply_production_factory_filter": apply_production_factory_filter,
        "refresh_production_factory_list_window": refresh_production_factory_list_window,
        "on_production_factory_search_submit": on_production_factory_search_submit,
        "open_production_factory_detail_window": open_production_factory_detail_window,
        "open_new_production_factory_dialog": open_new_production_factory_dialog,
        "edit_selected_production_factory_row": edit_selected_production_factory_row,
        "delete_selected_production_factory_row": delete_selected_production_factory_row,
        "on_production_factory_row_selected": on_production_factory_row_selected,
        "on_production_factory_row_double_click": on_production_factory_row_double_click,
        "open_production_factory_list_window": open_production_factory_list_window,
        "close_production_factory_list_window": close_production_factory_list_window,
        "export_production_report": export_production_report,
        "open_production_order_detail_window": open_production_order_detail_window,
        "save_production_detail_window": save_production_detail_window,
    }.items():
        setattr(app_cls, name, value)
