##
# @file Validation.py
#
# @brief Script para realizar dos pruebas de evaluación sobre la colección original (no-transformada) y la 
# colección transformada.
#
# El script realiza una prueba de integridad sobre los datos de la colección transformada. 
# Como resultado se obtiene un archivo JSON que contiene todos errores resultantes de las pruebas 
# de integridad por documento transformado. También se obtiene un archivo que entrega un resumen
# de los porcentaje de error detectado por llave de documento original. 
#
# @authors DopamineLabs LTDA
# @date 2025
##

import pprint as pp
from pymongo import MongoClient
import json
from bson.objectid import ObjectId
from tqdm import tqdm
import argparse
from ValidationFunctions import *

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


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        prog="ScappDB validation script",
        description="Checks the transformated collection againts its default types",
        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(
        "--time-series-collection",
        "-tsc",
        required=True,
        help="Collection to check"
    )

    parser.add_argument(
        "--original-collection",
        "-oc",
        required=True,
        help="Original collection"
    )
    
    parser.add_argument(
        "--integrity-collection",
        required=True
    )

    parser.add_argument(
        "--summary-log",
        default="summary_log.json"
    )

    parser.add_argument(
        "--transformation-log",
        help='Output file from transformation process. Used to reconstructed original data from new collection',
        required=True
    )

    args = parser.parse_args()

    # Connect to mongoDB
    client = MongoClient(args.mongo_uri)
    # Access database
    database = client[args.database]
    # Load collections 
    original_collection = database[args.original_collection]
    transformed_collection = database[args.time_series_collection]
    error_collection = database[args.integrity_collection]
    
    # Load JSON with associated ids
    with open(args.transformation_log) as transformation_data:
        transformation_json = json.load(transformation_data)
        
    associated_ids = transformation_json.get('associated_ids')
    transformed_docs = list(transformed_collection.find({}))
    general_progress = tqdm(total=original_collection.count_documents({}), desc="Original docs", position=0)

    for a_id in associated_ids:
        related_ids = set(associated_ids[a_id])
        # Get original doc
        original_document = original_collection.find_one({"_id": ObjectId(a_id)})
        # Evaluation
        compare_documents(original_document, related_ids, transformed_docs, error_collection)
        general_progress.update(1)
    
    # Resume metrics
    summary = {}
    valid_counter = 0
    invalid_counter = 0
    for error_doc in error_collection.find({}):
        integrity_flag = error_doc['integrity']
        evaluation = error_doc['evaluation']
        
        if integrity_flag:
            valid_counter +=1
        else:
            invalid_counter +=1
        
        for key, value in evaluation.items():
            value = value['valid']
            if key not in summary.keys():
                summary[key] = {'valid': 0, 'invalid': 0, 'total': 0, 'valid_percentage': 0}
            
            if value:
                summary[key]['valid'] += 1
            else:
                summary[key]['invalid'] += 1
            
            # Common
            summary[key]['total'] += 1
            summary[key]['valid_percentage'] = 100*(summary[key]['valid']/summary[key]['total'])
    
    general_progress.write(f"[INFO] Integrity summary. Valid docs: {valid_counter} | Invalid docs: {invalid_counter}")
    # Write results onto file
    general_progress.write(f"[INFO] Saving summary onto file.")
    with open(args.summary_log, 'w') as out_file:
        json.dump(summary, out_file, default=lambda x: str(x))

    general_progress.write(f"[INFO] Summary of all error was written onto {args.summary_log}")