# isort: skip_file
import os

os.environ["QT_QPA_PLATFORM"] = "offscreen"
import warnings


def no_futurewarning(message, category, *args, **kwargs):
    if category is FutureWarning:
        return


warnings.showwarning = no_futurewarning

import datetime
import json
import platform
import sys
import traceback
from pathlib import Path

CURRENT_OS = platform.system()
if CURRENT_OS == "Darwin":
    # on macOS, script is launched via QGIS and not python
    current_file_path = Path(os.path.abspath(sys.argv[0]))
else:
    current_file_path = Path(__file__)

current_file_folder = current_file_path.resolve().parents[0]
# path of openlog in QGIS plugins folder (user's profile)
openlog_path = str(current_file_path.resolve().parents[2]) + "/"
sys.path.append(openlog_path)

# path of pyqgis and PyQt
with open(current_file_folder / ".vars.conf", "r") as f:
    lines = f.readlines()
    for line in lines:
        if "PYQGIS_PATH" in line:
            line = line.replace("\n", "")
            pyqgis_lib_path = line.split("=")[1] + "/"
            sys.path.append(pyqgis_lib_path)
            break


# import OpenlogPlugin for adding embedded_external_libs and extensions to path
from openlog.plugin_main import OpenlogPlugin
from qgis.PyQt.QtWidgets import QApplication, QMessageBox

from openlog.datamodel.connection.openlog_connection import (
    Connection,
    OpenLogConnection,
)
from openlog.datamodel.connection.spatialite.spatialite_connection import (
    SpatialiteConnection,
)
from openlog.datamodel.connection.xplordb.xplordb_connection import XplordbConnection
from openlog.datamodel.imports.import_classes import (
    AutomatedImport,
    ImportProfile,
    ImportType,
)
from openlog.gui.import_assay.import_assay import AssayImportWizard
from openlog.gui.import_data.database_import import DatabaseImportWizard, ImportPages
import click


CREDNETIALS_FILE = ".openlog.conf"


def import_one_file(
    connection: OpenLogConnection,
    auto_import: AutomatedImport,
    import_profile: ImportProfile,
    file: str,
) -> tuple[bool, str]:
    """
    Import one file in database.
    Return True is imported, and error messages as JSON.
    """

    # import wizard page (containing DelimitedTextImportWidget)
    if ImportType(import_profile.type) == ImportType.ASSAY:
        wizard = AssayImportWizard(connection)
        IMPORT_WIZARD_PAGE = wizard.assay_import_wizard
    elif ImportType(import_profile.type) == ImportType.COLLAR:
        wizard = DatabaseImportWizard(connection, None, ImportPages.COLLAR)
        IMPORT_WIZARD_PAGE = wizard.import_wizard
    else:
        wizard = DatabaseImportWizard(connection, None, ImportPages.SURVEY)
        IMPORT_WIZARD_PAGE = wizard.import_wizard

    # 1st step : person and dataset
    wizard.person_dataset_import_wizard.person_cb.setCurrentText(auto_import.person)
    wizard.person_dataset_import_wizard.dataset_cb.setCurrentText(auto_import.dataset)

    # 2nd step : choose assay (Optionnal)
    if ImportType(import_profile.type) == ImportType.ASSAY:
        wizard.assay_selection_wizard.assay_selection_rb.setChecked(True)
        wizard.assay_selection_wizard.assay_selection_combo.setCurrentText(
            import_profile.assay_name
        )
        IMPORT_WIZARD_PAGE.initializePage()

    # 3nd step : import csv
    IMPORT_WIZARD_PAGE.dataset_edit.filename_edit.setCurrentText(file)
    IMPORT_WIZARD_PAGE.dataset_edit._source_updated()

    # 4th step : set profile
    params = json.loads(import_profile.parameters)
    IMPORT_WIZARD_PAGE.set_import_parameters(params)

    # 5th step : database summary (Optionnal)
    if ImportType(import_profile.type) == ImportType.ASSAY:
        wizard.assay_database_definition_wizard.initializePage()

    # 6th step : import
    result = wizard.confirmation_page.validatePage()

    return result, json.dumps(IMPORT_WIZARD_PAGE.dataset_edit.messages)


class ConnectionException(Exception):
    """
    Exception to be displayed in scheduler log (before stdout/stderr catching).
    """

    pass


def get_password(host: str, port: int, database: str, user: str) -> str:
    """
    Search for password in home directory.
    """
    # search for conf file
    home_dir = Path.home()
    if CREDNETIALS_FILE not in os.listdir(home_dir):
        raise ConnectionException("Configuration file not found")

    conf_path = home_dir / CREDNETIALS_FILE
    with open(conf_path, "r") as f:
        lines = f.readlines()
    lines = [line.rstrip("\n") for line in lines]
    pattern = ":".join([host, port, database, user])
    pwd = None

    # search in config file entries
    for line in lines:
        if pattern in line:
            pwd = line.split(":")[-1]
            break

    if pwd is None:
        raise ConnectionException("Password not found in configuration file.")

    return pwd


@click.command()
@click.option("--host", type=str)
@click.option("--port", type=str)
@click.option("--db", type=str)
@click.option("--user", type=str)
@click.option("--db-path", type=str)
@click.option("--id", type=str)
@click.option("--dry-run", type=int, default=0)
def main(host, port, db, user, db_path, id, dry_run):

    # test run
    if dry_run == 1:
        return 0

    now = datetime.datetime.now().strftime(format="%Y-%m-%d %H:%M")

    # missing connection infos
    if (host is None or port is None or db is None or user is None) and db_path is None:
        raise ConnectionException("Missing connection informations.")

    # missing automated import
    if id is None:
        raise Exception("Missing import ID.")

    # connection
    if db_path:
        connection = SpatialiteConnection(file_path=db_path, new_file=False)
    else:
        pwd = get_password(host, port, db, user)

        connection = XplordbConnection(
            Connection(user=user, database=db, host=host, port=port, password=pwd)
        )

    # monkeypatch QMessageBox for not blocking execution
    def redirige_message(parent, title, text, *args, **kwargs):
        print(f"[INFO] {title}: {text}")
        return QMessageBox.Ok

    QMessageBox.information = redirige_message
    QMessageBox.warning = redirige_message

    # in macOS, we are already in QgsApplication
    if CURRENT_OS != "Darwin":
        app = QApplication(sys.argv)

    # get automated import and import profile
    auto_import: AutomatedImport = connection.get_imports_iface().get_automated_import(
        id
    )
    import_profile: ImportProfile = connection.get_imports_iface().get_import_profile(
        auto_import.profile
    )

    # capture output in log file
    log_file = auto_import.log_folder + "/openlog_import.log"
    sys.stdout = open(log_file, "a", buffering=1)
    sys.stderr = open(log_file, "a", buffering=1)
    print(now)

    # get source files
    files = os.listdir(auto_import.source_folder)
    files = [file for file in files if ".csv" in file or ".txt" in file]
    files = [auto_import.source_folder + "/" + file for file in files]
    failed_files = []
    for file in files:
        try:
            imported, message_dict = import_one_file(
                connection, auto_import, import_profile, file
            )
            if not imported:
                failed_files.append(file)
                print(f"Error when importing file : {file}")
                print(f"Wizard error : {message_dict}")
        except Exception as exc:
            print("".join(traceback.TracebackException.from_exception(exc).format()))

    # update automated import (run date and counters)
    auto_import.last_run_date = now
    auto_import.run_count += 1
    auto_import.failed_run_count += 0 if len(failed_files) == 0 else 1

    connection.get_imports_iface().update_automated_import(auto_import)

    sys.stdout.close()
    sys.stderr.close()


if __name__ == "__main__":
    try:
        main()
    except SystemExit as e:
        os._exit(0)
