#!/usr/bin/env bash
"""
Run file
"""
import asyncio
import logging
import os

import geopandas as gpd
import pandas as pd

import src.query as qry
import src.write as write
import src.utils as utils
import src.modification as mod
import src.real_estate_cases as rec
import src.arguments as arguments
import src.dataframe_modification as dm


@utils.measure_time
def main(excel_path: str, kinnistu_field: str, out_name: str, intermediate_out: bool = False,
         will_log: bool = False) -> None:
    """Main driver function

    :param excel_path: excel full path to use
    :param kinnistu_field: field name w/ real estates
    :param out_name: output name, won't need extension or full path
    :param intermediate_out: intermediate outputs if the input is too large
    :param will_log: generating logfile
    """
    # Logging and environment
    work_dir = os.getcwd()  # working directory
    utils.log_init(full_path=work_dir, will_log=will_log)

    asyncio.set_event_loop_policy(
        asyncio.WindowsSelectorEventLoopPolicy())  # disable runtimeerror warning

    print("#" * 10)
    print("ALUSTAN")
    print("#" * 10)
    logging.info("Beginning analysis")

    intermediate_dir = os.path.join(work_dir, "outputs")  # intermediate directory
    if intermediate_out is True:
        # Creating an intermediate output directory if it does not exist
        if not os.path.exists(intermediate_dir):
            logging.info("Intermediate directory did not exist, will create")
            os.mkdir(intermediate_dir)

    # Reading in excel and writing out kinnistu
    kinnistu_lst = write.excel_to_df(excel_path, kinnistu_field)
    print(f"Kokku registrinumbreid: {len(kinnistu_lst)}")

    # Chunking results up
    query_chunks = list(utils.chunk_cadastre(estates=kinnistu_lst, chunk_size=100))
    logging.info(f"Created {len(query_chunks)} real estate chunks to query")

    modified_ok_dfs = []  # ok info
    miss_info_dcts = []  # error info
    for count, qc in enumerate(query_chunks):
        print("*" * 5)
        print(f"Alustan {count + 1}/{len(query_chunks)} päringut")
        logging.debug(f"There are {len(qc)} real estate in the chunk")

        # Matching kinnistu ID w/ cadastre (main initinal query, also detects errors)
        ka_miss_info, ka_ok_info = qry.get_cadastre_id_many(qc)
        print("\tKatastri WFS päring")

        intermediate_df_together = []  # collecting intermediate outputs

        # Kinnisasi determine
        if ka_ok_info:
            ka_ok_info_df = rec.handle_kinnisasi(kinnistu_numbers=ka_ok_info, main_directory=work_dir,
                                                 init_lst=kinnistu_lst)
            modified_ok_dfs.append(ka_ok_info_df)  # main append
            intermediate_df_together.append(ka_ok_info_df)  # intermediate append

        else:
            logging.info("\tKinnisasi not found")
            print("\tKinnisasjad puuduvad")

        # Korteriomandid determine
        ko_miss_info = dict()  # filler for intermediate outputs
        if ka_miss_info:
            ko_ok_info_df, ko_miss_info = rec.handle_korteriomandid(kinnistu_numbers=ka_miss_info,
                                                                    main_directory=work_dir,
                                                                    init_lst=kinnistu_lst)

            # Adding to the main list only if results are there
            if isinstance(ko_ok_info_df, pd.DataFrame):
                modified_ok_dfs.append(ko_ok_info_df)  # main append
                intermediate_df_together.append(ko_ok_info_df)  # intermediate append

            # Missing info collection
            miss_info_dcts.append(ko_miss_info)

        else:
            logging.info("There were no potential korteriomand")
            print("\tKorteriomandid puuduvad")

        # INTERMEDIATE OUTPUTS
        if intermediate_df_together and intermediate_out is True:
            i_merged_df = gpd.GeoDataFrame(pd.concat(intermediate_df_together))
            ka_final_dataframe_ok = dm.modify_final_df(i_merged_df, kinnistu_lst, want_shp=False)

            # Writing df to excel
            output_path_i = os.path.join(intermediate_dir, out_name + f"_{count + 1}")

            write.df_to_excel(okay_info_df=ka_final_dataframe_ok, miss_info_dct=ko_miss_info,
                              full_path=output_path_i)
            print(f"\tVahetulemuse asukoht: {output_path_i}.xlsx")

        print(f"Tehtud {count + 1}/{len(query_chunks)} päring")
        print("*" * 5)

    # Merging valid dataframes into one geodataframe if at least some of the results have been found
    if modified_ok_dfs:
        print("Liidan DF-d kokku ühte Excelisse")
        merged_df = gpd.GeoDataFrame(pd.concat(modified_ok_dfs))
        final_dataframe_merged = dm.modify_final_df(merged_df, kinnistu_lst, want_shp=False)

        modified_miss_info = mod.dict_merge(miss_info_dcts)  # modifying missing info

        output_path = os.path.join(work_dir, out_name)
        write.df_to_excel(okay_info_df=final_dataframe_merged, miss_info_dct=modified_miss_info, full_path=output_path)

        print("#" * 10)
        print(f"LÕPETATUD. Tulemus asub asukohas: {output_path}.xlsx")
        print("#" * 10)

    else:
        logging.error("All the inputs were erroneous")
        print("Kõik sisendid olid vigased")


if __name__ == '__main__':
    # Parsing arguments
    args = arguments.set_arguments()
    # Running the main function
    main(excel_path=args.Excel, kinnistu_field=args.Kinnistu, out_name=args.Out, intermediate_out=args.intermediate,
         will_log=args.logi)
