#!/usr/bin/env python3
"""Analyze Innovatech's synthetic sales CSV. Python 3 standard library only.
Run: python3 analyze.py --input input.csv --output results
All figures describe the supplied synthetic dataset.
"""
import argparse, csv, json
from collections import defaultdict
from datetime import date
from decimal import Decimal, InvalidOperation
from html import escape
from pathlib import Path

def analyze(rows):
    seen, clean, rejected, duplicates = set(), [], [], []
    for number, row in enumerate(rows, 2):
        try:
            when = date.fromisoformat(row['date'])
            amount = Decimal(row['unit_price']) * int(row['quantity'])
            if not row['order_id'] or not amount.is_finite() or amount <= 0:
                raise ValueError('Expected a positive finite amount and order ID')
        except (ValueError, KeyError, InvalidOperation):
            rejected.append(number)
            continue
        if row['order_id'] in seen:
            duplicates.append(number)
            continue
        seen.add(row['order_id'])
        clean.append({**row, 'month': when.strftime('%Y-%m'), 'revenue': amount})
    grouped = defaultdict(lambda: {'revenue': Decimal(0), 'orders': 0})
    for row in clean:
        key = (row['month'], row['channel'])
        grouped[key]['revenue'] += row['revenue']
        grouped[key]['orders'] += 1
    summary = [{'month': month, 'channel': channel, 'orders': values['orders'],
                'revenue_eur': str(values['revenue'].quantize(Decimal('.01')))}
               for (month, channel), values in sorted(grouped.items())]
    totals = {month: sum((r['revenue'] for r in clean if r['month'] == month), Decimal(0))
              for month in sorted({r['month'] for r in clean})}
    months = list(totals)
    change = ((totals[months[-1]] / totals[months[0]] - 1) * 100) if len(months) > 1 and totals[months[0]] else None
    result = {'data_type': 'synthetic teaching records', 'raw_rows': len(rows), 'clean_orders': len(clean),
              'duplicate_rows_removed': len(duplicates), 'invalid_rows_removed': len(rejected),
              'invalid_csv_line_numbers': rejected, 'duplicate_csv_line_numbers': duplicates,
              'total_revenue_eur': str(sum(totals.values(), Decimal(0)).quantize(Decimal('.01'))),
              'monthly_revenue_eur': {m: str(v.quantize(Decimal('.01'))) for m, v in totals.items()},
              'overall_change_percent': str(change.quantize(Decimal('.01'))) if change is not None else None,
              'by_channel': summary}
    return result

def chart(summary):
    maximum = max(Decimal(r['revenue_eur']) for r in summary)
    svg = ['<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 420" role="img" aria-labelledby="title desc">',
           '<title id="title">Revenue by month and channel</title><desc id="desc">Actual script output from synthetic teaching records. Amounts in EUR.</desc>',
           '<rect width="900" height="420" fill="#ffffff"/><text x="32" y="38" font-size="23" font-family="sans-serif" fill="#173b30">Revenue by month and channel · synthetic data</text>']
    for i, row in enumerate(summary):
        y = 95 + i * 76
        width = float(Decimal(row['revenue_eur']) / maximum) * 480
        label = escape(row['month'] + ' · ' + row['channel'])
        svg += [f'<text x="32" y="{y+24}" font-size="17" font-family="sans-serif">{label}</text>',
                f'<rect x="250" y="{y}" width="{width:.1f}" height="36" rx="4" fill="{"#008c76" if row["channel"]=="online" else "#6676a0"}"/>',
                f'<text x="{260+width:.1f}" y="{y+24}" font-size="17" font-family="sans-serif">€{row["revenue_eur"]}</text>']
    svg.append('</svg>')
    return ''.join(svg)

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--input', default='input.csv')
    parser.add_argument('--output', default='results')
    args = parser.parse_args()
    with open(args.input, newline='', encoding='utf-8') as file:
        rows = list(csv.DictReader(file))
    result = analyze(rows)
    out = Path(args.output); out.mkdir(parents=True, exist_ok=True)
    (out/'summary.json').write_text(json.dumps(result, indent=2)+'\n', encoding='utf-8')
    with (out/'channel-summary.csv').open('w', newline='', encoding='utf-8') as file:
        writer = csv.DictWriter(file, fieldnames=['month','channel','orders','revenue_eur']); writer.writeheader(); writer.writerows(result['by_channel'])
    (out/'chart.svg').write_text(chart(result['by_channel']), encoding='utf-8')
    print(json.dumps(result))

if __name__ == '__main__': main()
