##
# @file Transformation.py
#
# @brief Script para realizar la transformación de la colección original a la colección transformada.
#
# @authors DopamineLabs LTDA
# @date 2025
##

# Usage Example
# python Transformation.py --database ScappDB --target-collection dummy_data --old-collection dummy_data_old --parameter-collection 
# parameters --log-file log.json


import argparse
from tqdm import tqdm
from pymongo import MongoClient
import time
from TransformationFunctions import document_transformer
from Logger import dump_to_log_file

DEFAULT_MONGO_URI = 'mongodb://localhost:27017/'

if __name__ == '__main__':
    # Define arguments
    parser = argparse.ArgumentParser(
        prog="ScappDB transformation script",
        description="Transforms the provided collection into the requested format and performs data integrity validation",
        epilog="blueOctopus"
    )

    parser.add_argument(
        "--mongo-uri",
        default=DEFAULT_MONGO_URI,
        help=f"Overrides the default URI to connect to mongoDB. Default is {DEFAULT_MONGO_URI}"
    )

    parser.add_argument(
        "--database",
        "-db",
        required=True,
        help="Database name"
    )

    parser.add_argument(
        "--old-collection",
        "-oc",
        required=True,
        help="Old collection name"
    )

    parser.add_argument(
        "--target-collection",
        "-tc",
        required=True,
        help="Name of the collection to migrate"
    )

    parser.add_argument(
        "--parameter-collection",
        "-pc", 
        required=True,
        help="Name of the collection that contains the db parameters"
    )

    parser.add_argument(
        "--log-file",
        "-lf",
        required=False,
        help="File to log the transformation and validation messages",
        default="log.json"
    )

    parser.add_argument(
        '--verbose',
        action='store_true',
        help='Show all prints.'
    )

    args = parser.parse_args()

    # Connect to mongoDB
    print(f"[INFO] Setting up connection with mongoDB at {args.mongo_uri}")
    client = MongoClient(args.mongo_uri)

    # Access database
    database = client[args.database]

    # Load target collection
    current_collection = database[args.target_collection]
    n_docs_current_collection = current_collection.count_documents({})
    print(f"[INFO] There are {n_docs_current_collection} documents on the current collection to be transformed")

    # Rename the current collection
    print(f"[INFO] Renaming the target collection {args.target_collection} to {args.old_collection}")
    current_collection.rename(args.old_collection)
    current_collection = database[args.old_collection]

    
    # Create handle for new time-series collection
    time_series_options = {"timeseries": {
        "timeField": "timestamp",
        "metaField": "camera_id",
        "granularity": "seconds"
        }
    }
    database.create_collection(args.target_collection, **time_series_options)
    new_collection = database[args.target_collection]


    # Transformation error array: save the _id of this documents
    transformation_errors = [] 

    # Transformation associaton: Save the original _id and the resulting _id from new documents
    associated_ids = {}

    # Start the transformation process
    with tqdm(total=n_docs_current_collection, desc='Document progress', position=0) as pbar:
        for doc in current_collection.find({}):
            _id = doc['_id']
            new_docs = document_transformer(doc, args.verbose, pbar)
            if new_docs:
                resulting_ids = new_collection.insert_many(new_docs)
                # Save the ids
                associated_ids[str(_id)] = list(resulting_ids.inserted_ids)
            else:
                # Get id from document
                transformation_errors.append(_id)
                pbar.write(f'[Dataerror] Invalid documment could not be transformed: {doc}')
            pbar.update(1)

    # Save the logs onto file
    print(f'[INFO] Writting errors and associated ids onto file {args.log_file}')
    dump_to_log_file(args.log_file, transformation_errors, associated_ids)

    # updata ScappDB flag
    parameters_collection = database[args.parameter_collection]
    search_query = {'ScappDB_version': {'_id': {'$exists' : True}}}
    parameters_collection.update_one(search_query, {'$set': {'ScappDB_version': '20241118'}}, upsert=True)
    print(f"[INFO] Updating ScappDB version onto {args.parameter_collection}")