from __future__ import annotations

"""Export management module for SecInterp main dialog.

This module handles exporting preview data to various file formats
(PNG, PDF, SVG) and orchestrating data exports (SHP, CSV) via ExportService.
"""

from pathlib import Path
from typing import TYPE_CHECKING

from qgis.core import Qgis, QgsSettings
from qgis.PyQt.QtCore import QSize
from qgis.PyQt.QtGui import QColor
from qgis.PyQt.QtWidgets import QFileDialog

from sec_interp.core.exceptions import ExportError, SecInterpError
from sec_interp.core.performance_metrics import MetricsCollector, PerformanceTimer
from sec_interp.core.services.export_service import ExportService
from sec_interp.exporters import get_exporter
from sec_interp.logger_config import get_logger

from .main_dialog_config import DialogConfig

if TYPE_CHECKING:
    pass

logger = get_logger(__name__)


class ExportManager:
    """Manages all export operations for the dialog.

    This class handles exporting preview data to various file formats
    (PNG, PDF, SVG) and orchestrating data exports (SHP, CSV) via ExportService.
    """

    def __init__(self, dialog: sec_interp.gui.main_dialog.SecInterpDialog):
        """Initialize export manager with reference to parent dialog.

        Args:
            dialog: The :class:`sec_interp.gui.main_dialog.SecInterpDialog` instance

        """
        self.dialog = dialog
        self.metrics = MetricsCollector()
        self.export_service = ExportService(self.dialog.plugin_instance.controller)

    def export_preview(self) -> bool:
        """Export the current preview to a file.

        Returns:
            True if export successful, False otherwise

        """
        self.metrics.clear()

        try:
            with PerformanceTimer("Total Preview Export Time", self.metrics):
                if not self.dialog.current_canvas:
                    self.dialog.message_manager.push_message(
                        self.dialog.tr("Export Error"),
                        self.dialog.tr("No preview available to export. Generate a preview first."),
                        level=Qgis.Warning,
                    )
                    return False

                canvas = self.dialog.current_canvas
                layers = canvas.layers()
                if not layers:
                    self.dialog.message_manager.push_message(
                        self.dialog.tr("Export Error"),
                        self.dialog.tr("No layers to export."),
                        level=Qgis.Warning,
                    )
                    return False

                # Format selection
                settings = QgsSettings()
                last_dir = settings.value("SecInterp/lastExportDir", "", type=str)
                default_path = str(Path(last_dir) / "preview.png") if last_dir else "preview.png"

                file_filter = (
                    "PNG Image (*.png);;"
                    "JPEG Image (*.jpg *.jpeg);;"
                    "PDF Document (*.pdf);;"
                    "SVG Vector (*.svg)"
                )

                output_path, _selected_filter = QFileDialog.getSaveFileName(
                    self.dialog, "Export Preview", default_path, file_filter
                )

                if not output_path:
                    return False

                output_path = Path(output_path)
                settings.setValue("SecInterp/lastExportDir", str(output_path.parent))

                # Determine dimensions and DPI
                ext = output_path.suffix.lower()
                width = self.dialog.preview_widget.canvas.width()
                height = self.dialog.preview_widget.canvas.height()
                dpi = 96

                if ext in [".png", ".jpg", ".jpeg"]:
                    width *= 3
                    height *= 3
                    dpi = 300

                # Prepare settings
                opts = self.dialog.get_preview_options()
                export_params = {
                    "width": width,
                    "height": height,
                    "dpi": dpi,
                    "background_color": QColor(255, 255, 255),
                    "show_legend": opts.get("show_legend", True),
                    "legend_renderer": getattr(
                        self.dialog.plugin_instance, "preview_renderer", None
                    ),
                    "title": "Section Interpretation Preview",
                    "description": "Generated by SecInterp QGIS Plugin",
                    "extent": canvas.extent(),
                }

                map_settings = self.export_service.get_map_settings(
                    layers,
                    export_params["extent"],
                    self.dialog.preview_widget.canvas.size(),
                    export_params["background_color"],
                )

                # Special size override for rasters
                if ext in [".png", ".jpg", ".jpeg"]:
                    map_settings.setOutputSize(QSize(width, height))

                # Execute export
                exporter = get_exporter(ext, export_params)
                success = exporter.export(output_path, map_settings)

                if success:
                    self.dialog.message_manager.push_message(
                        self.dialog.tr("Success"),
                        self.dialog.tr("Preview exported to {}").format(output_path.name),
                        level=Qgis.Success,
                    )
                else:
                    raise ExportError(f"Failed to export preview to {output_path.name}")

                if DialogConfig.LOG_DETAILED_METRICS:
                    logger.info(f"Preview Performance: {self.metrics.get_summary()}")

                return success

        except SecInterpError as e:
            self.dialog.handle_error(e, "Export Error")
            return False
        except Exception as e:
            self.dialog.handle_error(e, "Unexpected Export Error")
            return False

    def export_data(self) -> bool:
        """Orchestrate full data export (SHP/CSV) to the selected folder.

        Returns:
            True if successful, False otherwise

        """
        try:
            # 1. Validate inputs via dialog
            params = self.dialog.plugin_instance._get_and_validate_inputs()
            if not params:
                return False

            # Auto-save current valid settings
            self.dialog.settings_manager.save_settings()

            # Get values for output path (still needed from dialog/values)
            values = self.dialog.get_selected_values()
            output_folder = Path(values["output_path"])

            # 2. Generate data via controller
            self.dialog.preview_widget.results_text.setPlainText("✓ Generating data for export...")
            profile_data, geol_data, struct_data, drillhole_data, _ = (
                self.dialog.plugin_instance.controller.generate_profile_data(params)
            )

            if not profile_data:
                self.dialog.message_manager.push_message(
                    self.dialog.tr("Error"),
                    self.dialog.tr("No profile data generated."),
                    level=Qgis.Critical,
                )
                return False

            num_interps = len(self.dialog.interpretations)
            logger.info(f"Exporting data: found {num_interps} interpretation(s) in dialog.")

            # Extract export settings
            export_options = {
                "exp_topo": values.get("exp_topo", True),
                "exp_geol": values.get("exp_geol", True),
                "exp_struct": values.get("exp_struct", True),
                "exp_drill": values.get("exp_drill", True),
                "exp_interp": values.get("exp_interp", True),
                "drill_3d_traces": values.get("drill_3d_traces", True),
                "drill_3d_intervals": values.get("drill_3d_intervals", True),
                "drill_3d_original": values.get("drill_3d_original", True),
                "drill_3d_projected": values.get("drill_3d_projected", False),
            }

            result_msg = self.export_service.export_data(
                output_folder,
                params,
                profile_data,
                geol_data,
                struct_data,
                drillhole_data,
                interp_data=self.dialog.interpretations,
                export_options=export_options,
            )

            self.dialog.preview_widget.results_text.setPlainText("\n".join(result_msg))
        except SecInterpError as e:
            self.dialog.handle_error(e, "Data Export Error")
            return False
        except Exception as e:
            self.dialog.handle_error(e, "Unexpected Data Export Error")
            return False
        else:
            return True
