"""
import_dialog.py — Dialog Import Excel hàng loạt (QDialog)

Hỗ trợ:
  • Chọn file DB công ty (.db)
  • Chọn file Excel (.xlsx)
  • Dry-run (kiểm tra không ghi DB)
  • Tải template mẫu
  • Chạy import trong QThread (không đóng băng UI)
  • Hiện kết quả chi tiết
"""
from __future__ import annotations

import os
import sys
import traceback
from pathlib import Path
from typing import Optional

from PySide6.QtWidgets import (
    QDialog, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
    QLineEdit, QCheckBox, QTextEdit, QProgressBar, QFileDialog,
    QGroupBox, QGridLayout, QMessageBox, QFrame, QSizePolicy,
    QTabWidget, QApplication
)
from PySide6.QtCore import Qt, QThread, Signal
from PySide6.QtGui import QFont, QColor
from gui.ui_helpers import show_toast

# ─── đảm bảo src/ trong sys.path ──────────────────────────────────────────────
_SRC = Path(__file__).resolve().parents[2]      # src/
_ROOT = _SRC.parent                             # Accountant/
if str(_SRC) not in sys.path:
    sys.path.insert(0, str(_SRC))


# ══════════════════════════════════════════════════════════════════════
#  Worker thread — chạy import không block GUI
# ══════════════════════════════════════════════════════════════════════
class ImportWorker(QThread):
    """Chạy batch_import.import_from_excel trong thread riêng."""

    finished = Signal(dict)   # {"success": N, "errors": [...]}
    error    = Signal(str)    # exception message

    def __init__(self, db_path: str, excel_path: str, dry_run: bool, replace: bool = False, sheet_name: Optional[str] = None):
        super().__init__()
        self.db_path    = db_path
        self.excel_path = excel_path
        self.dry_run    = dry_run
        self.replace    = replace
        self.sheet_name = sheet_name

    def run(self):
        try:
            from core.batch_import import import_from_excel
            result = import_from_excel(
                db_path    = self.db_path,
                excel_path = self.excel_path,
                dry_run    = self.dry_run,
                replace    = self.replace,
                sheet_name = self.sheet_name,
            )
            self.finished.emit(result)
        except Exception:
            self.error.emit(traceback.format_exc())


# ══════════════════════════════════════════════════════════════════════
#  Dialog chính
# ══════════════════════════════════════════════════════════════════════
class ImportDialog(QDialog):
    """Dialog Import Excel hàng loạt."""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("📥  Import Excel — Chứng Từ Hàng Loạt")
        self.setMinimumWidth(680)
        self.setMinimumHeight(560)
        self.resize(720, 600)
        self._worker: ImportWorker | None = None
        self._build_ui()

        # Pre-fill from Parent (MainWindow)
        main = self.window()
        if hasattr(main, "current_db_path") and main.current_db_path:
            self.inp_db.setText(main.current_db_path)

    # ── Xây dựng giao diện ──────────────────────────────────────────
    def _build_ui(self):
        root = QVBoxLayout(self)
        root.setSpacing(14)
        root.setContentsMargins(20, 20, 20, 20)

        # ── Tiêu đề ─────────────────────────────────────────────────
        title = QLabel("📥  Import Chứng Từ Từ Excel")
        title.setFont(QFont("Segoe UI", 15, QFont.Weight.Bold))
        root.addWidget(title)

        subtitle = QLabel(
            "Nhập hàng loạt bút toán kế toán từ file .xlsx theo đúng template mẫu."
        )
        subtitle.setStyleSheet("color: #64748b; font-size: 12px;")
        root.addWidget(subtitle)

        sep = QFrame()
        sep.setFrameShape(QFrame.Shape.HLine)
        sep.setStyleSheet("color: #e2e8f0;")
        root.addWidget(sep)

        # ── Tabs ─────────────────────────────────────────────
        self.tabs = QTabWidget()
        self.tabs.addTab(self._build_file_tab(), "📂  Nhập từ tệp (.xlsx)")
        self.tabs.addTab(self._build_cloud_tab(), "☁️  Google Spreadsheets")
        root.addWidget(self.tabs)

        # ── Tuỳ chọn ────────────────────────────────────────────────
        grp_opt = QGroupBox("2.  Tuỳ chọn")
        grp_opt.setFont(QFont("Segoe UI", 10, QFont.Weight.Bold))
        opt_layout = QVBoxLayout(grp_opt)
        opt_layout.setContentsMargins(16, 10, 16, 10)
        opt_layout.setSpacing(8)

        self.chk_dry = QCheckBox(
            "🔍  Kiểm tra trước (Dry-run) — Chỉ validate, KHÔNG ghi vào database"
        )
        self.chk_dry.setChecked(True)
        self.chk_dry.setFont(QFont("Segoe UI", 9))
        opt_layout.addWidget(self.chk_dry)

        root.addWidget(grp_opt)

        # ── Nút hành động ───────────────────────────────────────────
        btn_row = QHBoxLayout()
        btn_row.setSpacing(10)

        self.btn_template = QPushButton("📄  Tải template mẫu")
        self.btn_template.setFixedHeight(38)
        self.btn_template.setToolTip(
            "Tạo file Excel mẫu với header đúng định dạng và dữ liệu ví dụ"
        )
        self.btn_template.clicked.connect(self._on_download_template)

        self.btn_import = QPushButton("▶  Bắt đầu Import")
        self.btn_import.setFixedHeight(38)
        self.btn_import.setFont(QFont("Segoe UI", 9, QFont.Weight.Bold))
        self.btn_import.clicked.connect(self._on_import)

        self.btn_close = QPushButton("✖  Đóng")
        self.btn_close.setFixedHeight(38)
        self.btn_close.clicked.connect(self.close)

        btn_row.addWidget(self.btn_template)
        btn_row.addStretch()
        btn_row.addWidget(self.btn_import)
        btn_row.addWidget(self.btn_close)
        root.addLayout(btn_row)

        # ── Progress ─────────────────────────────────────────────────
        self.progress = QProgressBar()
        self.progress.setRange(0, 0)   # indeterminate
        self.progress.setFixedHeight(6)
        self.progress.setVisible(False)
        self.progress.setStyleSheet(
            "QProgressBar { border: none; background: #e2e8f0; border-radius: 3px; }"
            "QProgressBar::chunk { background: #1a56db; border-radius: 3px; }"
        )
        root.addWidget(self.progress)

        # ── Kết quả ──────────────────────────────────────────────────
        grp_res = QGroupBox("3.  Kết quả")
        grp_res.setFont(QFont("Segoe UI", 10, QFont.Weight.Bold))
        res_layout = QVBoxLayout(grp_res)
        res_layout.setContentsMargins(10, 8, 10, 10)

        self.txt_result = QTextEdit()
        self.txt_result.setReadOnly(True)
        self.txt_result.setFont(QFont("Consolas", 9))
        self.txt_result.setMinimumHeight(160)
        self.txt_result.setPlaceholderText(
            "Kết quả import sẽ hiện ở đây sau khi chạy...\n\n"
            "Cột bắt buộc trong Excel: NgayCT, LoaiCT, DienGiai, TaiKhoanNo, TaiKhoanCo, SoTien\n"
            "Cột tuỳ chọn: SoCT, DoiTuong, MaDoiTac, GhiChu"
        )
        res_layout.addWidget(self.txt_result)
        root.addWidget(grp_res)

    def _build_file_tab(self) -> QWidget:
        """Giao diện chọn file truyền thống."""
        w = QWidget()
        layout = QVBoxLayout(w)
        layout.setContentsMargins(0, 15, 0, 15)

        grp_files = QGroupBox("1.  Chọn tệp")
        grp_files.setFont(QFont("Segoe UI", 10, QFont.Weight.Bold))
        grid = QGridLayout(grp_files)
        grid.setContentsMargins(16, 14, 16, 14)
        grid.setSpacing(10)
        grid.setColumnStretch(1, 1)

        # DB công ty
        lbl_db = QLabel("Database công ty (.db):")
        lbl_db.setFont(QFont("Segoe UI", 9))
        self.inp_db = QLineEdit()
        self.inp_db.setPlaceholderText("Chọn file .db trong thư mục companies/...")
        self.inp_db.setFixedHeight(36)
        btn_db = QPushButton("📂 Chọn")
        btn_db.setFixedSize(80, 36)
        btn_db.clicked.connect(self._pick_db)
        grid.addWidget(lbl_db,       0, 0)
        grid.addWidget(self.inp_db,  0, 1)
        grid.addWidget(btn_db,       0, 2)

        # File Excel
        lbl_xl = QLabel("File Excel (.xlsx):")
        lbl_xl.setFont(QFont("Segoe UI", 9))
        self.inp_xl = QLineEdit()
        self.inp_xl.setPlaceholderText("Chọn file Excel cần import...")
        self.inp_xl.setFixedHeight(36)
        btn_xl = QPushButton("📂 Chọn")
        btn_xl.setFixedSize(80, 36)
        btn_xl.clicked.connect(self._pick_excel)
        grid.addWidget(lbl_xl,      1, 0)
        grid.addWidget(self.inp_xl, 1, 1)
        grid.addWidget(btn_xl,      1, 2)

        layout.addWidget(grp_files)
        layout.addStretch()
        return w

    def _build_cloud_tab(self) -> QWidget:
        """Giao diện dán link Google Sheets."""
        w = QWidget()
        layout = QVBoxLayout(w)
        layout.setContentsMargins(0, 15, 0, 15)

        grp_gs = QGroupBox("1.  Link Google Spreadsheets")
        grp_gs.setFont(QFont("Segoe UI", 10, QFont.Weight.Bold))
        vbox = QVBoxLayout(grp_gs)
        vbox.setContentsMargins(16, 14, 16, 14)
        vbox.setSpacing(10)

        lbl = QLabel("Dán link Google Sheets của bạn vào đây:")
        lbl.setFont(QFont("Segoe UI", 9))
        self.inp_gs_url = QLineEdit()
        self.inp_gs_url.setPlaceholderText("https://docs.google.com/spreadsheets/d/...")
        self.inp_gs_url.setFixedHeight(36)

        lbl_sheet = QLabel("Tên Sheet (Tab) cần nạp (để trống sẽ lấy Sheet đầu tiên):")
        lbl_sheet.setFont(QFont("Segoe UI", 9))
        self.inp_gs_sheet = QLineEdit()
        self.inp_gs_sheet.setPlaceholderText("Ví dụ: Tháng 05-2026 hoặc ChungTu")
        self.inp_gs_sheet.setFixedHeight(36)

        vbox.addWidget(lbl)
        vbox.addWidget(self.inp_gs_url)
        vbox.addWidget(lbl_sheet)
        vbox.addWidget(self.inp_gs_sheet)

        tip = QLabel(
            "💡 Lưu ý: Hãy đảm bảo file đã được 'Chia sẻ' với chế độ 'Bất kỳ ai có liên kết đều có thể xem'."
        )
        tip.setStyleSheet("color: #4b5563; font-style: italic; font-size: 11px;")
        vbox.addWidget(tip)

        layout.addWidget(grp_gs)
        layout.addStretch()
        return w

    # ── File pickers ────────────────────────────────────────────────
    def _pick_db(self):
        start = str(_ROOT / "companies")
        path, _ = QFileDialog.getOpenFileName(
            self, "Chọn database công ty", start, "SQLite DB (*.db)"
        )
        if path:
            self.inp_db.setText(path)
            # Sync to main window immediately
            main = self.window()
            if hasattr(main, "set_db_path"):
                main.set_db_path(path)

    def _pick_excel(self):
        start = str(_ROOT / "tmp")
        path, _ = QFileDialog.getOpenFileName(
            self, "Chọn file Excel", start, "Excel Files (*.xlsx)"
        )
        if path:
            self.inp_xl.setText(path)

    # ── Tải template ────────────────────────────────────────────────
    def _on_download_template(self):
        out_dir = _ROOT / "tmp"
        out_dir.mkdir(parents=True, exist_ok=True)
        save_path = str(out_dir / "import_template.xlsx")

        try:
            from core.batch_import import create_import_template
            create_import_template(save_path)
            self.inp_xl.setText(save_path)
            show_toast(self.window(), "Đã tạo file template mẫu thành công!")
        except Exception as e:
            QMessageBox.critical(self, "❌  Lỗi", f"Không thể tạo template:\n{e}")

    # ── Import ───────────────────────────────────────────────────────
    def _on_import(self):
        db_path = self.inp_db.text().strip()

        # Determine import source
        if self.tabs.currentIndex() == 1: # Google Sheets Tab
            gs_url = self.inp_gs_url.text().strip()
            sheet_name = self.inp_gs_sheet.text().strip() or None
            if not gs_url:
                QMessageBox.warning(self, "⚠️", "Vui lòng dán link Google Sheets.")
                return

            # Download file
            tmp_dir = _ROOT / "tmp"
            tmp_dir.mkdir(parents=True, exist_ok=True)
            xl_path = str(tmp_dir / "gsheets_download.xlsx")

            self.txt_result.clear()
            self.txt_result.append("⏳  Đang kết nối Cloud & tải dữ liệu...")

            from core.batch_import import download_gsheets_as_xlsx
            if not download_gsheets_as_xlsx(gs_url, xl_path):
                QMessageBox.critical(self, "❌", "Không thể tải Google Sheets. Hãy kiểm tra lại link và quyền chia sẻ.")
                return

            # --- KIỂM TRA NỘI DUNG SHEET ---
            import openpyxl
            wb = openpyxl.load_workbook(xl_path, data_only=True)
            ws = wb.active
            has_data = ws.max_row > 1 # Vượt quá header

            if not has_data:
                res = QMessageBox.question(
                    self, "📥 Sheet trống",
                    "Google Sheet này đang trống.\n\n"
                    "Bản muốn ĐẨY (Export) dữ liệu chứng từ hiện tại của máy lên để dán vào Sheet này không?",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
                )
                if res == QMessageBox.StandardButton.Yes:
                    self._on_export_to_clipboard(db_path)
                return
            else:
                res = QMessageBox.warning(
                    self, "⚠️ Cảnh báo thay thế",
                    "Google Sheet có dữ liệu.\n\n"
                    "Dữ liệu này sẽ THAY THẾ hoàn toàn tất cả chứng từ hiện có trong phần mềm.\n"
                    "Cả bảng 'Chứng từ' (Journal) và 'Chi tiết' (Journal Items) sẽ bị xóa trước khi nạp mới.\n\n"
                    "Bạn có chắc chắn muốn thực hiện không?",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
                )
                if res != QMessageBox.StandardButton.Yes:
                    return
                # Nếu Yes, chúng ta sẽ chạy worker với replace=True
                self._run_import_worker(db_path, xl_path, dry_run=False, replace=True, sheet_name=sheet_name)
                return

            self.inp_xl.setText(xl_path) # Update for display
            # Nếu có dữ liệu và không replace, vẫn chạy bình thường (nạp thêm)
            self._run_import_worker(db_path, xl_path, dry_run=self.chk_dry.isChecked(), replace=False, sheet_name=sheet_name)
        else:
            xl_path = self.inp_xl.text().strip()
            if not xl_path:
                QMessageBox.warning(self, "⚠️", "Vui lòng chọn file Excel (.xlsx).")
                return
            if not os.path.isfile(xl_path):
                QMessageBox.warning(self, "⚠️", f"Không tìm thấy file:\n{xl_path}")
                return

            # Với file Excel thường, hỏi xem có muốn ghi đè không hay chỉ thêm mới
            res = QMessageBox.question(
                self, "Chế độ nạp",
                "Bạn muốn THAY THẾ toàn bộ dữ liệu cũ (Yes) hay chỉ NẠP THÊM (No)?",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel
            )
            if res == QMessageBox.StandardButton.Cancel: return
            replace = (res == QMessageBox.StandardButton.Yes)
            self._run_import_worker(db_path, xl_path, dry_run=self.chk_dry.isChecked(), replace=replace)

    def _on_export_to_clipboard(self, db_path):
        """Xuất dữ liệu hiện tại ra Clipboard định dạng TSV."""
        try:
            from core.batch_import import get_all_vouchers_for_export
            data = get_all_vouchers_for_export(db_path)
            if not data:
                QMessageBox.information(self, "Thông báo", "Database hiện chưa có dữ liệu chứng từ để xuất.")
                return

            header = "NgayCT\tLoaiCT\tSoCT\tDienGiai\tTaiKhoanNo\tTaiKhoanCo\tSoTien\tMaDoiTac\tGhiChu\n"
            # Lưu ý: Logic lấy data đang trả về Nợ/Có tách dòng, cần gộp dòng nếu muốn chuẩn template.
            # Tạm thời xuất theo kiểu hỗ trợ dán cơ bản.
            rows = []
            for d in data:
                row = f"{d['NgayCT']}\t{d['LoaiCT']}\t{d['SoCT'] or ''}\t{d['DienGiai']}\t"
                if d['debit'] > 0:
                    row += f"{d['account_code']}\t\t{d['debit']}\t"
                else:
                    row += f"\t{d['account_code']}\t{d['credit']}\t"
                row += f"{d['MaDoiTac'] or ''}\t{d['GhiChu'] or ''}"
                rows.append(row)

            clip_text = header + "\n".join(rows)
            QApplication.clipboard().setText(clip_text)
            show_toast(self.window(), f"Đã sao chép {len(rows)} dòng dữ liệu vào Clipboard.")
        except Exception as e:
            QMessageBox.critical(self, "Lỗi", f"Không thể xuất dữ liệu: {e}")

    def _run_import_worker(self, db_path, xl_path, dry_run, replace, sheet_name=None):
        mode_txt = "DRY-RUN (kiểm tra)" if dry_run else ("THAY THẾ" if replace else "NẠP THÊM")

        self.txt_result.clear()
        self.txt_result.append(f"⏳  Đang chạy {mode_txt}...\n")
        self.txt_result.append(f"   DB   : {db_path}")
        self.txt_result.append(f"   Excel: {xl_path}")
        if sheet_name:
            self.txt_result.append(f"   Sheet: {sheet_name}\n")
        else:
            self.txt_result.append("\n")

        # Khoá nút, hiện progress
        self.btn_import.setEnabled(False)
        self.btn_template.setEnabled(False)
        self.progress.setVisible(True)

        self._worker = ImportWorker(db_path, xl_path, dry_run, replace, sheet_name)
        self._worker.finished.connect(self._on_import_done)
        self._worker.error.connect(self._on_import_error)
        self._worker.start()


    def _on_import_done(self, result: dict):
        self.progress.setVisible(False)
        self.btn_import.setEnabled(True)
        self.btn_template.setEnabled(True)

        success = result.get("success", 0)
        errors  = result.get("errors", [])
        dry_run = self.chk_dry.isChecked()

        mode = "🔍 [DRY-RUN]" if dry_run else "✅ [IMPORT THẬT]"
        self.txt_result.append(f"\n{'─'*50}")
        self.txt_result.append(f"{mode}  Hoàn thành!\n")
        self.txt_result.append(f"  ✅  Thành công : {success} chứng từ")
        self.txt_result.append(f"  ❌  Lỗi        : {len(errors)} chứng từ")

        if errors:
            self.txt_result.append("\n--- Chi tiết lỗi ---")
            for e in errors[:20]:
                row_info = e.get("row") or e.get("rows", "?")
                self.txt_result.append(f"  Dòng {row_info}: {e.get('error', '')}")
            if len(errors) > 20:
                self.txt_result.append(f"  ... và {len(errors)-20} lỗi khác.")

        if not dry_run and success > 0:
            self.txt_result.append(
                f"\n💾  {success} chứng từ đã được ghi vào database thành công."
            )
            # Sync to main window to refresh other pages
            main = self.window()
            if hasattr(main, "set_db_path"):
                main.set_db_path(self.inp_db.text())

            result_xlsx = self.inp_xl.text().replace(".xlsx", "_result.xlsx")
            if os.path.isfile(result_xlsx):
                self.txt_result.append(f"📄  File kết quả: {result_xlsx}")

        if dry_run and success > 0 and not errors:
            self.txt_result.append(
                "\n💡  Dữ liệu hợp lệ. Bỏ tick 'Kiểm tra trước' rồi bấm Import để ghi DB."
            )

    def _on_import_error(self, msg: str):
        self.progress.setVisible(False)
        self.btn_import.setEnabled(True)
        self.btn_template.setEnabled(True)
        self.txt_result.append(f"\n❌  Lỗi nghiêm trọng:\n{msg}")
        QMessageBox.critical(self, "❌  Lỗi Import", f"Đã xảy ra lỗi:\n\n{msg[:400]}")
