"""
Merge operations mixin for pyPhotoAlbum
"""

from PyQt6.QtWidgets import QFileDialog, QMessageBox
from pyPhotoAlbum.decorators import ribbon_action
from pyPhotoAlbum.merge_manager import MergeManager, concatenate_projects
from pyPhotoAlbum.merge_dialog import MergeDialog
from pyPhotoAlbum.project_serializer import load_from_zip, save_to_zip
from pyPhotoAlbum.models import set_asset_resolution_context
from pyPhotoAlbum.project import Project
import tempfile
import os


class MergeOperationsMixin:
    """Mixin providing project merge operations"""

    @ribbon_action(
        label="Merge Projects",
        tooltip="Merge another project file with the current project",
        tab="Home",
        group="File",
    )
    def merge_projects(self):
        """
        Merge another project with the current project.

        If the projects have the same project_id, conflicts will be resolved.
        If they have different project_ids, they will be concatenated.
        """
        # Check if current project has changes
        if self.project.is_dirty():
            reply = QMessageBox.question(
                self,
                "Unsaved Changes",
                "You have unsaved changes in the current project. Save before merging?",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel,
            )

            if reply == QMessageBox.StandardButton.Cancel:
                return
            elif reply == QMessageBox.StandardButton.Yes:
                # Save current project first
                if hasattr(self, "save_project"):
                    self.save_project()

        # Select file to merge
        file_path, _ = QFileDialog.getOpenFileName(
            self, "Select Project to Merge", "", "Photo Album Projects (*.ppz);;All Files (*)"
        )

        if not file_path:
            return

        try:
            # Disable autosave during merge
            if hasattr(self, "_autosave_timer"):
                self._autosave_timer.stop()

            # Load the other project
            with tempfile.TemporaryDirectory() as temp_dir:
                # Load project data
                other_project = load_from_zip(file_path, temp_dir)

                # Serialize both projects for comparison
                our_data = self.project.serialize()
                their_data = other_project.serialize()

                # Check if projects should be merged or concatenated
                merge_manager = MergeManager()
                should_merge = merge_manager.should_merge_projects(our_data, their_data)

                if should_merge:
                    # Same project - merge with conflict resolution
                    self._perform_merge_with_conflicts(our_data, their_data)
                else:
                    # Different projects - concatenate
                    self._perform_concatenation(our_data, their_data)

        except Exception as e:
            QMessageBox.critical(self, "Merge Error", f"Failed to merge projects:\n{str(e)}")
        finally:
            # Re-enable autosave
            if hasattr(self, "_autosave_timer"):
                self._autosave_timer.start()

    def _perform_merge_with_conflicts(self, our_data, their_data):
        """Perform merge with conflict resolution UI"""
        # Detect conflicts
        merge_manager = MergeManager()
        conflicts = merge_manager.detect_conflicts(our_data, their_data)

        if not conflicts:
            # No conflicts - auto-merge
            reply = QMessageBox.question(
                self,
                "No Conflicts",
                "No conflicts detected. Merge projects automatically?",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            )

            if reply != QMessageBox.StandardButton.Yes:
                return

            # Auto-merge non-conflicting changes
            merged_data = merge_manager.apply_resolutions(our_data, their_data, {})
        else:
            # Show merge dialog for conflict resolution
            dialog = MergeDialog(our_data, their_data, self)

            if dialog.exec() != QMessageBox.DialogCode.Accepted:
                QMessageBox.information(self, "Merge Cancelled", "Merge operation cancelled.")
                return

            # Get merged data from dialog
            merged_data = dialog.get_merged_project_data()

        # Apply merged data to current project
        self._apply_merged_data(merged_data)

        QMessageBox.information(
            self,
            "Merge Complete",
            f"Projects merged successfully.\n"
            f"Total pages: {len(merged_data.get('pages', []))}\n"
            f"Resolved conflicts: {len(conflicts)}",
        )

    def _perform_concatenation(self, our_data, their_data):
        """Concatenate two different projects"""
        reply = QMessageBox.question(
            self,
            "Different Projects",
            f"These are different projects:\n"
            f"  • {our_data.get('name', 'Untitled')}\n"
            f"  • {their_data.get('name', 'Untitled')}\n\n"
            f"Concatenate them (combine all pages)?",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
        )

        if reply != QMessageBox.StandardButton.Yes:
            return

        # Concatenate projects
        merged_data = concatenate_projects(our_data, their_data)

        # Apply merged data
        self._apply_merged_data(merged_data)

        QMessageBox.information(
            self,
            "Concatenation Complete",
            f"Projects concatenated successfully.\n" f"Total pages: {len(merged_data.get('pages', []))}",
        )

    def _apply_merged_data(self, merged_data):
        """Apply merged project data to current project"""
        # Create new project from merged data
        new_project = Project()
        new_project.deserialize(merged_data)

        # Replace current project
        self._project = new_project

        # Update asset resolution context
        set_asset_resolution_context(new_project.folder_path)

        # Mark as dirty (has unsaved changes from merge)
        new_project.mark_dirty()

        # Update UI
        if hasattr(self, "gl_widget"):
            self.gl_widget.set_project(new_project)
            self.gl_widget.update()

        if hasattr(self, "status_bar"):
            self.status_bar.showMessage("Merge completed successfully", 3000)
