#!/usr/bin/env ruby

require "csv"
require "date"
require "pathname"

def format_amount(amount)
  format("%.2f", amount)
end

def usage!
  warn "Usage: apple_card_report.rb INPUT.csv OUTPUT.md"
  exit 1
end

input_path = ARGV[0]
output_path = ARGV[1]
usage! unless input_path && output_path

input = Pathname.new(input_path)
output = Pathname.new(output_path)

rows = CSV.read(input, headers: true).map do |row|
  {
    transaction_date: Date.strptime(row.fetch("Transaction Date"), "%m/%d/%Y"),
    clearing_date: Date.strptime(row.fetch("Clearing Date"), "%m/%d/%Y"),
    description: row.fetch("Description"),
    merchant: row.fetch("Merchant"),
    category: row.fetch("Category"),
    type: row.fetch("Type"),
    amount: row.fetch("Amount (USD)").to_f,
    purchased_by: row.fetch("Purchased By"),
  }
end

dates = rows.map { |row| row[:transaction_date] }
cost_rows = rows.reject { |row| row[:type] == "Payment" }
cost_dates = cost_rows.map { |row| row[:transaction_date] }
type_totals = Hash.new(0.0)
purchase_category_totals = Hash.new(0.0)
merchant_totals = Hash.new(0.0)

cost_rows.each do |row|
  type_totals[row[:type]] += row[:amount]
  next unless row[:type] == "Purchase"

  purchase_category_totals[row[:category]] += row[:amount]
  merchant_totals[row[:merchant]] += row[:amount]
end

output.parent.mkpath

markdown = +"# Apple Card Report\n\n"
markdown << "- Source file: `#{input.basename}`\n"
markdown << "- Imported from: `#{input}`\n"
markdown << "- Rows: #{cost_rows.size}\n"
markdown << "- Actual transaction date range: #{cost_dates.min} to #{cost_dates.max}\n\n"

markdown << "## Totals By Type\n\n"
type_totals.sort.each do |type, total|
  markdown << "- #{type}: #{format_amount(total)}\n"
end
markdown << "- Net cost activity: #{format_amount(type_totals.values.sum)}\n\n"

markdown << "## Purchase Totals By Category\n\n"
purchase_category_totals.sort.each do |category, total|
  markdown << "- #{category}: #{format_amount(total)}\n"
end
markdown << "\n## Purchase Totals By Merchant\n\n"
merchant_totals.sort_by { |merchant, total| [-total, merchant] }.each do |merchant, total|
  markdown << "- #{merchant}: #{format_amount(total)}\n"
end

markdown << "\n## Transactions\n\n"
markdown << "| Transaction Date | Clearing Date | Type | Category | Amount (USD) | Merchant |\n"
markdown << "| --- | --- | --- | --- | ---: | --- |\n"
cost_rows.sort_by { |row| [row[:transaction_date], row[:clearing_date], row[:merchant]] }.reverse_each do |row|
  markdown << "| #{row[:transaction_date]} | #{row[:clearing_date]} | #{row[:type]} | #{row[:category]} | #{format_amount(row[:amount])} | #{row[:merchant]} |\n"
end

output.write(markdown)
