#!/usr/bin/python3

import argparse
import configparser
import psycopg2
import datetime
import json
import pprint

# network imports
import smtplib
from email.mime.text import MIMEText
from email.parser import Parser

# local imports
import fcntoolbox.dolibarr as dolibarr

parser = argparse.ArgumentParser()
parser.add_argument("selection", type=str,
                    choices=["send-reminders", "report"])
parser.add_argument("-c", "--config", type=str,
                    default="/etc/fcntoolbox/config.ini",
                    help="specify a configuration file")

args = parser.parse_args()

conf = configparser.RawConfigParser()
conf.sections()
conf.read(args.config)
confdoli = conf['dolibarr']
remindConf = conf['reminder']

s = smtplib.SMTP('localhost')

conn = psycopg2.connect(database=confdoli['database'], 
  user=confdoli['user'], password=confdoli['password'])
doli = dolibarr.Instance(conn)
accounts = list(doli.get_bank_accounts(fields=['iban_prefix', 'bank']))

parsedate = lambda x : datetime.datetime.strptime(x, "%Y-%m-%d %H:%M:%S")

reportAdherents = []
reportBody = []

def getLateMembers(reminder):
  minKey = "%s_min" % reminder
  maxKey = "%s_max" % reminder
  if (not minKey in remindConf) or (not maxKey in remindConf):
    print("Configuration missing for '%', skipping reminder" % reminder)
    return list()
  
  min = int(remindConf[minKey])
  minabs = abs(min)
  minsign = '+' if min >= 0 else '-'
  max = int(remindConf[maxKey])
  maxabs = abs(max)
  maxsign = '+' if max >= 0 else '-'
  
  rows = ["rowid", "firstname", "lastname", "datefin", "email"]
  query = """SELECT {} FROM llx_adherent
             WHERE (datefin {} interval '{} days' > 'now' 
                    AND datefin {} interval '{} days' < 'now')
             AND statut = 1 """
  
  cur = conn.cursor()
  cur.execute(query.format(",".join(rows), maxsign, maxabs, minsign, minabs))
  members = cur.fetchall()
  members = list(map(lambda member: dict(zip(rows, member)), members))
  return members

def sendReminders(reminder):
  global reportAdherents
  global reportBody
  lateMembers = getLateMembers(reminder)

  # Last reminder state  
  remindstate = laststate[reminder] if reminder in laststate else []
  
  # New reminder state
  state[reminder] = list(map(lambda x : int(x['rowid']), lateMembers))
  adherents = list(filter(lambda x: not int(x['rowid']) in remindstate, lateMembers))
  
  remindFormat = open('cotisation-%s.format' % reminder, 'r').read()
  
  for adherent in adherents:
    adherent['rowid'] = int(adherent['rowid'])
    fdict = adherent.copy()
    if len(accounts) > 0:
      account = accounts[0]
      fdict['bank_account_iban'] = account[0]
      fdict['bank_account_bank'] = account[1]
    rawemail = remindFormat.format(**fdict)
    parsedemail = Parser().parsestr(rawemail)
    body = parsedemail.get_payload()
    msg = MIMEText(body)
    for key, val in parsedemail.items():
      msg[key] = val
    msg['From'] = "tresoriers@listes.franciliens.net"
    msg['To'] = adherent['email']
    if not "Subject" in msg:
      print("Error: no subject in template email")
      break
    if len(body.strip()) == 0:
      print("Error: no body in template email")
      break
    s.send_message(msg)
  
  if len(adherents) > 0:
    reportAdherents += adherents
    reportBody += [body]

if args.selection == 'send-reminders':
  # Read state
  with open('cotisation-state.json', 'r') as statefp:
    laststate = json.load(statefp)
    state = laststate
  
  reminders = ['reminder0', 'reminder1', 'reminder2', 'reminder3']
  
  for reminder in reminders:
    sendReminders(reminder)
  
  reportFormat = open('cotisation-report.format', 'r').read()  
  pp = pprint.PrettyPrinter()
  
  if len(reportAdherents) > 0:
    body = reportFormat.format(adherents = pp.pformat(reportAdherents), template = "\n----------\n".join(reportBody))
    msg = MIMEText(body)
    msg['Subject'] = "Rapport des rappels de cotisation"
    msg['From'] = "root@franciliens.net"
    msg['To'] = "tresoriers@listes.franciliens.net"
    s.send_message(msg)
  s.quit()

  # Save state
  with open('cotisation-state.json', 'w') as statefp:
    json.dump(state, statefp)
  
elif args.selection == 'report':
  lateMembers = getLateMembers('reminder3')
  for member in lateMembers:
    print(member)