"""Validate then execute fixed Chapter 18 cases through the public Runtime CLI."""
from chapter18_support import *

e = Path(json.loads((ROOT/'latest-run.json').read_text(encoding='utf-8'))['evidenceDirectory'])
invoice = 'TeachingInvoiceDatesQueryModel'
calendar = 'TeachingCalendarReportQueryModel'

def q(name, model, payload, rejected=False):
    obj = run_query(e, name, model, payload, rejected)
    print(name, obj.get('success'), json.dumps(obj.get('data', {}).get('items', obj.get('error')), ensure_ascii=True)[:1700], flush=True)

def between(field, lo, hi):
    return {'field': field, 'op': '[)', 'value': [lo, hi]}

q('01-calendar-daily', calendar, {'columns':['calendarDate','dataComplete','rawAmount','reportedAmount'],
    'slice':[between('calendarDate','2012-11-01','2012-11-18')], 'orderBy':['calendarDate'],'limit':50})

for name, ym, dt in [('02-business-month', 'invoiceMonth', 'invoiceDate'), ('03-loaded-month', 'loadedMonth', 'loadedAt')]:
    q(name, invoice, {'columns': [ym, 'sum(invoiceAmount) as amount', 'count(invoiceId) as bills'],
        'slice': [between(dt, '2012-11-01', '2012-12-01')], 'groupBy': [ym], 'limit': 5})

q('04-boundary-invoice', invoice, {'columns': ['invoiceId', 'invoiceDate', 'loadedAt', 'invoiceAmount'],
    'slice': [{'field': 'invoiceId', 'op': '=', 'value': 325}], 'limit': 5})

q('05-comparable-periods', invoice, {'columns': ['invoiceMonth', 'sum(invoiceAmount) as amount', 'count(invoiceId) as bills'],
    'slice': [between('invoiceDate', '2012-10-01', '2012-11-16'), {'field': 'invoiceDayOfMonth', 'op': '<=', 'value': 15}],
    'groupBy': ['invoiceMonth'], 'orderBy': ['invoiceMonth'], 'limit': 5})

current = "sum(if(invoiceMonth == '2012-11', invoiceAmount, 0))"
prior = "sum(if(invoiceMonth == '2012-10', invoiceAmount, 0))"
q('06-period-difference', invoice, {'columns': ['currentAmount', 'priorAmount', 'difference', 'changeRate'],
    'calculatedFields': [
        {'name': 'currentAmount', 'expression': current}, {'name': 'priorAmount', 'expression': prior},
        {'name': 'difference', 'expression': f'{current} - {prior}'},
        {'name': 'changeRate', 'expression': f'({current} - {prior}) / nullif({prior}, 0)'}],
    'slice': [between('invoiceDate', '2012-10-01', '2012-11-16'), {'field': 'invoiceDayOfMonth', 'op': '<=', 'value': 15}], 'limit': 1})

q('07-period-coverage', calendar, {'columns': ['yearMonth', 'count(calendarDate) as days', 'sum(dataComplete) as confirmedDays',
    'sum(reportedAmount) as knownAmount'], 'slice': [between('calendarDate', '2012-10-01', '2012-12-01')],
    'groupBy': ['yearMonth'], 'orderBy': ['yearMonth'], 'limit': 5})

q('08-known-period-coverage', calendar, {'columns': ['yearMonth', 'count(calendarDate) as days',
    'sum(dataComplete) as confirmedDays', 'sum(reportedAmount) as amount'],
    'slice': [between('calendarDate', '2012-10-01', '2012-11-16'), {'field': 'dayOfMonth', 'op': '<=', 'value': 15}],
    'groupBy': ['yearMonth'], 'orderBy': ['yearMonth'], 'limit': 5})

q('09-equal-workdays', calendar, {'columns': ['yearMonth', 'count(calendarDate) as workdays', 'sum(reportedAmount) as amount'],
    'slice': [between('calendarDate', '2012-10-01', '2012-11-16'), {'field': 'isWorkday', 'op': '=', 'value': 1},
              {'field': 'workdayIndex', 'op': '<=', 'value': 11}],
    'groupBy': ['yearMonth'], 'orderBy': ['yearMonth'], 'limit': 5})

q('10-leap-day', calendar, {'columns': ['calendarDate', 'dataComplete', 'reportedAmount'],
    'slice': [between('calendarDate', '2012-02-28', '2012-03-02')], 'orderBy': ['calendarDate'], 'limit': 10})

q('11-cross-year-week', calendar, {'columns': ['calendarDate', 'weekStart', 'isoWeekYear', 'isoWeek'],
    'slice': [between('calendarDate', '2012-12-30', '2013-01-03')], 'orderBy': ['calendarDate'], 'limit': 10})

q('12-unconfirmed-with-records', calendar, {'columns': ['calendarDate', 'dataComplete', 'rawAmount', 'reportedAmount'],
    'slice': [between('calendarDate', '2012-11-27', '2012-11-30')], 'orderBy': ['calendarDate'], 'limit': 10})

q('13-year-join-check', calendar, {'columns': ['count(calendarDate) as days', 'sum(rawAmount) as amount', 'sum(rawCount) as bills'],
    'slice': [between('calendarDate', '2012-01-01', '2013-01-01')], 'limit': 1})

q('14-invalid-payment-field', invoice, {'columns': ['paidAt', 'invoiceAmount'], 'limit': 1}, rejected=True)

# The old namespace must be queried explicitly, never silently rebound to the fixture.
path = PROJECT / 'queries/15-original-invoice-regression.json'
save(path, {'columns': ['sum(invoiceAmount) as amount', 'count(invoiceId) as bills'],
            'slice': [between('invoiceDate', '2012-01-01', '2013-01-01')], 'limit': 1})
save(e/'queries'/path.name, json.loads(path.read_text(encoding='utf-8')))
for phase in ['validate', 'execute']:
    call(e, '15-original-invoice-regression-'+phase, 'query', phase, 'ChinookInvoiceQueryModel', '--payload', path, namespace='chinook')

assert hashes() == json.loads((e/'hashes-before.json').read_text(encoding='utf-8'))
save(e/'hashes-after.json', hashes())
print('Original Chinook data and models unchanged.')
