# AUTOGENERATED! DO NOT EDIT! File to edit: xlsx.ipynb (unless otherwise specified).

__all__ = ['to_excel', 'column_format', 'default_formats', 'column_formats', 'format_sheet']

# Internal Cell
import openpyxl
from openpyxl.styles import Alignment
from openpyxl.worksheet.table import Table, TableStyleInfo
import re
from pathlib import Path
import toolz.curried as tz
from fnmatch import fnmatch

# Internal Cell
from jedi_toolz import show
from datetime import date
from dateutil.relativedelta import relativedelta as delta
from random import choice, randint, random

names = (
    "Joe Nancy Harry Gus David Max Matt Nicole Tracy Stacy "
    "Kristi Kelly Mike James"
)
texts = (
    "Univeristy Franklin End_Game Tower New_York_Mets Last_Dance Movies Donald_Trump "
    "Nation_Captial COVID-19 Honesty Some_Really_Long_Text The_Lord_of_the_Rings"
)
flag = lambda: True if randint(1, 10) < 10 else False
text = lambda: choice([val.replace("_", " ") for val in texts.split()]) if flag() else None
name = lambda: choice(names.split())
dt = lambda: date.today() + delta(days=randint(-30, 30)) if flag() else None
amt = lambda: randint(150_000, 350_000) * random()

# Internal Cell
gen_data = lambda n=100: [
    {
        "Order Date": dt(),
        "Close Date": dt(),
        "Name": name(),
        "Dept": text(),
        "Balance": amt(),
        "Loan": amt(),
    }
    for row in range(n)
]
show(gen_data())

# Cell
def to_excel(data, file, sheet_name, over_write=True):
    if not over_write and file.exists():
        wb = openpyxl.load_workbook(file)
        ws = wb.create_sheet(sheet_name)
    else:
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = sheet_name
    for row_num, row in enumerate(data):
        if row_num == 0:
            ws.append([k for k in row])
        ws.append(v for v in row.values())
    wb.save(str(file))
    wb.close()
    return file

# Internal Cell
def make_test_file():
    file = Path.cwd() / "test.xlsx"
    sheet_name = "Test 1"
    over_write = True
    data = gen_data(100)
    return to_excel(data, file, sheet_name, over_write)

# Cell
def column_format(number_format="", width=15, vertical="top", horizontal="left", wrap_text=True, **kwargs):
    return {
        "number_format": number_format,
        "alignment": Alignment(vertical=vertical, horizontal=horizontal, wrap_text=wrap_text, **kwargs),
        "width": width,
    }

# Cell
def default_formats(file, sheet_name, rows_to_review=100):
    wb = openpyxl.load_workbook(str(file), read_only=True)
    ws = wb[sheet_name]
    rows = ws.rows
    header = next(rows)
    names = [cell.value for cell in header]
    letters = [cell.column_letter for cell in header]
    return tz.pipe(
        rows,
        tz.take(rows_to_review),
        tz.map(lambda row: dict(zip(names, row))),
        tz.map(tz.valmap(tz.flip(getattr, "data_type"))),
        tz.merge_with(list),
        tz.valmap(tz.frequencies),
        lambda row: {
            k: (
                column_format("YYYY-MM-DD", horizontal="right") if "d" in v else
                column_format() if "s" in v else
                column_format("#,##0.00", horizontal="right")
            )
            for k, v in row.items()
        },
    )

# Cell
def column_formats(file, sheet_name, patterns=None):
    defaults = default_formats(file, sheet_name)
    if patterns is None:
        return defaults

    results = {}
    for col in defaults:
        for pat, fmt in patterns.items():
            if fnmatch(col, pat) and col not in results:
                results[col] = fmt
        if col not in results:
            results[col] = defaults[col]
    return results

# Cell
def format_sheet(file, sheet_name, format_patterns=None, table_name=None, freeze_panes="A2"):
    # Load file
    wb = openpyxl.load_workbook(file)
    ws = wb[sheet_name]

    # Get column names and calc formats
    rows = ws.rows
    header = next(rows)
    column_names = [cell.value for cell in next(rows)]
    formats = column_formats(file, sheet_name, format_patterns)

    # Loop by column and format column
    for col in ws.iter_cols():
        header = col[0]
        name = header.value
        letter = header.column_letter

        # Set width first so that text wrap works
        ws.column_dimensions[letter].width = formats[name]["width"]

        # Add alignment and number format
        for cell in col:
            cell.alignment = formats[name]["alignment"]
            cell.number_format = formats[name]["number_format"]

    # Freeze panes
    ws.freeze_panes = ws[freeze_panes]

    # Add table
    table_name = table_name or sheet_name
    table_name = table_name.replace(" ", "_")
    table = Table(displayName=table_name, ref=ws.dimensions)
    style = TableStyleInfo(name="TableStyleLight1", showFirstColumn=False, showColumnStripes=False, showRowStripes=True)
    table.tableStyleInfo = style
    ws.add_table(table)

    # Save file
    wb.save(str(file))
    wb.close()