from __future__ import annotations

import importlib.util
import sys
import tkinter as tk
from pathlib import Path
from tkinter import ttk


BASE_DIR = Path(__file__).resolve().parent
PYC_PATH = BASE_DIR / "ricoh_gui_automation_310.pyc"

if str(BASE_DIR) not in sys.path:
    sys.path.insert(0, str(BASE_DIR))


def _load_module():
    spec = importlib.util.spec_from_file_location("ricoh_mod", str(PYC_PATH))
    if spec is None or spec.loader is None:
        raise RuntimeError(f"Unable to load {PYC_PATH}")
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


def _to_bool(value, default=False):
    if isinstance(value, bool):
        return value
    text = str(value or "").strip().lower()
    if not text:
        return default
    if text in {"1", "true", "y", "yes", "on", "auto", "자동", "자동계산"}:
        return True
    if text in {"0", "false", "n", "no", "off", "manual", "직접", "직접입력"}:
        return False
    return default


def _walk_widgets(widget):
    yield widget
    try:
        children = widget.winfo_children()
    except Exception:
        children = []
    for child in children:
        yield from _walk_widgets(child)


def _hide_widget(widget):
    try:
        manager = widget.winfo_manager()
    except Exception:
        return
    try:
        if manager == "pack":
            widget.pack_forget()
        elif manager == "grid":
            widget.grid_remove()
        elif manager == "place":
            widget.place_forget()
    except Exception:
        pass


def _widget_text(widget):
    try:
        return str(widget.cget("text") or "")
    except Exception:
        return ""


def _find_button_by_text(root, *texts):
    wanted = {text for text in texts if text}
    for widget in _walk_widgets(root):
        if widget.winfo_class() not in {"Button", "TButton"}:
            continue
        if _widget_text(widget) in wanted:
            return widget
    return None


def _set_file_status(var, prefix, path):
    selected = str(path or "").strip()
    if selected:
        var.set(f"{prefix}: {selected}")
    else:
        var.set(f"{prefix}: \ubbf8\uc120\ud0dd")


def _update_start_button_state(app):
    start_button = getattr(app, "_start_button", None)
    bulk_vars = getattr(app, "bulk_vars", {}) or {}
    confirmer_var = bulk_vars.get("batch_confirmer")
    has_confirmer = bool(confirmer_var and str(confirmer_var.get() or "").strip())
    if start_button is not None:
        try:
            start_button.configure(state="normal" if has_confirmer else "disabled")
        except Exception:
            pass
    return has_confirmer


def _install_ui_enhancements(app, root):
    if getattr(app, "_ui_enhanced", False):
        return
    app._ui_enhanced = True

    start_button = _find_button_by_text(root, "\uc2dc\uc791", "\uc2a4\ud0c0\ud2b8")
    excel_button = _find_button_by_text(root, "\uc5d1\uc140 \ubd88\ub7ec\uc624\uae30")
    pdf_button = _find_button_by_text(root, "\ucca8\ubd80\ud30c\uc77c PDF \uc120\ud0dd", "\ucca8\ubd80\ud30c\uc77c3 PDF \uc120\ud0dd")
    app._start_button = start_button

    if excel_button is not None:
        try:
            toolbar_frame = excel_button.nametowidget(excel_button.winfo_parent())
            list_section = toolbar_frame.nametowidget(toolbar_frame.winfo_parent())
            status_frame = ttk.Frame(list_section)
            status_frame.pack(fill="x", pady=(4, 2), after=toolbar_frame)

            app._excel_file_var = tk.StringVar()
            app._pdf_file_var = tk.StringVar()
            _set_file_status(app._excel_file_var, "\uc5d1\uc140", getattr(app, "last_excel_path", ""))
            _set_file_status(app._pdf_file_var, "PDF", getattr(app, "default_pdf_file3", ""))

            ttk.Label(
                status_frame,
                textvariable=app._excel_file_var,
                anchor="w",
                justify="left",
                wraplength=760,
            ).pack(fill="x")
            ttk.Label(
                status_frame,
                textvariable=app._pdf_file_var,
                anchor="w",
                justify="left",
                wraplength=760,
            ).pack(fill="x", pady=(2, 0))
        except Exception:
            pass
    elif pdf_button is not None:
        try:
            toolbar_frame = pdf_button.nametowidget(pdf_button.winfo_parent())
            list_section = toolbar_frame.nametowidget(toolbar_frame.winfo_parent())
            status_frame = ttk.Frame(list_section)
            status_frame.pack(fill="x", pady=(4, 2), after=toolbar_frame)

            app._pdf_file_var = tk.StringVar()
            _set_file_status(app._pdf_file_var, "PDF", getattr(app, "default_pdf_file3", ""))
            ttk.Label(
                status_frame,
                textvariable=app._pdf_file_var,
                anchor="w",
                justify="left",
                wraplength=760,
            ).pack(fill="x")
        except Exception:
            pass

    bulk_vars = getattr(app, "bulk_vars", {}) or {}
    confirmer_var = bulk_vars.get("batch_confirmer")
    if confirmer_var is not None:
        try:
            confirmer_var.trace_add("write", lambda *_: _update_start_button_state(app))
        except Exception:
            pass
    _update_start_button_state(app)


def _apply_ui_patch(root):
    rename_map = {
        "스타트": "시작",
        "첨부파일3 PDF 선택": "첨부파일 PDF 선택",
    }
    hide_texts = {
        "세션 종료",
        "로그인 세션 저장",
        "TXT 시리얼 불러오기",
    }
    for widget in _walk_widgets(root):
        try:
            text = widget.cget("text")
        except Exception:
            continue
        if text in hide_texts:
            _hide_widget(widget)
            continue
        new_text = rename_map.get(text)
        if new_text and new_text != text:
            try:
                widget.configure(text=new_text)
            except Exception:
                pass


def patch_module(mod):
    original_app_init = mod.App.__init__
    original_load_jobs_from_excel_file = mod.App.load_jobs_from_excel_file
    original_select_default_pdf_file3 = mod.App.select_default_pdf_file3
    original_on_start = mod.App.on_start

    def patched_app_init(self, root):
        original_app_init(self, root)
        try:
            root.after(0, lambda: (_apply_ui_patch(root), _install_ui_enhancements(self, root)))
        except Exception:
            pass

    def patched_load_jobs_from_excel_file(self):
        captured = {"path": ""}
        original_dialog = mod.filedialog.askopenfilename

        def remembered_dialog(*args, **kwargs):
            path = original_dialog(*args, **kwargs)
            captured["path"] = path
            return path

        mod.filedialog.askopenfilename = remembered_dialog
        try:
            return original_load_jobs_from_excel_file(self)
        finally:
            mod.filedialog.askopenfilename = original_dialog
            if captured["path"]:
                self.last_excel_path = captured["path"]
                file_var = getattr(self, "_excel_file_var", None)
                if file_var is not None:
                    _set_file_status(file_var, "\uc5d1\uc140", captured["path"])

    def patched_select_default_pdf_file3(self):
        captured = {"path": ""}
        original_dialog = mod.filedialog.askopenfilename

        def remembered_dialog(*args, **kwargs):
            path = original_dialog(*args, **kwargs)
            captured["path"] = path
            return path

        mod.filedialog.askopenfilename = remembered_dialog
        try:
            return original_select_default_pdf_file3(self)
        finally:
            mod.filedialog.askopenfilename = original_dialog
            if captured["path"]:
                file_var = getattr(self, "_pdf_file_var", None)
                if file_var is not None:
                    _set_file_status(file_var, "PDF", captured["path"])

    def patched_app_normalize(self, job):
        out = dict(mod.AUTO_JOB_DEFAULTS)
        out.update(job or {})
        for key, _, _ in mod.EDITABLE_COLUMNS:
            out[key] = str(out.get(key, "") or "")
        out = mod._apply_visit_type_preset(out, force=False)
        if not str(out.get("file3", "") or "").strip() and getattr(self, "default_pdf_file3", ""):
            out["file3"] = self.default_pdf_file3
        raw_job = job or {}
        out["use_auto_calc"] = _to_bool(raw_job.get("use_auto_calc"), default=False)
        out["complete_submit"] = _to_bool(out.get("complete_submit"), default=False)
        return out

    def patched_automation_normalize(self, job):
        out = dict(mod.AUTO_JOB_DEFAULTS)
        out.update(job or {})
        for key, _, _ in mod.EDITABLE_COLUMNS:
            out[key] = str(out.get(key, "") or "")
        out = mod._apply_visit_type_preset(out, force=False)
        raw_job = job or {}
        out["use_auto_calc"] = _to_bool(raw_job.get("use_auto_calc"), default=False)
        out["complete_submit"] = _to_bool(out.get("complete_submit"), default=False)
        return out

    def patched_fill_work_form(self, job):
        normalized_job = self._normalize_job(job)
        act_cat = str(normalized_job.get("act_cat", "") or "").strip() or "기타"
        vis_cat = str(normalized_job.get("vis_cat", "") or "").strip() or "비서비스"
        vis_obj = str(normalized_job.get("vis_obj", "") or "").strip() or "미터확인"
        handle_text = str(normalized_job.get("handle", "") or "").strip() or "미터 확인"

        self._fill_if_present('input[name="mov_time"]', normalized_job.get("mov_time", ""))
        self._fill_if_present('input[name="arr_time"]', normalized_job.get("arr_time", ""))
        self._fill_if_present('input[name="job_fin_time"]', normalized_job.get("job_fin_time", ""))
        self._fill_if_present('input[name="job_stb_time"]', normalized_job.get("job_stb_time", ""))

        if _to_bool(normalized_job.get("use_auto_calc"), default=False):
            self._click_if_exists_by_role("button", "자동계산")
        else:
            self._click_if_exists_by_role("button", "직접입력")
            self._fill_if_present('input[name="pur_job_time"]', normalized_job.get("pur_job_time", ""))

        self._select_if_present('select[name="act_cat"]', act_cat)
        self._select_if_present('select[name="vis_cat"]', vis_cat)
        if vis_obj == "미터확인":
            self._select_if_present('select[name="vis_obj"]', "기타")
        self._select_if_present('select[name="vis_obj"]', vis_obj)

        try:
            self.page.locator("body").first.click(timeout=800)
        except Exception:
            pass

        for key, selector in (
            ("p_code", 'input[name="p_code"]'),
            ("c_code", 'input[name="c_code"]'),
            ("r_code", 'input[name="r_code"]'),
            ("d_code", 'input[name="d_code"]'),
            ("t_code", 'input[name="t_code"]'),
        ):
            self._fill_if_present(selector, normalized_job.get(key, ""))

        for sel in ('textarea[name="handle"]', "textarea", 'div[contenteditable="true"]'):
            try:
                self.page.locator(sel).first.fill(handle_text)
                self.log(f"입력: 작업내용 = {handle_text}")
                break
            except Exception:
                continue

        self._fill_if_present('input[name="c_meter"]', normalized_job.get("c_meter", ""))
        self._fill_if_present('input[name="b_meter"]', normalized_job.get("b_meter", ""))
        self._attach_file("#file1", str(normalized_job.get("file1", "") or ""))
        self._attach_file("#file2", str(normalized_job.get("file2", "") or ""))
        self._attach_file("#file3", str(normalized_job.get("file3", "") or ""))

        confirmer = str(normalized_job.get("confirmer", "") or "").strip()
        if confirmer:
            self._fill_signature_text(confirmer)

    def patched_on_start(self):
        if not _update_start_button_state(self):
            try:
                mod.messagebox.showwarning(
                    "\ud655\uc778\uc790 \uc785\ub825 \ud544\uc694",
                    "\ud655\uc778\uc790 \uc77c\uad04 \uc785\ub825 \uce78\uc744 \uba3c\uc800 \uc785\ub825\ud558\uc138\uc694.",
                )
            except Exception:
                pass
            return None

        try:
            self.apply_batch_confirmer(silent=True)
        except Exception:
            pass

        result = original_on_start(self)
        if getattr(self, "default_pdf_file3", ""):
            self.default_pdf_file3 = ""
            try:
                self.enqueue_log("첨부파일3 기본 PDF를 현재 실행분만 적용하고 초기화했습니다.")
            except Exception:
                pass
        return result

    mod.App.__init__ = patched_app_init
    mod.App.load_jobs_from_excel_file = patched_load_jobs_from_excel_file
    mod.App.select_default_pdf_file3 = patched_select_default_pdf_file3
    mod.App._normalize_job = patched_app_normalize
    mod.App.on_start = patched_on_start
    mod.RicohAutomation._normalize_job = patched_automation_normalize
    mod.RicohAutomation._fill_work_form = patched_fill_work_form


def main():
    mod = _load_module()
    patch_module(mod)

    root = tk.Tk()
    try:
        try:
            mod.ttk.Style(root).theme_use("clam")
        except Exception:
            pass
        app = mod.App(root)
        root.protocol("WM_DELETE_WINDOW", lambda: (app.automation.close(), root.destroy()))
        root.mainloop()
    finally:
        try:
            root.destroy()
        except Exception:
            pass
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
