#!/usr/bin/env python3
# csv_to_xlsx.py

import argparse
import os
import sys
import csv
import pandas as pd


def get_column_formats(report_type: str):
  column_formats = {}

  if report_type == "stocks":
      column_formats.update({
          'SYS-LOT_NO': 'text',
          'MTR-SKU': 'text',
          'MRN-PARENT_SKU': 'text',
          'MI-FINAL SKU': 'text',
          'MI-FINAL_SKU_TYPE': 'text',
          'MI-DESCRIPTION': 'text',
          'MTR-UOM': 'text',
          'MTR-QTY': 'general',
          'MI-UOM': 'text',
          'SYS-QTY_ALLOC': 'general',
          'SYS-BAL_QTY': 'general',
          'MI-UOM_1': 'text',
          'SYS-QTY_1': 'general',
          'MI-UOM_2': 'text',
          'SYS-QTY_2': 'general',
          'MTR-SERIAL_NO': 'text',
          'MTR-ZAIN_TAG': 'text',
          'MTR-ITEM_CONDITION': 'text',
          'MI-MANUFACTURER': 'text',
          'MTR-SITE_ID_ORIGIN': 'text',
          'MTR-SITE_ID_DESTN': 'text',
          'SYS-AGING': 'general',
          'MTR-STORAGE_AGE': 'general',
          'SYS-AGE_YEAR': 'text',
          'MRN-WH_REF_NO': 'text',
          'MTR-VENDOR_NAME': 'text',
          'MI-DEPARTMENT': 'text',
          'MI-TEAM': 'text',
          'MI-OLD WH_ID': 'text',
          'MRN-NEW_WH_ID': 'text',
          'MI-FINAL_SKU_DESCRIPTION': 'text',
          'MRN-NEW_WH_LOCATION': 'text',
          'MI-FINAL_SKU_UOM': 'text',
          'MTR-REGION': 'text',
          'MTR-ACTION': 'text',
          'MTR-ITEM_TO_BE_REUSED': 'text',
          'MTR-REQUESTOR_NAME': 'text',
          'SYS-ADD_DATE': 'date',
          'SYS-EDIT_DATE': 'date',
          'MTR-REMARKS': 'text',
          'MI-ITEM_TYPE': 'text',
          'MRN-PALLETID': 'text',
          'MRN-PARENT_TAG': 'text',
          'MTR-MTR_SEQ': 'text',
          'MTR-AMU_RESPONSE': 'text',
          'MTR-AMU_REF': 'text',
          'MTR-AMU_NBV': 'general',
          'MRN-WH_REMARKS': 'text',
          'SYS-TAG-STATUS': 'text',
          'MTR-PO_NUMBER': 'text',
          'MTR-PROJECT_NAME': 'text',
          'MTR-ZAIN_PROJECT_OWNER': 'text',
          'MTR-ITEM_RELATED_TO_TEAM': 'text',
          'MTR-MAIN_SUB': 'text',
          'MTR-MAIN_SEQ': 'text',
          'MI-ITEM_DIMENSION': 'text',
          'MTR-NET_REFERRENCE': 'text',
          'STATUS': 'text',
          'Reserved-Status': 'text',
          'LEGACY_DATA': 'text',
      })
  elif report_type == "min":
      column_formats.update({
          'LotNo': 'text',
          'SKU': 'text',
          'Parent_Sku': 'text',
          'Description': 'text',
          'UOM': 'text',
          'Qty': 'general',
          'Serial_Number': 'text',
          'Zain_Tag': 'text',
          'Item_Condition': 'text',
          'MANUFACTURER': 'text',
          'Site_ID_Destn': 'text',
          'Site_ID_Origin': 'text',
          'WH_REF_NO': 'text',
          'VendorName': 'text',
          'Department': 'text',
          'Team': 'text',
          'WH ID': 'text',
          'WH_Location': 'text',
          'Region': 'text',
          'Item_to_be_Reused': 'text',
          'RequestorNameMobile': 'text',
          'Add_Date': 'date',
          'Edit_Date': 'date',
          'Remarks': 'text',
          'Item Type': 'text',
          'PO Number': 'text',
          'Project': 'text',
          'Zain Project Owner': 'text',
          'MIR Reference Number': 'text',
      })
  elif report_type == "mrn":
      column_formats.update({
          'LotNo': 'text',
          'PONumber': 'text',
          'WH_REF_NO': 'text',
          'Vendor_Name': 'text',
          'SKU': 'text',
          'Parent SKU': 'text',
          'Parent Tag': 'text',
          'Description': 'text',
          'UOM': 'text',
          'Qty': 'general',
          'Serial_No': 'text',
          'Zain_Tag': 'text',
          'Item_Condition': 'text',
          'Manufacturer': 'text',
          'Site_ID_Origin': 'text',
          'Site_ID_Destn': 'text',
          'Department': 'text',
          'Team': 'text',
          'WH_ID': 'text',
          'WH_Location': 'text',
          'Region': 'text',
          'Storage Age': 'general',
          'Action': 'text',
          'Main / Sub Item': 'text',
          
          'Item Dimensions': 'text',
          'Main Item Sequence': 'text',
          'Item_to_be_Reuse': 'text',
          'RequestorNameMobile': 'text',
          'Add_Date': 'date',
          'Edit_Date': 'date',
          'Remarks': 'text',
          'Item Type': 'text',
          'AMU Reference': 'text',
          'AMU Response': 'text',
          'AMU NBV': 'general',
          'Pallet': 'text',
          'MTR Sequence Number': 'text',
          'Project': 'text',
          'Zain Project Owner': 'text',
          'MTR Reference Number': 'text',
      })
  elif report_type == "items":
      column_formats.update({
          'MI-SKU': 'text',
          'MI-PARENT SKU': 'text',
          'MI-SERIALIZED': 'text',
          'MI-SNAP_YN': 'text',
          'MI-ZAIN_LOGO_YN': 'text',
          'MI-ACTIVE_PASSIVE': 'text',
          'MI-UOM': 'text',
          'MI-QTY': 'general',
          'MI-UOM_1': 'text',
          'SYS-QTY_1': 'general',
          'MI-UOM_2': 'text',
          'SYS-QTY_2': 'general',
          'MI-CONVERSION FACTOR': 'general',
          'MI-CONVERSION FACTOR1': 'general',
          'MI-CONVERSION FACTOR2': 'general',
          'MI-DEPARTMENT': 'text',
          'MI-TEAM': 'text',
          'MI-ITEM_MAJOR_TYPE': 'text',
          'MI-MANUFACTURER': 'text',
          'MI-ITEM_DESCRIPTION': 'text',
          'MI-LONG_DESCRIPTION': 'text',
          'MI-HEIGHT': 'general',
          'MI-WIDTH': 'general',
          'MI-LENGTH': 'general',
          'MI-HEIGHT1': 'general',
          'MI-WIDTH1': 'general',
          'MI-LENGTH1': 'general',
          'MI-HEIGHT2': 'general',
          'MI-WIDTH2': 'general',
          'MI-LENGTH2': 'general',
          'MI-AF_SQM_ST': 'text',
          'MI-AF_SQM_OPS': 'general',
          'MI-STACKING': 'general',
          'MI-AF_SQM_ST1': 'text',
          'MI-AF_SQM_OPS1': 'general',
          'MI-STACKING1': 'general',
          'MI-AF_SQM_ST2': 'text',
          'MI-AF_SQM_OPS2': 'general',
          'MI-STACKING2': 'general',
          'MI-ADD_DATE': 'date',
      })

  return column_formats


def csv_to_xlsx(input_csv: str, output_xlsx: str, report_type: str) -> bool:
    if not os.path.exists(input_csv):
        print(f"[PY] ERROR: CSV not found: {input_csv}", file=sys.stderr)
        return False

    column_formats = get_column_formats(report_type)

    print(f"[PY] Reading CSV: {input_csv}")
    df = pd.read_csv(
        input_csv,
        encoding="utf-8",
        delimiter=",",
        quoting=csv.QUOTE_MINIMAL,
        dtype=str,
        na_values=['', 'NULL', 'null'],
        keep_default_na=False
    )
    print(f"[PY] Loaded {len(df)} rows, {len(df.columns)} columns")

    # Format columns
    for col, fmt in column_formats.items():
        if col not in df.columns:
            continue

        if fmt == "general":
             # Replace empty strings and NULL variants with NaN before numeric conversion
            df[col] = df[col].replace(['', 'NULL', 'null'], pd.NA)
            df[col] = pd.to_numeric(df[col], errors="coerce")
        elif fmt == "date":
            # Replace empty strings and NULL variants with NaN before date conversion
            df[col] = df[col].replace(['', 'NULL', 'null'], pd.NA)
            df[col] = pd.to_datetime(df[col], errors="coerce").dt.strftime('%d-%b-%y')

    # Clean whitespace from text columns
    for col in df.select_dtypes(include=['object']).columns:
        df[col] = df[col].str.strip() if hasattr(df[col], 'str') else df[col]
        # Replace empty strings with empty cells for text columns
        df[col] = df[col].replace('', pd.NA)

    print(f"[PY] Writing XLSX: {output_xlsx}")
    
    # Use xlsxwriter for smaller file size
    with pd.ExcelWriter(output_xlsx, engine="xlsxwriter",
                        engine_kwargs={'options': {
                            'strings_to_numbers': False,  # Changed to False!
                            'strings_to_urls': False,
                            'nan_inf_to_errors': True
                        }}) as writer:
        df.to_excel(writer, sheet_name="Data", index=False)
        
        # Get workbook and worksheet objects
        workbook = writer.book
        worksheet = writer.sheets['Data']
        
        # Create text format
        text_format = workbook.add_format({'num_format': '@'})
        
        # Apply text format to specific columns
        for col_name, col_format in column_formats.items():
            if col_format == 'text' and col_name in df.columns:
                col_idx = df.columns.get_loc(col_name)
                # Set column format as text (from row 1 to end, skipping header)
                worksheet.set_column(col_idx, col_idx, None, text_format)

    print("[PY] OK")
    return True
def main():
  parser = argparse.ArgumentParser()
  parser.add_argument("--input", required=True, help="Input CSV path")
  parser.add_argument("--output", required=True, help="Output XLSX path")
  parser.add_argument("--type", required=True, help="Report type (stocks|min|mrn|items)")
  args = parser.parse_args()

  ok = csv_to_xlsx(args.input, args.output, args.type)
  sys.exit(0 if ok else 1)


if __name__ == "__main__":
  main()
