from __future__ import annotations

import requests
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QCheckBox,
    QDialog,
    QFrame,
    QGridLayout,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QMessageBox,
    QPushButton,
    QScrollArea,
    QStackedWidget,
    QVBoxLayout,
    QWidget,
)

from core.auth import (
    get_last_tax_code,
    get_local_company_info,
    has_any_account,
    login_user,
    register_account,
    reset_password_with_usb_token,
)
from gui.ui_helpers import PrimaryButton, SecondaryButton


class AuthDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.auth_account: dict | None = None
        self.setWindowTitle("Đăng nhập phần mềm")
        self.setModal(True)
        self.resize(1080, 720)
        self.setMinimumSize(960, 660)
        self._build_ui()
        self._load_defaults()

    def _build_ui(self) -> None:
        self.setStyleSheet(
            "QDialog { background: #f4efe7; }"
            "QFrame#auth_brand {"
            "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #0f766e, stop:1 #155e75);"
            "border-top-left-radius: 22px; border-bottom-left-radius: 22px;"
            "}"
            "QFrame#auth_card { background: white; border-top-right-radius: 22px; border-bottom-right-radius: 22px; }"
            "QLabel#brand_title { color: white; font-size: 28px; font-weight: 700; }"
            "QLabel#brand_text { color: rgba(255, 255, 255, 0.9); font-size: 13px; line-height: 1.5; }"
            "QLabel#panel_title { color: #0f172a; font-size: 24px; font-weight: 700; }"
            "QLabel#panel_subtitle { color: #64748b; font-size: 13px; }"
            "QLabel#field_label { color: #334155; font-size: 12px; font-weight: 600; }"
            "QLabel#status_ok { color: #166534; font-size: 12px; font-weight: 600; }"
            "QLabel#status_error { color: #b91c1c; font-size: 12px; font-weight: 600; }"
            "QLineEdit {"
            "border: 1px solid #d0d7de; border-radius: 10px; padding: 10px 12px;"
            "font-size: 13px; background: #ffffff; min-height: 18px;"
            "}"
            "QLineEdit:focus { border: 1px solid #0f766e; }"
            "QCheckBox { color: #475569; }"
            "QPushButton#link_button { color: #0f766e; background: transparent; border: none; font-weight: 600; text-align: left; }"
            "QPushButton#link_button:hover { color: #115e59; text-decoration: underline; }"
        )

        root = QHBoxLayout(self)
        root.setContentsMargins(24, 24, 24, 24)
        root.setSpacing(0)

        brand = QFrame()
        brand.setObjectName("auth_brand")
        brand_layout = QVBoxLayout(brand)
        brand_layout.setContentsMargins(36, 36, 36, 36)
        brand_layout.setSpacing(18)

        brand_badge = QLabel("INI Accountant")
        brand_badge.setStyleSheet(
            "background: rgba(255,255,255,0.16); color: white; padding: 8px 12px; "
            "border-radius: 999px; font-size: 12px; font-weight: 700;"
        )
        brand_badge.setAlignment(Qt.AlignmentFlag.AlignCenter)
        brand_badge.setFixedWidth(150)

        brand_title = QLabel("Đăng nhập bằng MST, quản lý theo đúng hồ sơ doanh nghiệp")
        brand_title.setObjectName("brand_title")
        brand_title.setWordWrap(True)

        brand_text = QLabel(
            "Mỗi tài khoản gắn với một MST để mở đúng dữ liệu công ty và quản lý cục bộ trên máy của bạn. "
            "Khi quên mật khẩu, bạn có thể dùng USB token để xác thực và tạo mật khẩu mới."
        )
        brand_text.setObjectName("brand_text")
        brand_text.setWordWrap(True)

        feature_box = QFrame()
        feature_box.setStyleSheet(
            "QFrame { background: rgba(255,255,255,0.12); border: 1px solid rgba(255,255,255,0.18); border-radius: 16px; }"
        )
        feature_layout = QVBoxLayout(feature_box)
        feature_layout.setContentsMargins(18, 18, 18, 18)
        feature_layout.setSpacing(10)
        for text in (
            "Tài khoản mặc định dùng MST.",
            "Đăng ký mới tái dùng đúng bộ thông tin Công ty/HKD.",
            "Quên mật khẩu có thể xác thực lại bằng USB token.",
        ):
            item = QLabel(f"• {text}")
            item.setObjectName("brand_text")
            item.setWordWrap(True)
            feature_layout.addWidget(item)

        brand_layout.addWidget(brand_badge)
        brand_layout.addStretch()
        brand_layout.addWidget(brand_title)
        brand_layout.addWidget(brand_text)
        brand_layout.addWidget(feature_box)
        brand_layout.addStretch()

        card = QFrame()
        card.setObjectName("auth_card")
        card_layout = QVBoxLayout(card)
        card_layout.setContentsMargins(34, 30, 34, 30)
        card_layout.setSpacing(0)

        self.stack = QStackedWidget()
        self.stack.addWidget(self._build_login_page())
        self.stack.addWidget(self._build_register_page())
        self.stack.addWidget(self._build_reset_page())
        card_layout.addWidget(self.stack)

        root.addWidget(brand, 5)
        root.addWidget(card, 6)

    def _build_login_page(self) -> QWidget:
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(14)

        title = QLabel("Đăng nhập")
        title.setObjectName("panel_title")
        subtitle = QLabel("Bạn dùng MST làm tài khoản. Nếu chưa có tài khoản, hãy đăng ký ở bước tiếp theo.")
        subtitle.setObjectName("panel_subtitle")
        subtitle.setWordWrap(True)

        layout.addWidget(title)
        layout.addWidget(subtitle)
        layout.addSpacing(10)

        self.inp_login_tax_id = self._make_line_edit("Nhập MST của bạn")
        self.inp_login_password = self._make_line_edit("Nhập mật khẩu", password=True)
        self.inp_login_password.returnPressed.connect(self._on_login_clicked)
        self.chk_remember = QCheckBox("Ghi nhớ đăng nhập trên máy này")

        layout.addWidget(self._wrap_field("Mã số thuế", self.inp_login_tax_id))
        layout.addWidget(self._wrap_field("Mật khẩu", self.inp_login_password))
        layout.addWidget(self.chk_remember)

        self.lbl_login_status = QLabel("")
        self.lbl_login_status.hide()
        layout.addWidget(self.lbl_login_status)

        self.btn_login = PrimaryButton("Đăng nhập")
        self.btn_login.setFixedHeight(44)
        self.btn_login.clicked.connect(self._on_login_clicked)
        layout.addWidget(self.btn_login)

        self.btn_forgot_password = QPushButton("Quên mật khẩu? Dùng USB token")
        self.btn_forgot_password.setObjectName("link_button")
        self.btn_forgot_password.clicked.connect(self._show_reset_page)
        layout.addWidget(self.btn_forgot_password, alignment=Qt.AlignmentFlag.AlignLeft)

        self.btn_open_register = QPushButton("Chưa có tài khoản? Đăng ký ngay")
        self.btn_open_register.setObjectName("link_button")
        self.btn_open_register.clicked.connect(self._show_register_page)
        layout.addWidget(self.btn_open_register, alignment=Qt.AlignmentFlag.AlignLeft)

        if not has_any_account():
            hint = QLabel("Máy này chưa có tài khoản nào. Bạn hãy đăng ký trước khi đăng nhập.")
            hint.setObjectName("panel_subtitle")
            hint.setWordWrap(True)
            layout.addWidget(hint)

        layout.addStretch()
        return page

    def _build_register_page(self) -> QWidget:
        page = QWidget()
        outer = QVBoxLayout(page)
        outer.setContentsMargins(0, 0, 0, 0)
        outer.setSpacing(12)

        title = QLabel("Đăng ký tài khoản")
        title.setObjectName("panel_title")
        subtitle = QLabel(
            "Hồ sơ đăng ký dùng đúng bộ thông tin Công ty/HKD đang dùng trong phần mềm. "
            "Tài khoản này được lưu cục bộ trên máy của bạn và không đồng bộ thông tin đăng nhập lên server."
        )
        subtitle.setObjectName("panel_subtitle")
        subtitle.setWordWrap(True)

        outer.addWidget(title)
        outer.addWidget(subtitle)

        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setFrameShape(QFrame.Shape.NoFrame)

        container = QWidget()
        grid = QGridLayout(container)
        grid.setContentsMargins(0, 6, 6, 6)
        grid.setHorizontalSpacing(18)
        grid.setVerticalSpacing(12)
        grid.setColumnStretch(1, 1)
        grid.setColumnStretch(3, 1)

        self.inp_reg_legal_name = self._make_line_edit("Tên đầy đủ theo ĐKKD")
        self.inp_reg_tax_id = self._make_line_edit("0123456789")
        self.inp_reg_address = self._make_line_edit("Số nhà, phường/xã, quận/huyện, tỉnh/thành")
        self.inp_reg_email = self._make_line_edit("ketoan@congty.com")
        self.inp_reg_phone = self._make_line_edit("0912345678")
        self.inp_reg_fax = self._make_line_edit("02412345678")
        self.inp_reg_website = self._make_line_edit("https://tenmiencuaban.vn")
        self.inp_reg_rep = self._make_line_edit("Họ và tên người đại diện pháp luật")
        self.inp_reg_position = self._make_line_edit("Giám đốc / Chủ hộ kinh doanh")
        self.inp_reg_bank = self._make_line_edit("Số tài khoản - Ngân hàng")
        self.inp_reg_password = self._make_line_edit("Tạo mật khẩu", password=True)
        self.inp_reg_confirm = self._make_line_edit("Nhập lại mật khẩu", password=True)
        self.inp_reg_confirm.returnPressed.connect(self._on_register_clicked)

        btn_lookup_tax = SecondaryButton("Tra cứu MST")
        btn_lookup_tax.setFixedHeight(40)
        btn_lookup_tax.clicked.connect(self._on_lookup_tax_clicked)
        tax_widget = QWidget()
        tax_layout = QHBoxLayout(tax_widget)
        tax_layout.setContentsMargins(0, 0, 0, 0)
        tax_layout.setSpacing(8)
        tax_layout.addWidget(self.inp_reg_tax_id, 1)
        tax_layout.addWidget(btn_lookup_tax)

        self._add_field(grid, 0, 0, "Tên pháp lý", self.inp_reg_legal_name)
        self._add_field(grid, 0, 2, "Mã số thuế", tax_widget)
        self._add_field(grid, 1, 0, "Địa chỉ", self.inp_reg_address)
        self._add_field(grid, 1, 2, "Email", self.inp_reg_email)
        self._add_field(grid, 2, 0, "Số điện thoại", self.inp_reg_phone)
        self._add_field(grid, 2, 2, "Fax", self.inp_reg_fax)
        self._add_field(grid, 3, 0, "Website", self.inp_reg_website)
        self._add_field(grid, 3, 2, "Người đại diện", self.inp_reg_rep)
        self._add_field(grid, 4, 0, "Chức vụ", self.inp_reg_position)
        self._add_field(grid, 4, 2, "Tài khoản ngân hàng", self.inp_reg_bank)
        self._add_field(grid, 5, 0, "Mật khẩu", self.inp_reg_password)
        self._add_field(grid, 5, 2, "Xác nhận mật khẩu", self.inp_reg_confirm)

        scroll.setWidget(container)
        outer.addWidget(scroll, 1)

        self.lbl_register_status = QLabel("")
        self.lbl_register_status.hide()
        outer.addWidget(self.lbl_register_status)

        actions = QHBoxLayout()
        actions.setContentsMargins(0, 4, 0, 0)
        actions.setSpacing(10)
        self.btn_back_login = SecondaryButton("Quay lại đăng nhập")
        self.btn_back_login.clicked.connect(self._show_login_page)
        self.btn_register = PrimaryButton("Đăng ký và đăng nhập")
        self.btn_register.setFixedHeight(44)
        self.btn_register.clicked.connect(self._on_register_clicked)
        actions.addWidget(self.btn_back_login)
        actions.addStretch()
        actions.addWidget(self.btn_register)
        outer.addLayout(actions)
        return page

    def _build_reset_page(self) -> QWidget:
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(14)

        title = QLabel("Quên mật khẩu")
        title.setObjectName("panel_title")
        subtitle = QLabel(
            "Cắm USB token, chọn đúng chứng thư số có MST trùng với tài khoản rồi tạo mật khẩu mới. "
            "Ứng dụng sẽ yêu cầu token ký một challenge xác thực trước khi đổi mật khẩu."
        )
        subtitle.setObjectName("panel_subtitle")
        subtitle.setWordWrap(True)

        note = QFrame()
        note.setStyleSheet("QFrame { background: #f8fafc; border: 1px solid #dbeafe; border-radius: 12px; }")
        note_layout = QVBoxLayout(note)
        note_layout.setContentsMargins(14, 12, 14, 12)
        note_layout.setSpacing(6)
        for text in (
            "1. Nhập MST của tài khoản cần khôi phục.",
            "2. Nhập mật khẩu mới rồi bấm xác thực bằng USB token.",
            "3. Chọn chứng thư số có MST trùng tài khoản và xác nhận PIN nếu token yêu cầu.",
        ):
            item = QLabel(text)
            item.setObjectName("panel_subtitle")
            item.setWordWrap(True)
            note_layout.addWidget(item)

        self.inp_reset_tax_id = self._make_line_edit("Nhập MST của tài khoản cần đặt lại mật khẩu")
        self.inp_reset_password = self._make_line_edit("Nhập mật khẩu mới", password=True)
        self.inp_reset_confirm = self._make_line_edit("Nhập lại mật khẩu mới", password=True)
        self.inp_reset_confirm.returnPressed.connect(self._on_reset_password_clicked)

        layout.addWidget(title)
        layout.addWidget(subtitle)
        layout.addWidget(note)
        layout.addWidget(self._wrap_field("Mã số thuế", self.inp_reset_tax_id))
        layout.addWidget(self._wrap_field("Mật khẩu mới", self.inp_reset_password))
        layout.addWidget(self._wrap_field("Xác nhận mật khẩu mới", self.inp_reset_confirm))

        self.lbl_reset_status = QLabel("")
        self.lbl_reset_status.hide()
        layout.addWidget(self.lbl_reset_status)

        actions = QHBoxLayout()
        actions.setContentsMargins(0, 4, 0, 0)
        actions.setSpacing(10)
        self.btn_back_from_reset = SecondaryButton("Quay lại đăng nhập")
        self.btn_back_from_reset.clicked.connect(self._show_login_page)
        self.btn_reset_password = PrimaryButton("Xác thực USB token và tạo mật khẩu mới")
        self.btn_reset_password.setFixedHeight(44)
        self.btn_reset_password.clicked.connect(self._on_reset_password_clicked)
        actions.addWidget(self.btn_back_from_reset)
        actions.addStretch()
        actions.addWidget(self.btn_reset_password)
        layout.addLayout(actions)
        layout.addStretch()
        return page

    def _make_line_edit(self, placeholder: str, password: bool = False) -> QLineEdit:
        widget = QLineEdit()
        widget.setPlaceholderText(placeholder)
        widget.setMinimumHeight(40)
        if password:
            widget.setEchoMode(QLineEdit.EchoMode.Password)
        return widget

    def _wrap_field(self, label_text: str, widget: QWidget) -> QWidget:
        container = QWidget()
        layout = QVBoxLayout(container)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(6)
        label = QLabel(label_text)
        label.setObjectName("field_label")
        layout.addWidget(label)
        layout.addWidget(widget)
        return container

    def _add_field(self, grid: QGridLayout, row: int, col: int, label_text: str, widget: QWidget) -> None:
        label = QLabel(label_text)
        label.setObjectName("field_label")
        grid.addWidget(label, row, col)
        grid.addWidget(widget, row, col + 1)

    def _load_defaults(self) -> None:
        company = get_local_company_info()
        last_tax_code = get_last_tax_code() or str(company.get("tax_id", "")).strip()
        self.inp_login_tax_id.setText(last_tax_code)
        self.chk_remember.setChecked(True)

        self.inp_reg_legal_name.setText(str(company.get("legal_name", "")))
        self.inp_reg_tax_id.setText(last_tax_code)
        self.inp_reg_address.setText(str(company.get("address", "")))
        self.inp_reg_email.setText(str(company.get("email", "")))
        self.inp_reg_phone.setText(str(company.get("phone", "")))
        self.inp_reg_fax.setText(str(company.get("fax", "")))
        self.inp_reg_website.setText(str(company.get("website", "")))
        self.inp_reg_rep.setText(str(company.get("representative", "")))
        self.inp_reg_position.setText(str(company.get("position", "")))
        self.inp_reg_bank.setText(str(company.get("bank_account", "")))
        self.inp_reset_tax_id.setText(last_tax_code)

        if last_tax_code:
            self.inp_login_password.setFocus()
        elif not has_any_account():
            self._show_register_page()

    def _set_status(self, label: QLabel, message: str, ok: bool) -> None:
        label.setText(message)
        label.setObjectName("status_ok" if ok else "status_error")
        label.style().unpolish(label)
        label.style().polish(label)
        label.show()

    def _show_login_page(self) -> None:
        self.stack.setCurrentIndex(0)
        candidate_tax_code = self.inp_login_tax_id.text().strip()
        if self.inp_reset_tax_id.text().strip():
            candidate_tax_code = self.inp_reset_tax_id.text().strip()
        elif self.inp_reg_tax_id.text().strip():
            candidate_tax_code = self.inp_reg_tax_id.text().strip()
        self.inp_login_tax_id.setText(candidate_tax_code)
        self.inp_login_password.setFocus()

    def _show_register_page(self) -> None:
        if self.inp_login_tax_id.text().strip() and not self.inp_reg_tax_id.text().strip():
            self.inp_reg_tax_id.setText(self.inp_login_tax_id.text().strip())
        self.stack.setCurrentIndex(1)
        self.inp_reg_legal_name.setFocus()

    def _show_reset_page(self) -> None:
        if self.inp_login_tax_id.text().strip():
            self.inp_reset_tax_id.setText(self.inp_login_tax_id.text().strip())
        self.stack.setCurrentIndex(2)
        self.inp_reset_password.setFocus()

    def _collect_registration_info(self) -> dict:
        return {
            "legal_name": self.inp_reg_legal_name.text().strip(),
            "tax_id": self.inp_reg_tax_id.text().strip(),
            "address": self.inp_reg_address.text().strip(),
            "email": self.inp_reg_email.text().strip(),
            "phone": self.inp_reg_phone.text().strip(),
            "fax": self.inp_reg_fax.text().strip(),
            "website": self.inp_reg_website.text().strip(),
            "representative": self.inp_reg_rep.text().strip(),
            "position": self.inp_reg_position.text().strip(),
            "bank_account": self.inp_reg_bank.text().strip(),
        }

    def _on_login_clicked(self) -> None:
        result = login_user(
            self.inp_login_tax_id.text().strip(),
            self.inp_login_password.text(),
            remember=self.chk_remember.isChecked(),
        )
        if not result.ok:
            self._set_status(self.lbl_login_status, result.message, ok=False)
            return

        self.auth_account = result.account
        self.accept()

    def _on_register_clicked(self) -> None:
        info_data = self._collect_registration_info()
        result = register_account(
            company_info=info_data,
            password=self.inp_reg_password.text(),
            confirm_password=self.inp_reg_confirm.text(),
        )
        if not result.ok:
            self._set_status(self.lbl_register_status, result.message, ok=False)
            return

        login_result = login_user(info_data.get("tax_id", ""), self.inp_reg_password.text(), remember=True)
        if not login_result.ok:
            self._set_status(self.lbl_register_status, login_result.message, ok=False)
            return

        self.auth_account = login_result.account
        self.accept()

    def _on_reset_password_clicked(self) -> None:
        result = reset_password_with_usb_token(
            self.inp_reset_tax_id.text().strip(),
            self.inp_reset_password.text(),
            self.inp_reset_confirm.text(),
        )
        if not result.ok:
            self._set_status(self.lbl_reset_status, result.message, ok=False)
            return

        self._set_status(self.lbl_reset_status, result.message, ok=True)
        self.inp_login_tax_id.setText(self.inp_reset_tax_id.text().strip())
        self.inp_login_password.clear()
        self.inp_reset_password.clear()
        self.inp_reset_confirm.clear()
        QMessageBox.information(self, "Khôi phục mật khẩu", result.message)
        self._show_login_page()

    def _on_lookup_tax_clicked(self) -> None:
        tax_code = self.inp_reg_tax_id.text().strip()
        if not tax_code:
            QMessageBox.warning(self, "Tra cứu MST", "Bạn hãy nhập MST trước khi tra cứu.")
            return

        try:
            response = requests.get(
                f"https://api.xinvoice.vn/gdt-api/tax-payer/{tax_code}",
                headers={"Accept": "application/json", "client-id": "", "api-key": ""},
                timeout=10,
            )
            payload = response.json()
        except Exception as exc:
            QMessageBox.warning(self, "Tra cứu MST", f"Không tra cứu được MST:\n{exc}")
            return

        if response.status_code != 200 or not payload:
            QMessageBox.warning(self, "Tra cứu MST", "Không nhận được dữ liệu MST phù hợp.")
            return

        name = str(payload.get("name", "")).strip()
        if name:
            name_lines = [line.strip() for line in name.split("\n") if line.strip() and not line.strip().startswith("Thông tin Công ty")]
            self.inp_reg_legal_name.setText(name_lines[-1] if name_lines else name)

        address = str(payload.get("address", "")).strip()
        if address:
            self.inp_reg_address.setText(address)
