﻿"""
SyncFlowController - Orchestration Layer untuk UI Flow Sinkronisasi
Mengatur alur UI, popup, callback untuk mode login dan manual
Menggunakan SyncService sebagai single source of truth untuk business logic
"""

from PySide6.QtCore import QObject, Signal
from pypos.core.base_controller import BaseController
from pypos.modules.sinkronisasi.services.sync_service import SyncService, get_master_tables


class SyncFlowController(BaseController, QObject):
    """
    Controller untuk mengelola alur UI sinkronisasi
    Mendukung dua mode: 'login' (silent) dan 'manual' (dengan popup)
    """

    sync_finished = Signal(bool)
    sync_progress = Signal(int, str, str)
    sync_completed_rows = Signal(int)
    sync_failed_detail = Signal(str)

    def __init__(self, mode='login', view=None, user_info=None, app_controller=None):
        """
        Args:
            mode (str): 'login' atau 'manual'
            view (SinkronView): View untuk menampilkan progress (optional)
            user_info (dict): Informasi user yang sedang login
            app_controller: Reference ke AppController untuk navigasi
        """
        super().__init__()

        # Mode sinkronisasi
        if mode not in ['login', 'manual']:
            raise ValueError("Mode harus 'login' atau 'manual'")
        self.mode = mode
        self.silent_mode = (mode == 'login')

        # View dan app references
        self.view = view
        self.user_info = user_info
        self.app_controller = app_controller

        # Service layer (single source of truth)
        self.sync_service = SyncService()

        # Hubungkan signals dari service ke controller
        self.sync_service.progress_updated.connect(self._handle_progress)
        self.sync_service.sync_completed.connect(self._handle_completion)
        self.sync_service.sync_failed.connect(self._handle_failure)

        self.log_debug(f"[SyncFlowController] Initialized with mode={self.mode}, silent_mode={self.silent_mode}")

    def start(self):
        """
        Memulai proses sinkronisasi
        """
        self.log_info(f"[SyncFlowController] Starting sync in {self.mode} mode")
        force_full = ["per_employee"] if self.mode == "manual" else []
        full_refresh_tables = get_master_tables() if self.mode == "manual" else []
        # edited by glg
        # Guard hasil start agar mode manual tidak diam saat sinkron ditolak (mis. export sedang jalan).
        started = self.sync_service.start_sync(
            tables=full_refresh_tables or None,
            force_full_tables=force_full,
            full_refresh_tables=full_refresh_tables
        )
        if started:
            return True

        reason = (
            "Sinkronisasi belum dapat dimulai karena ada proses sinkronisasi/export yang masih berjalan. "
            "Silakan coba kembali beberapa saat lagi."
        )
        self.log_warning(f"[SyncFlowController] Start sinkron ditunda: {reason}")
        if self.view:
            self.view.update_progress(0, "Sinkronisasi ditunda", reason)
        if not self.silent_mode and self.view is not None:
            self.show_warning("Sinkronisasi Ditunda", reason, view=self.view)
        self.sync_failed_detail.emit(reason)
        self.sync_finished.emit(False)
        return False

    def _handle_progress(self, percent, status, detail_log):
        """
        Handle progress update dari service
        Args:
            percent (int): Progress percentage (0-100)
            status (str): Status message
            detail_log (str): Detail log message
        """
        self.sync_progress.emit(int(percent), str(status or ""), str(detail_log or ""))
        if self.silent_mode:
            # Mode login: hanya print, update dashboard status jika ada
            self.log_debug(f"[Silent Sync] {percent}% - {status}")

            # Update indikator kecil di Dashboard jika dashboard sudah aktif
            if self.app_controller:
                dashboard_window = getattr(self.app_controller, 'dashboard_window', None)
                if dashboard_window is not None:
                    dashboard_window.set_sinkron_status(f"Sinkron {percent}%...")
        else:
            # Mode manual: update view progress
            if self.view:
                self.view.update_progress(percent, status, detail_log)

    def _handle_completion(self, total_rows):
        """
        Handle completion dari service
        Args:
            total_rows (int): Total rows yang berhasil disinkronkan
        """
        success = (total_rows >= 0)
        self.log_info(f"[SyncFlowController] Sync completed: {total_rows} rows, mode={self.mode}")

        if self.view:
            self.view.update_progress(100, "Sinkronisasi selesai.", f"{total_rows} data diperbarui")

        # Tampilkan popup hanya untuk mode manual
        if not self.silent_mode:
            self._show_success_popup(total_rows)

        self.sync_completed_rows.emit(int(total_rows or 0))
        # Emit signal ke parent (bool untuk consistency dengan behavior sebelumnya)
        self.sync_finished.emit(success)

    def _handle_failure(self, error_message):
        """
        Handle failure dari service
        """
        self.log_error(f"[SyncFlowController] Sync failed: {error_message}")

        if self.view:
            self.view.update_progress(0, "Gagal sinkronisasi", error_message)

        # Tampilkan popup error untuk semua mode
        self._show_error_popup(error_message)

        self.sync_failed_detail.emit(str(error_message or ""))
        # Emit signal ke parent
        self.sync_finished.emit(False)

    def _show_success_popup(self, total_rows):
        """
        Tampilkan popup sukses (hanya untuk mode manual)
        Args:
            total_rows (int): Total rows yang berhasil disinkronkan
        """
        if self.view:
            self.show_info(
                "Sinkronisasi Selesai",
                f"Sinkronisasi berhasil diselesaikan. Total {total_rows} data telah diperbarui dari server.",
                view=self.view,
            )

    def _show_error_popup(self, error_message):
        """
        Tampilkan popup error
        """
        parent = self.view if self.view else None
        self.show_error(
            "Sinkronisasi Gagal",
            f"Terjadi kesalahan saat sinkronisasi:\n{error_message}",
            view=parent,
        )

    def stop(self, force=False, wait_timeout_ms=None):
        """
        Hentikan proses sinkronisasi jika sedang berjalan
        """
        if self.sync_service.is_running():
            self.log_info("[SyncFlowController] Stopping sync")
            self.sync_service.stop_sync(force=force, wait_timeout_ms=wait_timeout_ms)

    def is_running(self):
        """
        Cek apakah sinkronisasi sedang berjalan
        """
        return self.sync_service.is_running()
