"""
app.py — MainWindow (Odoo-style 2-column layout)
Sidebar (trái) + QStackedWidget (phải).
"""
from PySide6.QtWidgets import (
    QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QStackedWidget,
    QStatusBar, QLabel, QLineEdit, QSizePolicy, QApplication, QMessageBox
)
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QFont, QIcon

from gui.sidebar import Sidebar
from gui.modules.dashboard    import DashboardPage
from gui.modules.revenue_module import RevenuePage
from gui.modules.s1a_module import S1aModule
from gui.modules.hkd_tax_module import HKDTaxPage
from gui.modules.journal_module import JournalPage
from gui.modules.inventory_module import InventoryPage
from gui.modules.customers_module import CustomersPage
from gui.modules.reports_module import ReportsPage
from gui.modules.settings_module import SettingsPage
from gui.modules.pdf_tools_module import PDFToolsPage
from gui.modules.support_payment_module import FeedbackPage, GuidePage, PackagesPage, SupportPage
from gui.theme import MAIN_STYLESHEET

import os
import json
from pathlib import Path
from core.utils import get_resource_path, get_app_data_path
from core.db_init import init_company_db


class AppHeader(QWidget):
    """Global header bar: page icon + breadcrumb + search."""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setObjectName("app_header")

        layout = QHBoxLayout(self)
        layout.setContentsMargins(16, 0, 16, 0)
        layout.setSpacing(12)

        # Page icon (PNG, 56x56, transparent bg)
        self._icon_lbl = QLabel()
        self._icon_lbl.setFixedSize(56, 56)
        self._icon_lbl.setScaledContents(True)
        self._icon_lbl.setStyleSheet("background: transparent; border: none;")
        layout.addWidget(self._icon_lbl)

        # Tiêu đề & Subtitle
        title_box = QVBoxLayout()
        title_box.setContentsMargins(0, 0, 0, 0)
        title_box.setSpacing(2)

        self._title_lbl = QLabel("Tổng Quan")
        self._title_lbl.setObjectName("page_title")
        self._title_lbl.setFont(QFont("Segoe UI", 16, QFont.Weight.Bold))

        self._sub_lbl = QLabel("...")
        self._sub_lbl.setObjectName("page_subtitle")
        self._sub_lbl.setFont(QFont("Segoe UI", 9))

        title_box.addWidget(self._title_lbl)
        title_box.addWidget(self._sub_lbl)

        layout.addLayout(title_box)
        layout.addStretch()

    def set_breadcrumb(self, title: str, subtitle: str, icon_path: str = ""):
        self._title_lbl.setText(title)
        self._sub_lbl.setText(subtitle)
        if icon_path and os.path.exists(icon_path):
            self._icon_lbl.setPixmap(QIcon(icon_path).pixmap(56, 56))
            self._icon_lbl.show()
        else:
            self._icon_lbl.hide()

class MainWindow(QMainWindow):
    """Cửa sổ chính — Odoo-style layout."""

    def __init__(self):
        super().__init__()
        current_version = QApplication.instance().applicationVersion() if QApplication.instance() else "1.0.5"
        self.setWindowTitle(f"🏪  INI HD Hợp Đồng & Doanh Thu  ·  v{current_version}")
        self.setMinimumSize(1200, 720)
        self.resize(1366, 800)

        # ── State ──────────────────────────────────────────
        self.settings_path = get_app_data_path("settings.json")
        self.current_db_path = ""
        self.company_info = {}
        self.company_profiles = []
        self.license_key = ""
        self.is_activated = False
        self.is_cloud_active = False
        self.is_license_blocked = False
        self.plan_type = "free"
        self.license_context = {}
        self.effective_plan_limits = {}
        self.expires_at = None
        self.is_expired = False
        self.license_block_reason = ""
        self._license_block_dialog_shown = False
        self.cloud_license_url = "https://docs.google.com/spreadsheets/d/1NJ3api5KxD41ncWYFNv4SLtsRiMwtQZzeJFZzpio7ek/export?format=csv&gid=0"
        
        # Load settings
        self.load_settings()
        # (check_license sẽ được gọi sau khi status bar được tạo)
        
        # Nếu chưa có db từ settings, mới đi tìm tự động
        if not self.current_db_path:
            self._auto_find_db()
            
        # Đảm bảo schema luôn đầy đủ (tạo bảng products, inventory_movements...)
        if self.current_db_path and os.path.exists(self.current_db_path):
            try:
                init_company_db(self.current_db_path)
            except Exception as e:
                print(f"⚠️ Lỗi khởi tạo schema khi startup: {e}")
            try:
                from core.revenue_db import init_revenue_db
                init_revenue_db(self.current_db_path)
            except Exception as e:
                print(f"⚠️ Lỗi khởi tạo bảng revenue khi startup: {e}")

        # Apply global stylesheet
        self.setStyleSheet(MAIN_STYLESHEET)

        # ── Central widget ─────────────────────────────────
        central = QWidget()
        self.setCentralWidget(central)

        main_layout = QHBoxLayout(central)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)

        # ── Sidebar ────────────────────────────────────────
        self.sidebar = Sidebar()
        self.sidebar.page_changed.connect(self.switch_page)
        main_layout.addWidget(self.sidebar)

        # ── Content column (header + stack) ────────────────
        content_col = QWidget()
        content_col.setObjectName("content_area")
        col_layout = QVBoxLayout(content_col)
        col_layout.setContentsMargins(0, 0, 0, 0)
        col_layout.setSpacing(0)

        # App header
        self.app_header = AppHeader()
        col_layout.addWidget(self.app_header)

        # Stack of pages
        self.stack = QStackedWidget()

        self.pages: dict[str, QWidget] = {
            "dashboard": DashboardPage(),
            "customers": CustomersPage(),
            "revenue":   RevenuePage(),
            "s1a_book":  S1aModule(),
            "hkd_tax":   HKDTaxPage(),
            "pdf_tools": PDFToolsPage(),
            "support":   SupportPage(),
            "guide":     GuidePage(),
            "packages":  PackagesPage(),
            "feedback":  FeedbackPage(),
            "inventory": InventoryPage(),
            "journal":   JournalPage(),
            "reports":   ReportsPage(),
            "settings":  SettingsPage(),
        }

        for page in self.pages.values():
            self.stack.addWidget(page)

        col_layout.addWidget(self.stack)
        main_layout.addWidget(content_col, stretch=1)

        # ── Status bar ─────────────────────────────────────
        self.statusbar = QStatusBar()
        self.setStatusBar(self.statusbar)
        self.status_lbl = QLabel(
            "✅  Hệ thống sẵn sàng  ·  "
            "Ngưỡng miễn thuế HKD 2026: 500.000.000đ/năm  ·  "
            "Phương pháp: Kê khai (thay thuế khoán từ 01/01/2026)"
        )
        self.status_lbl.setFont(QFont("Segoe UI", 8))
        self.statusbar.addWidget(self.status_lbl, 1)

        self.version_lbl = QLabel(f"Phiên bản {current_version}")
        self.version_lbl.setFont(QFont("Segoe UI", 8, QFont.Weight.Bold))
        self.version_lbl.setStyleSheet(
            "padding: 2px 10px; margin-right: 8px; "
            "border-radius: 10px; background: #e0f2fe; color: #0f172a;"
        )
        self.statusbar.addPermanentWidget(self.version_lbl)

        # Kiểm tra bản quyền sau khi status bar đã sẵn sàng
        self.check_license()

        # Show dashboard by default
        self.switch_page("dashboard")

    # Mảng tên hiển thị: "page_id": ("Title", "Subtitle")
    from datetime import date
    _today = date.today().strftime("%d/%m/%Y")
    
    _ASSETS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets")

    PAGE_LABELS = {
        "dashboard": ("Tổng Quan",              f"Sổ tay Hộ Kinh Doanh · Nhóm 1 & 2 · Hôm nay: {_today}",         "icon_dashboard.png"),
        "customers": ("Khách Hàng",             "Danh bạ khách hàng & nhà cung cấp · Tra cứu MST · Dùng cho Hợp Đồng",               "icon_customers.png"),
        "revenue":   ("Sổ Tay Thu / Chi",         f"Ghi nhận tiền vào / tiền ra · Hôm nay: {_today} · Ngưỡng miễn thuế 2026: 500 triệu đ/năm", "icon_revenue.png"),
        "s1a_book":  ("Sổ Doanh Thu",             "Sổ chi tiết doanh thu · Đối với hộ khoán nộp thuế 1 lần/năm · Theo TT 152/2025/TT-BTC", "icon_s1a_book.png"),
        "inventory": ("Kho Hàng & Sản Phẩm",      "Quản lý danh mục hàng hóa, dịch vụ và tồn kho theo Thông tư 88/2021",     "icon_inventory.png"),
        "hkd_tax":   ("Tạo Hợp Đồng",             "Công cụ hỗ trợ soạn thảo và quản lý hợp đồng kinh doanh",    "icon_hkd_tax.png"),
        "pdf_tools": ("Công Cụ PDF", "Xem, in, ký số theo vùng chọn và kiểm tra chữ ký số trên file PDF", "action_pdf_128.png"),
        "support":   ("Hỗ trợ", "Thông tin liên hệ hỗ trợ qua điện thoại và Zalo để xử lý nhanh các vấn đề vận hành", "action_mail_128.png"),
        "guide":     ("Hướng dẫn", "Mở nhanh file guid-contract.html và link tải phần mềm cài đặt", "action_view_128.png"),
        "packages":  ("Gói số", "Xem bảng giá trên website; thanh toán được thực hiện trực tiếp trên web", "action_report1_128.png"),
        "feedback":  ("Phản hồi", "Gửi góp ý, yêu cầu tính năng hoặc lỗi vận hành trực tiếp lên server hỗ trợ", "icon_feedback_pen_chat.svg"),
        "journal":   ("Nhật Ký & Chứng Từ",      "Lưu trữ Sổ kế toán HKD và các loại chứng từ · Theo TT88/2021/TT-BTC",           "icon_journal.png"),
        "reports":   ("Báo Cáo",                  "Xuất báo cáo tài chính, thuế và sổ sách kế toán theo kỳ",                        "icon_reports.png"),
        "settings":  ("Cài Đặt Hệ Thống",          "Cấu hình ứng dụng, đồng bộ Google Sheets và bản quyền phần mềm",                    "icon_settings.png"),
    }

    def switch_page(self, page_id: str):
        """Switch the visible page in the stack."""
        page = self.pages.get(page_id)
        if page:
            self.stack.setCurrentWidget(page)

            # Update breadcrumb with icon
            info = self.PAGE_LABELS.get(page_id, (page_id, "", ""))
            title, sub = info[0], info[1]
            icon_file = info[2] if len(info) > 2 else ""
            icon_path = os.path.join(self._ASSETS, icon_file) if icon_file else ""
            self.app_header.set_breadcrumb(title, sub, icon_path)

            # Try to refresh if page has a refresh method
            if hasattr(page, "refresh") and self.current_db_path:
                page.refresh(self.current_db_path)

            # Special refresh for settings to show activation status
            if page_id == "settings":
                if hasattr(page, "refresh_activation"):
                    page.refresh_activation(self)
                # Populate db path
                if hasattr(page, "inp_active_db") and self.current_db_path:
                    page.inp_active_db.setText(self.current_db_path)
                # Populate gs_url
                if hasattr(page, "inp_gs_url"):
                    gs_url = self.company_info.get("gs_url", "")
                    page.inp_gs_url.setText(gs_url)

        else:
            self.status_lbl.setText(f"⚠️  Trang '{page_id}' chưa được tạo.")

 
    def check_license(self, info_data: dict = None):
        """Kiểm tra bản quyền máy này (Local + Cloud). Nhận diện theo MST."""
        from core.licensing import (
            check_cloud_license,
            format_plan_label
        )
        candidate_info = info_data if isinstance(info_data, dict) else self.company_info
        mst = self._normalize_tax_id((candidate_info or {}).get("tax_id") or self.company_info.get("tax_id", ""))
        if not mst and not self.license_key:
            self.is_cloud_active = False
            self.is_license_blocked = False
            self.plan_type = "free"
            self.expires_at = None
            self.is_expired = False
            self.license_block_reason = ""
            self.cloud_company_info = dict(candidate_info or {})
            self.license_context = {}
            self.effective_plan_limits = {}
            self.cloud_notification = ""
            self.is_activated = False
            self.status_lbl.setText(
                "✅ Hệ thống sẵn sàng  ·  Trạng thái: Gói FREE  ·  "
                "ID: MST: Chưa đăng ký"
            )
            return
        
        # 1. Kiểm tra Cloud (Supabase) - Ưu tiên hàng đầu (theo MST)
        # Pass info_data if we want to sync UP to cloud
        c_active, c_plan, c_expire, c_expired, c_info, c_noti, c_blocked = check_cloud_license(
            mst,
            None,
            info_data,
            self.license_key,
        )
        self.is_cloud_active = c_active
        self.is_license_blocked = bool(c_blocked)
        self.plan_type = c_plan
        self.expires_at = c_expire
        self.is_expired = c_expired
        self.license_block_reason = str(c_noti or "").strip()
        
        # New: Store cloud-synced company info & notification
        self.cloud_company_info = c_info
        self.license_context = c_info.get("_license_context", {}) if isinstance(c_info, dict) else {}
        self.effective_plan_limits = c_info.get("_effective_limits", {}) if isinstance(c_info, dict) else {}
        self.cloud_notification = c_noti

        local_is_valid = False
        self.is_activated = local_is_valid or (self.is_cloud_active and not self.is_expired)
        
        # Build status text
        if self.is_license_blocked:
            status_text = "🔒 BỊ KHÓA TRÊN SERVER"
        elif self.is_expired:
            status_text = "🔴 HẾT HẠN SỬ DỤNG"
        elif self.is_cloud_active:
            exp_date = self.expires_at.strftime("%d/%m/%Y") if self.expires_at else "Vĩnh viễn"
            plan_display = format_plan_label(self.plan_type)
            status_text = f"Bản {plan_display} ✅ (Hạn: {exp_date})"
        elif self.is_activated:
            status_text = "Bản PRO ✅"
        else:
            status_text = "Gói FREE"

        # Hiển thị ID nhận diện (Ưu tiên MST)
        if mst:
            license_id = f"MST: {mst}"
        elif self.license_key:
            key_tail = self.license_key[-8:] if len(self.license_key) > 8 else self.license_key
            license_id = f"Key: ...{key_tail}"
        else:
            license_id = "MST: Chưa đăng ký"
        if self.is_license_blocked:
            blocked_reason = self.license_block_reason or "Bản quyền đã bị khóa hoặc vô hiệu hóa trên server."
            self.status_lbl.setText(
                f"🔒 Trạng thái: {status_text}  ·  ID: {license_id}  ·  {blocked_reason}"
            )
        else:
            self.status_lbl.setText(
                f"✅ Hệ thống sẵn sàng  ·  Trạng thái: {status_text}  ·  "
                f"ID: {license_id}"
            )
        
        # Nếu hết hạn, thông báo ngay
        if self.is_expired:
                        from gui.ui_helpers import show_toast
                        show_toast(self, "Bản quyền của bạn đã hết hạn. Vui lòng liên hệ hỗ trợ để gia hạn!", duration=10000)
        elif self.is_license_blocked and self.isVisible():
            QTimer.singleShot(0, self._enforce_blocked_license)

    def get_license_block_message(self) -> str:
        return self.license_block_reason or "Phần mềm đã bị khóa hoặc vô hiệu hóa trên server. Vui lòng liên hệ quản trị viên để mở khóa."

    def _enforce_blocked_license(self):
        if self._license_block_dialog_shown:
            return
        self._license_block_dialog_shown = True
        QMessageBox.critical(self, "Phần mềm đã bị khóa", self.get_license_block_message())
        app = QApplication.instance()
        if app:
            app.quit()

    def save_license(self, key: str):
        """Kích hoạt và lưu key."""
        self.license_key = key
        self.check_license()
        self.save_settings()

    def load_settings(self):
        """Tải cấu hình từ settings.json."""
        data = {}
        if os.path.exists(self.settings_path):
            try:
                with open(self.settings_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
            except Exception as e:
                print(f"❌ Lỗi load settings: {e}")

        system = data.get("system", {}) if isinstance(data.get("system"), dict) else {}
        self.company_info = data.get("company", {}) if isinstance(data.get("company"), dict) else {}
        self.license_key = system.get("license_key", "")

        try:
            from core.company_manager import get_profiles, get_active_profile

            self.company_profiles = get_profiles()
            active_profile = get_active_profile()
            if active_profile:
                self.company_info = {
                    key: value
                    for key, value in active_profile.items()
                    if key not in {"db_path", "path", "is_active", "name"}
                }
                self.current_db_path = active_profile.get("db_path") or active_profile.get("path") or ""
            if not self.current_db_path:
                self.current_db_path = system.get("last_db_path", "")
        except Exception as e:
            print(f"❌ Lỗi load danh sách công ty: {e}")


    def save_settings(self):
        """Lưu cấu hình vào settings.json."""
        try:
            existing = {}
            if os.path.exists(self.settings_path):
                try:
                    with open(self.settings_path, 'r', encoding='utf-8') as f:
                        existing = json.load(f)
                except Exception:
                    existing = {}

            current_tax_id = self._normalize_tax_id(self.company_info.get("tax_id", ""))
            normalized_profiles = []
            seen_tax_ids = set()
            try:
                from core.company_manager import get_company_db_path_for_tax_id, save_profiles
            except Exception:
                get_company_db_path_for_tax_id = None
                save_profiles = None

            for raw_profile in self.company_profiles:
                if not isinstance(raw_profile, dict):
                    continue
                tax_id = self._normalize_tax_id(raw_profile.get("tax_id", ""))
                if not tax_id or tax_id in seen_tax_ids:
                    continue
                seen_tax_ids.add(tax_id)
                profile = dict(raw_profile)
                profile["tax_id"] = tax_id
                profile["db_path"] = raw_profile.get("db_path") or raw_profile.get("path") or (
                    get_company_db_path_for_tax_id(tax_id) if get_company_db_path_for_tax_id else ""
                )
                profile["is_active"] = (tax_id == current_tax_id)
                normalized_profiles.append(profile)

            if current_tax_id and current_tax_id not in seen_tax_ids:
                normalized_profiles.append(
                    {
                        **self.company_info,
                        "tax_id": current_tax_id,
                        "db_path": self.current_db_path or (
                            get_company_db_path_for_tax_id(current_tax_id) if get_company_db_path_for_tax_id else ""
                        ),
                        "is_active": True,
                    }
                )

            if normalized_profiles and not any(profile.get("is_active") for profile in normalized_profiles):
                normalized_profiles[0]["is_active"] = True

            self.company_profiles = normalized_profiles

            system = dict(existing.get("system", {}) or {})
            system["last_db_path"] = self.current_db_path
            system["license_key"] = self.license_key
            system["active_company_tax_id"] = current_tax_id
            system["company_profiles"] = normalized_profiles

            data = dict(existing)
            data["company"] = self.company_info
            data["system"] = system

            with open(self.settings_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=4, ensure_ascii=False)

            if save_profiles is not None:
                self.company_profiles = save_profiles(self.company_profiles)
        except Exception as e:
            print(f"❌ Lỗi save settings: {e}")

    def _normalize_tax_id(self, tax_id: str) -> str:
        return "".join(ch for ch in str(tax_id or "").strip() if ch.isdigit())

    def get_company_profile_limit(self) -> int:
        from core.licensing import get_effective_plan_limits

        try:
            limits = self.effective_plan_limits or get_effective_plan_limits(self.plan_type, self.license_context)
            limit = int(limits.get("multi_mst", 1) or 1)
        except Exception:
            limit = 1
        return max(limit, 1)

    def upsert_company_profile(self, info_data: dict, activate: bool = True):
        from core.company_manager import get_company_db_path_for_tax_id

        normalized_tax_id = self._normalize_tax_id((info_data or {}).get("tax_id", ""))
        if not normalized_tax_id:
            return False, False, ""

        db_path = get_company_db_path_for_tax_id(normalized_tax_id)
        new_profile = dict(info_data or {})
        new_profile["tax_id"] = normalized_tax_id
        new_profile["db_path"] = db_path

        profiles = [dict(profile) for profile in self.company_profiles if isinstance(profile, dict)]
        existing_index = next(
            (
                idx
                for idx, profile in enumerate(profiles)
                if self._normalize_tax_id(profile.get("tax_id", "")) == normalized_tax_id
            ),
            -1,
        )
        is_new_profile = existing_index < 0

        if is_new_profile:
            profiles.append(new_profile)
        else:
            merged = dict(profiles[existing_index])
            merged.update(new_profile)
            profiles[existing_index] = merged

        if activate:
            for profile in profiles:
                profile["is_active"] = self._normalize_tax_id(profile.get("tax_id", "")) == normalized_tax_id
            self.company_info = dict(new_profile)
            self.company_info.pop("db_path", None)
            self.current_db_path = db_path

        self.company_profiles = profiles
        self.save_settings()
        return True, is_new_profile, db_path

    def activate_company_profile(self, tax_id: str) -> bool:
        from core.company_manager import get_company_db_path_for_tax_id

        normalized_tax_id = self._normalize_tax_id(tax_id)
        if not normalized_tax_id:
            return False

        selected_profile = None
        for profile in self.company_profiles:
            if self._normalize_tax_id(profile.get("tax_id", "")) == normalized_tax_id:
                selected_profile = dict(profile)
                break

        if not selected_profile:
            return False

        for profile in self.company_profiles:
            profile["is_active"] = self._normalize_tax_id(profile.get("tax_id", "")) == normalized_tax_id

        self.company_info = {
            key: value
            for key, value in selected_profile.items()
            if key not in {"db_path", "path", "is_active", "name"}
        }
        self.company_info["tax_id"] = normalized_tax_id
        self.current_db_path = selected_profile.get("db_path") or selected_profile.get("path") or get_company_db_path_for_tax_id(normalized_tax_id)
        self.save_settings()
        self.set_active_db(self.current_db_path)
        self.check_license(self.company_info)
        return True


    def set_db_path(self, db_path: str):
        """Cập nhật DB path, lưu vào info.json & settings.json, refresh tất cả trang."""
        if not db_path or not os.path.exists(db_path):
            return

        try:
            init_company_db(db_path)
        except Exception as e:
            print(f"⚠️ Lỗi cập nhật schema company DB: {e}")

        try:
            from core.revenue_db import init_revenue_db
            init_revenue_db(db_path)
        except Exception as e:
            print(f"⚠️ Lỗi khởi tạo bảng revenue: {e}")

        self.current_db_path = db_path
        self.save_settings()                         # ← lưu vào settings.json

        self.status_lbl.setText(f"📂  Database: {os.path.basename(db_path)}  ·  ✅ Sẵn sàng")
        self.refresh_all_pages()

        # Cập nhật ô hiển thị DB path trong Settings
        settings_page = self.pages.get("settings")
        if settings_page and hasattr(settings_page, "inp_active_db"):
            settings_page.inp_active_db.setText(db_path)

    # Alias — Settings gọi set_active_db
    def set_active_db(self, db_path: str):
        self.set_db_path(db_path)

    def refresh_all_pages(self):
        """Broadcast refresh to all modules."""
        for page in self.pages.values():
            if hasattr(page, "refresh"):
                try:
                    page.refresh(self.current_db_path)
                except Exception as e:
                    print(f"[refresh_all_pages] {type(page).__name__}: {e}")

    def _auto_find_db(self):
        """Tự động tìm file .db đầu tiên trong thư mục companies/ để khởi tạo."""
        comp_dir = get_app_data_path("companies")
        if not os.path.exists(comp_dir):
            return
            
        for root, dirs, files in os.walk(comp_dir):
            for f in files:
                if f.endswith(".db"):
                    self.current_db_path = os.path.join(root, f)
                    return
