"""
A dialog that allows journalists to export conversations or transcripts to the
Whistleflow View VM. This is a clone of FileDialog.
"""

import datetime
import logging
from gettext import gettext as _

from PyQt5.QtCore import QSize, pyqtSlot

from securedrop_client.export_status import ExportError, ExportStatus
from securedrop_client.gui.base import ModalDialog, SecureQLabel

from ....export import Export

logger = logging.getLogger(__name__)


class WhistleflowDialog(ModalDialog):
    PASSPHRASE_LABEL_SPACING = 0.5
    NO_MARGIN = 0
    FILENAME_WIDTH_PX = 260

    def __init__(self, device: Export, summary: str, file_locations: list[str]) -> None:
        super().__init__()
        self.setStyleSheet(self.DIALOG_CSS)

        self._device = device
        self._file_locations = file_locations
        self.file_name = SecureQLabel(
            summary, wordwrap=False, max_length=self.FILENAME_WIDTH_PX
        ).text()
        # Hold onto the error status we receive from the Export VM
        self.error_status: ExportStatus | None = None

        # Connect device signals to slots
        self._device.whistleflow_preflight_check_succeeded.connect(
            self._on_export_preflight_check_succeeded
        )
        self._device.whistleflow_preflight_check_failed.connect(
            self._on_export_preflight_check_failed
        )
        self._device.export_completed.connect(self._on_export_succeeded)

        # # For now, connect both success and error signals to close the print dialog.
        self._device.whistleflow_call_failure.connect(self._on_export_failed)
        self._device.whistleflow_call_success.connect(self._on_export_succeeded)

        # Connect parent signals to slots
        self.continue_button.setEnabled(False)
        self.continue_button.clicked.connect(self._run_preflight)

        # Dialog content
        self.starting_header = _(
            "Preparing to export:<br />" '<span style="font-weight:normal">{}</span>'
        ).format(self.file_name)
        self.ready_header = _(
            "Ready to export:<br />" '<span style="font-weight:normal">{}</span>'
        ).format(self.file_name)
        self.success_header = _("Export successful")
        self.error_header = _("Export failed")
        self.starting_message = _(
            "<h2>Understand the risks before exporting files</h2>"
            "<b>Malware</b>"
            "<br />"
            "This workstation lets you open files securely. If you open files on another "
            "computer, any embedded malware may spread to your computer or network. If you are "
            "unsure how to manage this risk, please print the file, or contact your "
            "administrator."
            "<br /><br />"
            "<b>Anonymity</b>"
            "<br />"
            "Files submitted by sources may contain information or hidden metadata that "
            "identifies who they are. To protect your sources, please consider redacting files "
            "before working with them on network-connected computers."
        )
        self.generic_error_message = _("See your administrator for help.")
        self.success_message = _(
            "Remember to be careful when working with files outside of your Workstation machine."
        )

        self._show_starting_instructions()
        self.start_animate_header()
        self._run_preflight()

    def _show_starting_instructions(self) -> None:
        self.header.setText(self.starting_header)
        self.body.setText(self.starting_message)
        self.adjustSize()

    def _send_to_whistleflow(self) -> None:
        timestamp = datetime.datetime.now().isoformat()
        self._device.send_files_to_whistleflow(f"export-{timestamp}.tar", self._file_locations)

    def _show_success_message(self) -> None:
        self.continue_button.clicked.disconnect()
        self.continue_button.clicked.connect(self.close)
        self.header.setText(self.success_header)
        self.continue_button.setText(_("DONE"))
        self.body.setText(self.success_message)
        self.cancel_button.hide()
        self.error_details.hide()
        self.header_line.show()
        self.body.show()
        self.adjustSize()

    def _show_generic_error_message(self) -> None:
        self.continue_button.clicked.disconnect()
        self.continue_button.clicked.connect(self.close)
        self.continue_button.setText(_("DONE"))
        self.header.setText(self.error_header)
        self.body.setText(  # nosemgrep: semgrep.untranslated-gui-string
            f"{self.error_status}: {self.generic_error_message}"
        )
        self.error_details.hide()
        self.header_line.show()
        self.body.show()
        self.adjustSize()

    @pyqtSlot()
    def _run_preflight(self) -> None:
        self._device.run_whistleflow_preflight_checks()

    @pyqtSlot()
    def _export_file(self, checked: bool = False) -> None:
        self.start_animate_activestate()
        self.cancel_button.setEnabled(False)
        self._device.send_files_to_whistleflow(self.file_name, self._file_locations)

    @pyqtSlot()
    def _on_export_preflight_check_succeeded(self) -> None:
        # If the continue button is disabled then this is the result of a background preflight check
        self.stop_animate_header()
        self.header_icon.update_image("savetodisk.svg", QSize(64, 64))
        self.header.setText(self.ready_header)
        if not self.continue_button.isEnabled():
            self.continue_button.clicked.disconnect()
            self.continue_button.clicked.connect(self._send_to_whistleflow)
            self.continue_button.setEnabled(True)
            self.continue_button.setFocus()
            return

        self._send_to_whistleflow()

    @pyqtSlot(object)
    def _on_export_preflight_check_failed(self, error: ExportError) -> None:
        self.stop_animate_header()
        self.header_icon.update_image("savetodisk.svg", QSize(64, 64))

    @pyqtSlot()
    def _on_export_succeeded(self) -> None:
        self.stop_animate_activestate()
        self._show_success_message()

    @pyqtSlot(object)
    def _on_export_failed(self, error: ExportError) -> None:
        self.stop_animate_activestate()
        self.cancel_button.setEnabled(True)
        logger.error(error.status)
