import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from pathlib import Path
import threading


class DataSlot(ttk.Frame):
    """Single row for data loading with dropdowns."""

    def __init__(self, parent, app, initial_role: str = "source"):
        super().__init__(parent)
        self.app = app
        self.role = initial_role
        self.loaded_data = None
        self.loaded_path = None
        self._is_loading = False
        self._data_loaded = False  # Track if data is loaded

        # Configure grid
        self.columnconfigure(5, weight=1)  # File info column expands

        # Role dropdown
        ttk.Label(self, text="Role:").grid(row=0, column=0, padx=(0, 5))

        self.role_var = tk.StringVar(
            value="Source Data" if initial_role == "source" else "Reference Data"
        )
        self.role_combo = ttk.Combobox(
            self,
            textvariable=self.role_var,
            values=["Source Data", "Reference Data"],
            state="readonly",
            width=15,
        )
        self.role_combo.grid(row=0, column=1, padx=(0, 10))
        self.role_combo.bind("<<ComboboxSelected>>", self._on_role_changed)

        # Source dropdown
        ttk.Label(self, text="From:").grid(row=0, column=2, padx=(0, 5))

        self.source_var = tk.StringVar(value="CSV/File")
        self.source_combo = ttk.Combobox(
            self,
            textvariable=self.source_var,
            values=["CSV/File", "Salesforce", "HubSpot"],
            state="readonly",
            width=12,
        )
        self.source_combo.grid(row=0, column=3, padx=(0, 10))
        self.source_combo.bind("<<ComboboxSelected>>", self._on_source_changed)

        # Action button
        self.action_btn = ttk.Button(
            self, text="Browse...", command=self._perform_action, width=10
        )
        self.action_btn.grid(row=0, column=4, padx=(0, 10))

        # File info label
        self.info_label = ttk.Label(
            self, text="No data loaded", foreground="gray", font=("TkDefaultFont", 9)
        )
        self.info_label.grid(row=0, column=5, sticky="w")

        # ID selector (hidden initially)
        self.id_frame = ttk.Frame(self)
        ttk.Label(self.id_frame, text="ID:").pack(side=tk.LEFT, padx=(0, 5))
        self.id_var = tk.StringVar()
        self.id_combo = ttk.Combobox(
            self.id_frame, textvariable=self.id_var, state="readonly", width=20
        )
        self.id_combo.pack(side=tk.LEFT)

        # Set tab order
        self.role_combo.bind("<Tab>", lambda e: self.source_combo.focus_set())
        self.source_combo.bind("<Tab>", lambda e: self.action_btn.focus_set())

    def _on_role_changed(self, event=None):
        """Handle role change - warn if data is loaded."""
        if self._data_loaded:
            if messagebox.askyesno(
                "Change Role?",
                "Changing role will clear the currently loaded data. Continue?",
            ):
                # Clear data
                self._clear_data()
            else:
                # Restore previous value
                old_role = "Source Data" if self.role == "source" else "Reference Data"
                self.role_var.set(old_role)

    def _clear_data(self):
        """Clear loaded data."""
        is_source = self.role_var.get() == "Source Data"
        if is_source:
            self.app.source_df = None
            self.app.src_path = None
        else:
            self.app.ref_df = None
            self.app.ref_path = None

        self._data_loaded = False
        self.loaded_path = None
        self.info_label.config(text="No data loaded", foreground="gray")
        self.id_frame.grid_forget()

        # Update app UI
        if hasattr(self.app, "refresh_ui"):
            self.app.refresh_ui()

    def _on_source_changed(self, event=None):
        """Update button text based on source."""
        source = self.source_var.get()
        if source == "CSV/File":
            self.action_btn.config(text="Browse...")
        elif source == "Salesforce":
            self.action_btn.config(text="Connect...")
        elif source == "HubSpot":
            self.action_btn.config(text="Connect...")

    def _perform_action(self):
        """Execute the appropriate action based on source."""
        if self._is_loading:
            return

        source = self.source_var.get()
        is_source = self.role_var.get() == "Source Data"

        # Lock role once loading starts
        if not self._data_loaded:
            self.role_combo.config(state="disabled")

        if source == "CSV/File":
            self._load_file(is_source)
        elif source == "Salesforce":
            self._load_salesforce(is_source)
        elif source == "HubSpot":
            self._load_hubspot(is_source)

    def _load_file(self, is_source: bool):
        """Load CSV/Excel file."""
        filetypes = [
            ("All Supported", "*.csv;*.xlsx;*.xls"),
            ("CSV files", "*.csv"),
            ("Excel files", "*.xlsx;*.xls"),
            ("All files", "*.*"),
        ]

        filename = filedialog.askopenfilename(
            title=f"Select {self.role_var.get()} File", filetypes=filetypes
        )

        if filename:
            # Set loading state
            self._set_loading_state(True)

            # Load in thread
            def load_async():
                try:
                    # Use app's existing load method
                    self.app._load_data_file(filename, is_source)
                    self.loaded_path = filename
                    self.app.after(0, self._handle_load_complete, True)
                except Exception as e:
                    self.app.after(0, self._handle_load_complete, False, str(e))

            threading.Thread(target=load_async, daemon=True).start()

    def _load_salesforce(self, is_source: bool):
        """Load from Salesforce."""
        # Check if connect method exists
        if not hasattr(self.app, "_connect_to_salesforce"):
            # Create minimal connection method
            def _connect():
                messagebox.showinfo(
                    "Salesforce",
                    "Salesforce connection dialog would appear here.\n"
                    "Import gui_compact_sf for full functionality.",
                )

            self.app._connect_to_salesforce = _connect

        if hasattr(self.app, "sf_integration") and self.app.sf_integration:
            # Show compact dialog
            try:
                from .gui_compact_sf import CompactSalesforceDialog

                dialog = CompactSalesforceDialog(
                    self.app, self.app.sf_integration, is_source
                )
            except ImportError:
                messagebox.showwarning(
                    "Module Not Found",
                    "Salesforce dialog module not found. Please ensure gui_compact_sf.py is installed.",
                )
        else:
            # Need to connect first
            self.app._connect_to_salesforce()

    def _load_hubspot(self, is_source: bool):
        """Placeholder for HubSpot integration."""
        messagebox.showinfo(
            "Coming Soon", "HubSpot integration will be available in the next release!"
        )

    def _set_loading_state(self, loading: bool):
        """Update UI for loading state."""
        self._is_loading = loading
        if loading:
            self.action_btn.config(text="Loading...", state="disabled")
            self.configure(cursor="watch")
        else:
            self._on_source_changed()  # Reset button text
            self.action_btn.config(state="normal")
            self.configure(cursor="")

    def _handle_load_complete(self, success: bool, error: str = None):
        """Handle load completion."""
        self._set_loading_state(False)

        if success:
            self._data_loaded = True
            self._update_info_display()
        else:
            self.role_combo.config(state="readonly")  # Re-enable if failed
            if error:
                messagebox.showerror("Load Error", f"Failed to load file: {error}")

    def _update_info_display(self):
        """Update the info label after data is loaded."""
        role = self.role_var.get()

        if (
            role == "Source Data"
            and hasattr(self.app, "source_df")
            and self.app.source_df is not None
        ):
            df = self.app.source_df
            filename = Path(self.loaded_path).name if self.loaded_path else "Data"
            # Show actual row count (post-filtering)
            actual_rows = len(df)
            self.info_label.config(
                text=f"{filename} ({actual_rows:,} rows)", foreground="black"
            )
            # Show ID selector
            self.id_combo.config(values=list(df.columns))
            if hasattr(self.app, "source_id_var"):
                self.id_combo.config(textvariable=self.app.source_id_var)
            self.id_frame.grid(row=0, column=6, padx=(10, 0))

        elif (
            role == "Reference Data"
            and hasattr(self.app, "ref_df")
            and self.app.ref_df is not None
        ):
            df = self.app.ref_df
            filename = Path(self.loaded_path).name if self.loaded_path else "Data"
            actual_rows = len(df)
            self.info_label.config(
                text=f"{filename} ({actual_rows:,} rows)", foreground="black"
            )
            # Show ID selector
            self.id_combo.config(values=list(df.columns))
            if hasattr(self.app, "ref_id_var"):
                self.id_combo.config(textvariable=self.app.ref_id_var)
            self.id_frame.grid(row=0, column=6, padx=(10, 0))

        # Update mapping trees
        if hasattr(self.app, "_show_mapping_trees"):
            self.app._show_mapping_trees()

    def refresh(self):
        """Refresh display from app state."""
        # Determine role from current data
        if hasattr(self.app, "source_df") and self.app.source_df is not None:
            if self.role == "source":
                self._data_loaded = True
                self.role_combo.config(state="disabled")

        if hasattr(self.app, "ref_df") and self.app.ref_df is not None:
            if self.role == "reference":
                self._data_loaded = True
                self.role_combo.config(state="disabled")

        self._update_info_display()


class CompactDataLoader(ttk.Frame):
    """Ultra-compact data loading interface with dropdowns."""

    def __init__(self, parent, app):
        super().__init__(parent)
        self.app = app

        # Create slots
        self.source_slot = DataSlot(self, app, "source")
        self.source_slot.pack(fill=tk.X, pady=2)

        # Only show reference slot in match mode
        self.ref_slot = DataSlot(self, app, "reference")
        if app.mode.get() == "match":
            self.ref_slot.pack(fill=tk.X, pady=2)

    def update_displays(self):
        """Update both slots after data changes."""
        self.source_slot.refresh()
        self.ref_slot.refresh()

    def update_mode(self, mode: str):
        """Update visibility based on mode."""
        if mode == "duplicate":
            self.ref_slot.pack_forget()
        else:
            self.ref_slot.pack(fill=tk.X, pady=2)
