#=
Code to produce well laid out Starling statements.
=#
using CSV, Printf

# Format array of numbers to have two decimal places.
fmt_float(m) = map( e -> isa(e, AbstractFloat) ? @sprintf("%.2f", e) : e, m)

#=
Create statement table
Parameter m is the bank's statement csv file as a matrix, 8 columns as follows.
 1      2              3           4      5        6         7                   8
 Date | Counterparty | Reference | Type | Amount | Balance | Spending Category | Notes
=#
function statement(m)

    # text_clean: clean text up by:
    # 1. replacing 'missing' with empty string,
    # 2. escaping characters that are special to Latex
    function text_clean(mtx)
        temp1 = map( e -> ismissing(e) ? "" : e, mtx )
        map( e -> replace(e, "&" => "\\&", "_" => "\\_"), temp1 )
    end

    #=
    This function cleans up the data.
    i.e. It creates a new matrix from the raw data with the text cleaned up
         and the floats formatted and turned into strings.
    All 8 columns don't fit on a landscape A4 page so drop the 'Spending Category' column (#7).
    V2 onwards also drop the 'Balance' column (#6) and add a summary table showing the opening and closing balances.
    =#
    function clean_data(input)
        [ input[:,1] text_clean(input[:,2:4]) fmt_float(input[:,5]) text_clean(input[:,8])]
    end

    # Create a single row of latex table.
    row(v) = join(v, " & ") * "\\\\ \n"

    # Given matrix m collect up all its rows to be the rows of a latex table
    # Changed in V4: rows(m) = map(r -> row(r), eachrow(m)) |> join
    rows(m) = row.(eachrow(m)) |> join

    statement_start = """
    \\begin{center}

    \\begin{longtblr}[
        caption ={Starling Joint Account Statement},
        label = {tab:test},
        ]{
        rowhead = 1,
        }
    \\textbf{Date} & \\textbf{Counterparty} & \\textbf{Reference} & \\textbf{Type} 
    & \\textbf{Amount} & \\textbf{Notes} \\\\
    \\hline
    """

    statement_end = """   
    \\end{longtblr}
    \\end{center}
    """
    
    string(statement_start, rows(clean_data(m)), statement_end)

end

#=
Create footer table.
The bank's statement csv file is a matrix, 8 columns as follows.
1      2              3           4      5        6         7                   8
Date | Counterparty | Reference | Type | Amount | Balance | Spending Category | Notes
The data parameter here is just columns 5 and 6.
=#
function footer(data)

    # Create the single row of data in the latex table.
    row(v) = join(v, " & ") * "\\\\ \n"

    transactions = data[:,1]

    #=
    Calcjulate opening balance, negatives, positives, expenditure, closing balance.
    The closing balance value, cbal, is the bank's closing balance, i.e. after the last transaction.
    The code checks that this is the same figure we get by working out
    positives, negatives, expenditure and then closing balance = opening balance + expenditure.
    =#
    obal = data[1,2] - data[1,1]
    negatives = filter(v -> v < 0, transactions) |> sum
    positives = filter(v -> v > 0, transactions) |> sum
    expenditure = positives + negatives
    cbal = data[end,2]

    # Code checks that obal + expenditure == cbal
    msg = 
        if round(obal + expenditure; digits=2) == round(cbal; digits=2)
            @sprintf("""
                \\begin{center}
                Opening Balance + Expenditure = Bank's Closing Balance: %.2f + %.2f = %.2f
                \\end{center}
                """,
                obal, expenditure, cbal)
        else
            @sprintf("""
                \\begin{center}
                Error: Opening Balance + Expenditure != Bank's Closing Balance: %.2f + %.2f != %.2f
                \\end{center}
                """,
                obal, expenditure, cbal)
        end

    raw_figures = [obal, negatives, positives, expenditure, cbal]
    figures = fmt_float(raw_figures)

    summary_table_pre = """
    \\begin{table}[h!]
      \\begin{center}
        \\caption{Summary}
        \\begin{tabular}{rrrrr} 
          \\textbf{O/Bal} & \\textbf{Negatives} & \\textbf{Positives} & \\textbf{Expenditure} & \\textbf{C/Bal} \\\\ \n
          \\hline
    """

    summary_table_post = """
        \\end{tabular}
      \\end{center}
    \\end{table}
    """

    string(summary_table_pre, row(figures), summary_table_post, msg)

end

# Create latex document given latex formatted content.
function document(statement, footer)
    doc_start = """
    \\documentclass[12pt]{article}
    \\usepackage[a4paper, landscape, margin=0.5in]{geometry}
    \\usepackage{tabularray}
    \\usepackage{setspace}
    \\renewcommand{\\baselinestretch}{1.5}

    \\begin{document}
    """

    doc_end = """
    \\end{document}
    """

    string(doc_start, statement, footer, doc_end)
end

# Write the data, converted to a latex document, to a file.
function write_latex(filename, document_tex)
    open(filename, "w") do f
        write(f, document_tex)
    end
end

#====================================================================================
# The main program.
# I'm just going to assume that the input and output filenames are in the right order.
# Maybe -i -o style prefixes to the filenames would be more 'industrial strength'! 
======================================================================================#
function main(inputfile, outputfile)

    input = CSV.read(inputfile, CSV.Tables.matrix)
    statement_tex = statement(input)
    footer_tex = footer(input[:,5:6])
    document_tex = document(statement_tex, footer_tex)
    write_latex(outputfile, document_tex)

    # Print on the terminal how to convert the tex file to a pdf file.
    println("""
    Success: Output .tex file created.
    Use command line utility pdflatex to convert [filename].tex to [filename].pdf:
    \$ pdflatex [filename].tex
    """)
end

# Use command line arguments to call main.
if length(ARGS) == 2

    main(ARGS[1], ARGS[2])

else

    println("""
        Error: after the name of the julia program file we need
        the inputfile complete with .csv suffix and
        the outputfile complete with .tex suffix. e.g:
        \$ julia  StarlingStatementV5.jl StarlingStatement.csv StarlingStatementV5.tex
        """)

end