"""Draw Week 9's original synthetic reform comparisons from exact lab CSVs.

Run after lab generation, from the book directory:
    conda run -n research python assets/scripts/build-week9-work-design.py

Known population effects and one realized assignment occupy separate panels.
No normal intervals are inferred from the three independent blocks. The second
figure contains separate analytical examples, not estimated lab outcomes.
"""
from pathlib import Path
import csv
import math
import os
import sys

BOOK = Path(__file__).resolve().parents[2]
REPO = BOOK.parents[1]
LAB = BOOK / 'labs/09-organizational-change-and-work-design'
PROVENANCE = 'ORIGINAL_SYNTHETIC_FACTORIAL_DESIGN_NOT_A_PAPER_REPLICATION'
os.environ.setdefault('MPLCONFIGDIR', str(BOOK / '.mpl-cache'))
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
sys.path.insert(0, str(REPO))
from shared.figure_style import COLORS, apply_style, save_figure, style_axis


def read_and_preserve(relative, target):
    """Retain source bytes, including provenance, before plotting."""
    source = LAB / relative
    destination = BOOK / 'assets/data' / target
    destination.parent.mkdir(parents=True, exist_ok=True)
    destination.write_bytes(source.read_bytes())
    with destination.open(newline='') as stream:
        rows = list(csv.DictReader(stream))
    assert rows and all(row['provenance'] == PROVENANCE for row in rows)
    return rows


def save(fig, stem):
    destination = BOOK / 'assets/figures' / stem
    save_figure(fig, destination.with_suffix('.png'))
    fig.savefig(destination.with_suffix('.pdf'), bbox_inches='tight',
                facecolor='white', metadata={'CreationDate': None, 'ModDate': None})
    plt.close(fig)


def main():
    estimates = read_and_preserve('output/reproduced/dynamic_estimates.csv',
                                  '09-dynamic-estimates.csv')
    truth = read_and_preserve('data/instructor/dynamic_arm_effects.csv',
                              '09-dynamic-arm-effects.csv')
    cells = read_and_preserve('output/diagnose/complementarity_cells.csv',
                              '09-complementarity-cells.csv')
    stocks = read_and_preserve('output/diagnose/maintenance_path.csv',
                               '09-maintenance-path.csv')
    assert len(estimates) == 32 and len(truth) == 16
    periods = [1, 2, 3, 4]
    actual = {(int(r['period']), r['contrast']): float(r['estimate']) for r in estimates}
    known = {(int(r['period']), int(r['tool']), int(r['redesign'])):
             float(r['population_effect_relative_to_00']) for r in truth}
    assert len(actual) == 32 and len(known) == 16
    expected = {(1, 0): [-6, -5, -4, -4], (0, 1): [-1, 1, 2, 3],
                (1, 1): [-3, 4, 9, 12], (0, 0): [0, 0, 0, 0]}
    for arm, path in expected.items():
        assert [known[t, *arm] for t in periods] == path
    for t in periods:
        tool = actual[t, 'tool_without_redesign']
        redesign = actual[t, 'redesign_without_tool']
        interaction = actual[t, 'interaction']
        assert math.isclose(actual[t, 'bundle'], tool + redesign + interaction, abs_tol=1e-8)
        assert math.isclose(actual[t, 'tool_with_redesign'], tool + interaction, abs_tol=1e-8)
        assert math.isclose(actual[t, 'redesign_with_tool'], redesign + interaction, abs_tol=1e-8)
        assert math.isclose(actual[t, 'tool_main'], tool + interaction / 2, abs_tol=1e-8)
        assert math.isclose(actual[t, 'redesign_main'], redesign + interaction / 2, abs_tol=1e-8)
    assert all(float(r['independent_block_se']) >= 0 for r in estimates)

    apply_style()
    fig, axes = plt.subplots(1, 2, figsize=(10.6, 5.5), sharey=True)
    series = [('Tool only', (1, 0), 'tool_without_redesign', 'rust', 's'),
              ('Redesign only', (0, 1), 'redesign_without_tool', 'navy', '^'),
              ('Bundle', (1, 1), 'bundle', 'teal', 'o')]
    for label, arm, contrast, color, marker in series:
        axes[0].plot(periods, [known[t, *arm] for t in periods], label=label,
                     color=COLORS[color], marker=marker, linewidth=2.2, markersize=5.5)
        axes[1].plot(periods, [actual[t, contrast] for t in periods], label=label,
                     color=COLORS[color], marker=marker, linewidth=2.2, markersize=5.5)
    for ax, title in zip(axes, ['Instructor-known population effects', 'Estimates from one assignment']):
        ax.axhline(0, color=COLORS['muted'], linewidth=1, linestyle='--')
        ax.set(title=title, xlabel='Follow-up period', xticks=periods,
               xlim=(.8, 4.2), ylim=(-8, 19))
        style_axis(ax)
    axes[0].set_ylabel('Verified-output units relative to neither intervention')
    axes[1].tick_params(labelleft=True)
    axes[0].legend(loc='upper left', fontsize=10)
    axes[0].annotate('Bundle: 12', (4, 12), xytext=(2.55, 14.7),
                     arrowprops={'arrowstyle': '->', 'color': COLORS['teal']},
                     fontsize=10, color=COLORS['teal'])
    axes[1].annotate(f"Bundle: {actual[4, 'bundle']:.2f}", (4, actual[4, 'bundle']),
                     xytext=(1.5, 16.8), fontsize=10, color=COLORS['teal'],
                     arrowprops={'arrowstyle': '->', 'color': COLORS['teal']})
    fig.text(.5, .095, '12 establishments • 3 independent blocks • baseline-adjusted estimates • no confidence bands',
             ha='center', fontsize=9.5)
    fig.text(.5, .035, 'Original synthetic teaching example • one assignment need not reproduce population effects',
             ha='center', fontsize=10, color=COLORS['muted'])
    fig.tight_layout(rect=(0, .14, 1, 1), w_pad=2)
    save(fig, '09-dynamic-reform-effects')

    arms = [(int(r['tool']), int(r['redesign'])) for r in cells]
    throughput = [float(r['throughput']) for r in cells]
    assert arms == [(0, 0), (1, 0), (0, 1), (1, 1)]
    assert throughput == [10, 10, 10, 16]
    assert [float(r['output']) for r in cells] == [100, 96, 103, 112]
    times = [int(r['period']) for r in stocks]
    assert times == [0, 1, 2, 3, 4]
    neglect = [float(r['no_maintenance']) for r in stocks]
    maintained = [float(r['with_maintenance']) for r in stocks]
    assert all(math.isclose(k, .8**t, abs_tol=1e-10) for t, k in zip(times, neglect))
    assert maintained == [1] * 5
    fig, axes = plt.subplots(1, 2, figsize=(10.6, 5.5))
    colors = [COLORS[c] for c in ['slate', 'rust', 'navy', 'teal']]
    bars = axes[0].bar(range(4), throughput, width=.62, color=colors)
    axes[0].bar_label(bars, labels=['10', '10', '10', '16'], padding=5, fontsize=11)
    axes[0].set(title='A bottleneck needs both changes', ylabel='Finished items per period',
                xticks=range(4), xticklabels=['Neither\n00', 'Tool only\n10', 'Redesign only\n01', 'Bundle\n11'],
                ylim=(0, 19), yticks=[0, 5, 10, 15])
    axes[0].text(.04, .92, r'$Q=\min(C_{draft},C_{review})$',
                 transform=axes[0].transAxes, fontsize=11)
    axes[1].plot(times, maintained, marker='o', color=COLORS['teal'], linewidth=2.2,
                 label='Maintenance = 0.2 per period')
    axes[1].plot(times, neglect, marker='s', color=COLORS['rust'], linewidth=2.2,
                 label='No maintenance')
    axes[1].set(title='A routine can decay after launch', xlabel='Periods since initial stock of 1',
                ylabel='Organizational stock (normalized units)', xticks=times,
                xlim=(-.1, 4.45), ylim=(0, 1.25))
    axes[1].text(3.15, .31, '0.4096', color=COLORS['rust'], fontsize=10)
    axes[1].legend(loc='lower left', fontsize=9)
    axes[1].text(.04, .92, r'$k_{t+1}=0.8k_t+u_t$',
                 transform=axes[1].transAxes, fontsize=11)
    for ax in axes:
        style_axis(ax)
    fig.text(.5, .095, 'Separate analytical examples: capacity gains precede costs; maintaining routines consumes resources.',
             ha='center', fontsize=9.5)
    fig.text(.5, .035, 'Original synthetic teaching examples • known model quantities, not intervention estimates',
             ha='center', fontsize=10, color=COLORS['muted'])
    fig.tight_layout(rect=(0, .14, 1, 1), w_pad=3)
    save(fig, '09-bottlenecks-and-maintenance')
    print('PASS: four exact CSV inputs; dynamic contrast identities and analytical paths checked; two PNG/PDF pairs saved.')


if __name__ == '__main__':
    main()
