#!/usr/bin/env python
# -*- encoding: utf-8

import contextlib
import copy
import datetime as dt
import hashlib
import json
import os
import subprocess
import sys
import tempfile

import boto3
import click


def sha256(s):
    h = hashlib.sha256()
    h.update(s)
    return h.hexdigest()


@contextlib.contextmanager
def edit_miro_vhs_record(miro_id, reason):
    dynamodb = boto3.client("dynamodb")
    s3 = boto3.client("s3")

    resp = dynamodb.get_item(
        TableName="vhs-sourcedata-miro",
        Key={"id": {"S": miro_id}}
    )

    try:
        item = resp["Item"]
    except KeyError:
        raise ValueError(f"Unable to find Miro ID {miro_id!r}")

    existing_record = json.loads(s3.get_object(
        Bucket=item["location"]["M"]["namespace"]["S"],
        Key=item["location"]["M"]["key"]["S"]
    )["Body"].read())

    record = copy.deepcopy(existing_record)
    yield record

    if record == existing_record:
        print("No changes; not uploading a new version")
        return

    username = boto3.client("iam").get_user()["User"]["UserName"]

    record["all_amendment_by"].append(f"aws:{username}")
    record["all_amendment_date"].append(dt.datetime.now().strftime("%d/%m/%Y"))
    record["all_amendment_note"].append(reason)

    json_string = json.dumps(record, separators=(",", ":")).encode("utf8")
    new_key = f"{miro_id}/{sha256(json_string)}.json"
    print(f"Uploading new object as {new_key}")

    item["location"]["M"]["key"]["S"] = new_key
    item["version"]["N"] = str(int(item["version"]["N"]) + 1)

    s3.put_object(
        Bucket=item["location"]["M"]["namespace"]["S"],
        Key=item["location"]["M"]["key"]["S"],
        Body=json_string
    )

    print(f"Updating DynamoDB item {miro_id}")
    dynamodb.put_item(
        TableName="vhs-sourcedata-miro",
        Item=item
    )


@click.command()
@click.option(
    "--miro-id", required=True, prompt="Which Miro record do you want to edit?"
)
@click.option(
    "--reason", required=True, prompt="Why are you editing this Miro record?"
)
def edit_miro_record(miro_id, reason):
    with edit_miro_vhs_record(miro_id=miro_id, reason=reason) as r:
        r_saved = copy.deepcopy(r)
        tmp_path = os.path.join(tempfile.mkdtemp(), f"{miro_id}.json")

        with open(tmp_path, "w") as outfile:
            outfile.write(json.dumps(r, indent=2, sort_keys=True))

        subprocess.check_call(["nano", tmp_path])

        r.clear()
        r.update(json.load(open(tmp_path)))


if __name__ == '__main__':
    # Allows us to omit the '--miro-id' argument and click is still happy.
    if len(sys.argv) == 2:
        sys.argv = [sys.argv[0], "--miro-id", sys.argv[1]]

    edit_miro_record()

@@ -493,24 +493,16 @@
 a-miro%22,
-%0A       
  Key=%7B%22i
@@ -521,16 +521,16 @@
 ro_id%7D%7D%0A
+
     )%0A%0A 
@@ -684,16 +684,25 @@
 n.loads(
+%0A        
 s3.get_o
@@ -700,32 +700,36 @@
  s3.get_object(%0A
+    
         Bucket=i
@@ -768,32 +768,36 @@
 %5D%5B%22S%22%5D,%0A        
+ 
+   
 Key=item%5B%22locati
@@ -817,17 +817,22 @@
 y%22%5D%5B%22S%22%5D
-%0A
+,%0A    
     )%5B%22B
@@ -843,16 +843,21 @@
 %5D.read()
+%0A    
 )%0A%0A    r
@@ -1708,16 +1708,17 @@
 n_string
+,
 %0A    )%0A%0A
@@ -1782,33 +1782,24 @@
 db.put_item(
-%0A        
 TableName=%22v
@@ -1818,24 +1818,16 @@
 a-miro%22,
-%0A       
  Item=it
@@ -1828,21 +1828,16 @@
 tem=item
-%0A    
 )%0A%0A%0A@cli
@@ -1960,21 +1960,16 @@
 .option(
-%0A    
 %22--reaso
@@ -2033,17 +2033,16 @@
 record?%22
-%0A
 )%0Adef ed
@@ -2496,17 +2496,17 @@
  == 
-'
+%22
 __main__
 ':%0A 
@@ -2501,17 +2501,17 @@
 __main__
-'
+%22
 :%0A    # 

Apply auto-formatting rules