#!/usr/bin/env python3
"""
populate_template.py

Script to copy data from a production order Excel file into an ODS template
and save the result as a new ODS file named after the value in cell A2.

Requirements:
    pip install openpyxl odfpy
"""

import sys
from pathlib import Path

from openpyxl import load_workbook
from odf.opendocument import load, OpenDocumentSpreadsheet
from odf.table import Table, TableRow, TableCell
from odf.text import P

# ----------------------------------------------------------------------
# Configuration – adjust if your filenames differ
# ----------------------------------------------------------------------
SOURCE_XLSX = Path("Production Order (mrp.production).xlsx")
TEMPLATE_ODS = Path("A4004_v3.0-260617.ods")
OUTPUT_DIR   = Path(".")  # current directory; change if you prefer another location

# ----------------------------------------------------------------------
# Helper functions for ODS manipulation
# ----------------------------------------------------------------------
def get_cell(table: Table, col_idx: int, row_idx: int) -> TableCell:
    """Return the TableCell at (col_idx, row_idx) – 0‑based indices."""
    rows = table.getElementsByType(TableRow)
    if row_idx >= len(rows):
        raise IndexError(f"Row {row_idx} out of range")
    cells = rows[row_idx].getElementsByType(TableCell)
    if col_idx >= len(cells):
        raise IndexError(f"Column {col_idx} out of range")
    return cells[col_idx]

def set_cell_value(table: Table, col_idx: int, row_idx: int, value: str):
    """Write a string value into the specified cell."""
    cell = get_cell(table, col_idx, row_idx)
    # Clear existing content
    for child in list(cell.childNodes):
        cell.removeChild(child)
    # Insert new text
    cell.addElement(P(text=str(value)))

def col_letter_to_index(letter: str) -> int:
    """Convert Excel‑style column letter (A=0, B=1, …) to zero‑based index."""
    return ord(letter.upper()) - ord('A')

# ----------------------------------------------------------------------
# Main processing
# ----------------------------------------------------------------------
def main() -> None:
    # 1. Load source workbook
    wb = load_workbook(SOURCE_XLSX, data_only=True)
    ws = wb.active

    # Helper to find a cell containing a given substring (case‑sensitive)
    def find_cell_containing(text: str):
        for row in ws.iter_rows(values_only=False):
            for cell in row:
                if isinstance(cell.value, str) and text in cell.value:
                    return cell
        return None

    # ------------------------------------------------------------------
    # Extract required values from the source file
    # ------------------------------------------------------------------
    # a) FA‑ suffix (column B)
    fa_suffix = None
    for cell in ws["B"]:
        if isinstance(cell.value, str) and cell.value.startswith("FA-"):
            fa_suffix = cell.value.split("FA-")[1].strip()
            break
    if fa_suffix is None:
        sys.exit("Error: Could not find a cell in column B starting with 'FA-'")

    # b) Adjacent values for the component strings
    def get_right_adjacent(search_str: str) -> str:
        match = find_cell_containing(search_str)
        if not match:
            sys.exit(f"Error: Could not find cell containing '{search_str}'")
        right_cell = ws.cell(row=match.row, column=match.column + 1)
        return right_cell.value if right_cell.value is not None else ""

    barebone_val = get_right_adjacent("All / Components / Barebone")
    gpu_val      = get_right_adjacent("All / Components / GPU")
    ram_val      = get_right_adjacent("All / Components / RAM")
    cpu_val      = get_right_adjacent("All / Components / CPU")
    ssd_val      = get_right_adjacent("All / Components / SSD")
    raid_val     = get_right_adjacent("All / Components / RAID")

    # c) File name from A2
    file_name_cell = ws["A2"]
    if file_name_cell.value is None:
        sys.exit("Error: Cell A2 in source file is empty")
    output_name = f"{file_name_cell.value}.ods"

    # ------------------------------------------------------------------
    # Load ODS template and write values
    # ------------------------------------------------------------------
    ods_doc: OpenDocumentSpreadsheet = load(str(TEMPLATE_ODS))
    # Assuming the template has a single table; adjust index if needed
    table: Table = ods_doc.spreadsheet.getElementsByType(Table)[0]

    # Mapping of target ranges (top‑left cell only) → value
    # (col_letter, row_number) are 1‑based as in Excel/ODS UI
    targets = {
        ("B", 1): fa_suffix,      # B1:C2 → write to B1
        ("C", 10): barebone_val, # C10:D10 → write to C10
        ("C", 20): gpu_val,      # C20:D23 → write to C20
        ("C", 12): ram_val,      # C12:D19 -> write to C12
        ("C", 11): cpu_val,      # C11:D11 -> write to C11
        ("C", 24): ssd_val,      # C24:D25 -> write to C24
        ("C", 27): raid_val,     # C27:D27 -> write to C27
    }

    for (col_letter, row_number), value in targets.items():
        col_idx = col_letter_to_index(col_letter)
        row_idx = row_number - 1  # zero‑based for helper
        set_cell_value(table, col_idx, row_idx, value)

    # ------------------------------------------------------------------
    # Save the modified document
    # ------------------------------------------------------------------
    output_path = OUTPUT_DIR / output_name
    ods_doc.save(str(output_path))
    print(f"Successfully created: {output_path}")

if __name__ == "__main__":
    main()
