import csv
from typing import Counter, Dict, Any
from db_query import get_staters
import os
import shutil
from string import ascii_letters, digits


DAY_NUM = 1
CSV_PATH = f"Names Day {DAY_NUM}.csv"  # CSV containing stater PIN and other info in order of photos
PHOTOS_PATH = f"Day {DAY_NUM} Staters/"  
OUTPUT_PATH = "Renamed/"
OUTPUT_CSV = "photo_stats.csv"
DO_RENAME = True  # Will not do the actual rename step if False
VERBOSE = False  # Output every label as it is created

NAME_FORMAT = "{id} ({name}) - {FNAME}_{LNAME}"

labels = []
ids = []

staters = get_staters()

# Literally just find most common extension in folder (sorry for over-engineering)
extensions = Counter(map(lambda p: os.path.splitext(p)[1], os.listdir(PHOTOS_PATH)))
EXTENSION = extensions.most_common(1)[0][0]


def remove_odd_chars(s: str):
    """Remove chars not in ascii_letters and digits from string s."""
    return "".join(v for v in s if v in ascii_letters + digits + " ")


with open(CSV_PATH) as f:
    names = csv.reader(f)

    names_iter = iter(names)
    headers = next(names_iter)
    for num, row in enumerate(names_iter):

        # Retrieve values for this PIN for use in formatting label
        values: Dict[str, Any] = {
            headers[i].strip(): remove_odd_chars(value) for i, value in enumerate(row)
        }
        if not values["id"]:
            continue
        # Add values from db query to dictionary for use in labels
        db_values = staters[values["id"]]
        values.update(db_values)

        # Check if the PIN is a duplicate
        values["duplicate"] = ids.count(values["id"])
        if values["duplicate"] > 0:
            print(f"*** Duplicate #{values['duplicate']} value found for pin", values, num)
        ids.append(values["id"])

        # Format the File Name
        label = NAME_FORMAT.format_map(values)
        if values["duplicate"]:
            label += f" ({values['duplicate']})"

        label += EXTENSION

        # Assert that stored name matches hand recorded name when present in csv

        db_name = f"{values['FNAME']} {values['LNAME']}"
        if (
            values["name"]
            and values["name"].lower() != db_name.lower()
        ):
            print(f"*** Recorded name does not match PIN name for {label}")

        labels.append((label, values))
        if VERBOSE:
            print(label)


# Rename each file in order from labels
photos = [PHOTOS_PATH + p for p in os.listdir(PHOTOS_PATH) if p.endswith(EXTENSION)]
photos.sort(key=os.path.getctime)

with open(OUTPUT_CSV, "a", newline='') as f:
    output_csv = csv.writer(f)
    # Write header row
    output_csv.writerow(labels[0][1].keys())
    last_photo_num = 0
    for i, photo in enumerate(photos):
        last_photo_num = i
        try:
            label, values = labels[i]
        except IndexError:
            print("*** More photos found than labels in csv")
            raise

        # Write stats for photos
        output_csv.writerow(values.values())

        if DO_RENAME:
            path = f"{OUTPUT_PATH}/{values['CITYNAME']}/"
            try:
                os.makedirs(path)
            except FileExistsError:
                pass
            shutil.copyfile(photo, path + label)

    if last_photo_num < len(labels) - 1:
        print("*** More labels in csv than photos provided")
