import os
import zipfile
import hashlib
from io import BytesIO
from PyQt6.QtWidgets import QFileDialog, QMessageBox
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

public_key_path = os.path.join(".config_app","data","public_key.pem")

with open(public_key_path, "rb") as key_file:
    public_key = serialization.load_pem_public_key(key_file.read())

def calcular_hash_zip_sin_firma(zip_data):
    hash_sha256 = hashlib.sha256()
    with zipfile.ZipFile(zip_data, 'r') as zipf:
        for name in sorted(zipf.namelist()):
            if name == "signature.sig":
                continue
            data = zipf.read(name)
            hash_sha256.update(data)
    return hash_sha256.digest()

def extraer_zip(zip_data, destino):
    os.makedirs(destino, exist_ok=True)
    with zipfile.ZipFile(zip_data) as zip_file:
        for member in zip_file.namelist():
            if member == "signature.sig":
                continue
            zip_file.extract(member, destino)
    print(f"Files extracted to: {destino}")

def open_zip():
    file_dialog = QFileDialog()
    file_dialog.setFileMode(QFileDialog.FileMode.ExistingFiles)
    file_dialog.setNameFilter("ZIP files (*.zip)")
    file_dialog.setViewMode(QFileDialog.ViewMode.List)

    if file_dialog.exec():
        selected_files = file_dialog.selectedFiles()
        if selected_files:
            zip_file_path = selected_files[0]

            if not zip_file_path.lower().endswith(".zip"):
                QMessageBox.warning(None, "Invalid File", "Please select a valid ZIP file.")
                return False

            try:
                with open(zip_file_path, 'rb') as f:
                    zip_data = BytesIO(f.read())

                with zipfile.ZipFile(zip_data) as zip_file:
                    file_list = zip_file.namelist()
                    warning = False

                    if "signature.sig" not in file_list:
                        print("Warning: 'signature.sig' not found in the ZIP.")
                        warning = True
                    else:
                        signature = zip_file.read("signature.sig")
                        file_hash = calcular_hash_zip_sin_firma(zip_data)

                        try:
                            public_key.verify(
                                signature,
                                file_hash,
                                padding.PKCS1v15(),
                                hashes.SHA256()
                            )
                            print("ZIP is valid and correctly signed.")
                            destination = os.path.expanduser(".config_app/templates")
                            extraer_zip(zip_data, destination)
                            return True
                        except Exception as e:
                            print("ZIP is altered or invalid:", e)
                            warning = True

                    if warning:
                        reply = QMessageBox.question(
                            None,
                            "Signature Warning",
                            "This file may be tampered or unofficial.\nDo you want to continue at your own risk?",
                            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
                        )
                        if reply == QMessageBox.StandardButton.Yes:
                            destination = os.path.expanduser(".config_app/templates")
                            extraer_zip(zip_data, destination)
                            return True
                        else:
                            return False

            except Exception as e:
                print(f"Error processing the ZIP file → {e}")
                QMessageBox.critical(None, "Error", "An error occurred while processing the ZIP file.")
                return False
        else:
            return False
    else:
        return False
