"""
:synopsis: Check All and Zip
:authors: Riley Baird (OK), Emma Baker (OK)
"""
import os
import re
from pathlib import Path

import arcpy

from ...lib.misc import unwrap_to_dict, unwrap
from ...lib.validator import NG911Validator


class CheckAllAndZipTool:
    """
    Class describing an ArcGIS Python Toolbox tool: "Export to ZIP".
    """

    def __init__(self):
        """Define the tool (tool name is the name of the class)."""
        self.label = "Check All and Zip"
        self.description = ""
        self.canRunInBackground = False
        self.category = "6 - Submission"

    def getParameterInfo(self):
        """Define parameter definitions"""
        params = [
            arcpy.Parameter(
                displayName="NG911 Geodatabase",
                name="gdb",
                datatype="DEWorkspace",
                parameterType="Required",
                direction="Input"
            ),
            arcpy.Parameter(
                displayName="Output ZIP File",
                name="output_zip_file",
                datatype="DEFile",
                parameterType="Required",
                direction="Output",
            ),
            arcpy.Parameter(
                displayName="Respect Submit",
                name="respect_submit",
                datatype="GPBoolean",
                parameterType="Optional",
                direction="Input"
            ),
            arcpy.Parameter(
                displayName="Overwrite Existing Output",
                name="overwrite",
                datatype="GPBoolean",
                parameterType="Optional",
                direction="Input"
            )
        ]
        return params

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True

    def updateParameters(self, parameters):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""
        param_dict: dict[str, arcpy.Parameter] = {p.name: p for p in parameters}
        param_values = unwrap_to_dict(parameters)
        gdb_path = Path(x) if (x := param_values["gdb"]) else None
        out_file_param = param_dict["output_zip_file"]
        if gdb_path and not out_file_param.altered:
            # Compute default value for output_zip_file if gdb parameter has been set
            param_dict["output_zip_file"].value = str(gdb_path.parent / f"{gdb_path.name}.zip")
        if out_file_param.altered:
            if "." not in unwrap(out_file_param):
                out_file_param.value += ".gdb.zip"

    def updateMessages(self, parameters):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        param_dict: dict[str, arcpy.Parameter] = {p.name: p for p in parameters}
        param_values = unwrap_to_dict(parameters)
        if (out_file_param := param_dict["output_zip_file"]).altered:
            out_file = unwrap(out_file_param) or ""
            if os.path.exists(out_file) and not param_values["overwrite"]:
                out_file_param.setIDMessage("ERROR", 2869, out_file)
            elif not out_file.endswith(".gdb.zip"):
                if out_file.endswith(".zip") or out_file.endswith(".gdb"):
                    out_file_param.value = re.sub(r"\.(zip|gdb)$", ".gdb.zip", out_file)
                else:
                    out_file_param.setErrorMessage("File path must end in '.gdb.zip'.")

    def execute(self, parameters, messages):
        """The source code of the tool."""
        param_dict: dict[str, arcpy.Parameter] = {p.name: p for p in parameters}
        param_values = unwrap_to_dict(parameters)
        gdb = Path(param_values["gdb"])
        output_zip_file = Path(param_values["output_zip_file"])
        respect_submit = bool(param_values["respect_submit"])
        overwrite_zip = bool(param_values["overwrite"])

        with NG911Validator(gdb, respect_submit, use_edit_session=False, messenger=messages, overwrite_error_tables=True, export=True) as validator:
            validator.run_all_routines()
            if validator.has_errors:
                validator.messenger.addWarningMessage(f"Validation of the geodatabase resulted in {validator.error_count} error(s) that must be resolved before submission. The geodatabase will not be zipped.")
                param_dict["output_zip_file"].value = None
                return
            elif validator.has_issues:
                notice_count: int = len([issue for issue in validator.validation_issues if issue.severity == "Notice"])
                warning_count: int = len([issue for issue in validator.validation_issues if issue.severity == "Warning"])
                warning_notice_count_str: str = " and ".join(
                    f"{count} {label}"
                    for count, label
                    in ((warning_count, "warning(s)"), (notice_count, "notice(s)"))
                    if count
                )
                validator.messenger.addMessage(f"There are no validation errors preventing submission, but there are {warning_notice_count_str}.")

            validator.export_to_zip(output_zip_file, overwrite=overwrite_zip)
            param_dict["output_zip_file"].value = str(output_zip_file)

if __name__ == "__main__":
    raise Exception("This module is a dependency of an ArcGIS Python Toolbox and should not be executed directly.")
