"""First-order A -> B at constant temperature and volume.

Run: python3 first_order.py --rate 0.1 --initial 1 --duration 60
Writes kinetics.csv. Add --plot for a graph (requires matplotlib).
No third-party packages are needed for CSV output.
"""
import argparse
import csv
import math


def concentrations(initial, rate, time):
    a = initial * math.exp(-rate * time)
    return a, initial - a


def positive(value):
    number = float(value)
    if not math.isfinite(number) or number <= 0:
        raise argparse.ArgumentTypeError('Enter a finite positive number.')
    return number


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--rate', type=positive, default=0.1, help='k in s^-1')
    parser.add_argument('--initial', type=positive, default=1.0, help='[A]0 in mol/L; [B]0=0')
    parser.add_argument('--duration', type=positive, default=60.0, help='Time in seconds')
    parser.add_argument('--output', default='kinetics.csv')
    parser.add_argument('--plot', action='store_true')
    args = parser.parse_args()
    rows = [(t, *concentrations(args.initial, args.rate, t))
            for t in (args.duration * i / 200 for i in range(201))]
    with open(args.output, 'w', newline='', encoding='utf-8') as file:
        writer = csv.writer(file)
        writer.writerow(['time_s', 'A_mol_L', 'B_mol_L'])
        writer.writerows(rows)
    print(f'Half-life: {math.log(2) / args.rate:.4g} s. Saved {args.output}')
    if args.plot:
        try:
            import matplotlib.pyplot as plt
        except ImportError:
            parser.exit(1, 'CSV saved. For plotting, install matplotlib: pip install matplotlib\n')
        plt.plot([r[0] for r in rows], [r[1] for r in rows], label='[A]')
        plt.plot([r[0] for r in rows], [r[2] for r in rows], '--', label='[B]')
        plt.xlabel('Time / s')
        plt.ylabel('Concentration / mol L⁻¹')
        plt.legend()
        plt.tight_layout()
        plt.show()


if __name__ == '__main__':
    main()
