# Retry: create the GUI script file attr_form_gui.py in /mnt/data and report result.
import os, textwrap, sys
OUTFILE = "/mnt/data/attr_form_gui.py"
code = r'''"""
attr_form_gui.py
Phase 3: Dynamic GUI form that builds widgets based on attribute_properties JSON and YAML config.
Saves completed work entries into work_properties table as JSON.
Requires: ttkbootstrap, pyyaml
Run: python attr_form_gui.py
"""

import os, sqlite3, json, yaml, datetime, random, string, sys
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import ttkbootstrap as tb

DB_PATH = "wdyd4.db"
YAML_PATH = "attributes_config.yaml"

# ---------- Phase1 utilities (embedded) ----------
def load_config(config_path=YAML_PATH):
    if not os.path.exists(config_path):
        return {"attributes": [], "attribute_properties": [], "maximum_binded_attribute_support": 1}
    with open(config_path, "r", encoding="utf-8") as f:
        cfg = yaml.safe_load(f) or {}
    cfg.setdefault("attributes", [])
    cfg.setdefault("attribute_properties", [])
    cfg.setdefault("maximum_binded_attribute_support", 1)
    return cfg

def formWorkID(prefix="WDY"):
    now = datetime.datetime.utcnow()
    core = now.strftime("%y%m%d%H%M%S%f")[:-3]
    suffix = ''.join(random.choices(string.ascii_uppercase + string.digits, k=2))
    return f"{prefix}{core}{suffix}"

def _get_db_conn(db_path=DB_PATH):
    if not os.path.exists(db_path):
        raise FileNotFoundError(f"DB not found at {db_path}")
    return sqlite3.connect(db_path)

def get_attribute_properties(attr_name, db_path=DB_PATH):
    conn = _get_db_conn(db_path)
    cur = conn.cursor()
    cur.execute("SELECT properties_json FROM attribute_properties WHERE attribute_name = ?", (attr_name,))
    row = cur.fetchone()
    conn.close()
    if not row: return None
    try:
        return json.loads(row[0])
    except Exception:
        return row[0]

def get_dropdown_items(attr_name, db_path=DB_PATH):
    props = get_attribute_properties(attr_name, db_path=db_path)
    if not props or not isinstance(props, dict): return []
    for key in ("DropdownItems","dropdownitems","dropdown_items","dropdown"):
        if key in props:
            val = props[key]
            if isinstance(val, list): return val
            try:
                parsed = json.loads(val)
                if isinstance(parsed, list): return parsed
            except Exception:
                pass
    return []

def get_default_value(attr_name, db_path=DB_PATH):
    props = get_attribute_properties(attr_name, db_path=db_path)
    if not props or not isinstance(props, dict): return None
    for key in ("DefaultValue","Default","defaultvalue","default"):
        if key in props: return props[key]
    return None

def is_flag_true(attr_name, flag, db_path=DB_PATH):
    props = get_attribute_properties(attr_name, db_path=db_path)
    if not props or not isinstance(props, dict): return False
    if flag in props: return bool(props[flag])
    alt = flag.replace(" ", "").replace("_","").lower()
    for k,v in props.items():
        if k.replace(" ","").replace("_","").lower() == alt:
            return bool(v)
    return False

# ---------- Phase2 DB helpers (embedded) ----------
def ensure_work_tables(db_path=DB_PATH):
    conn = _get_db_conn(db_path); cur = conn.cursor()
    cur.execute("""CREATE TABLE IF NOT EXISTS work_properties (
        work_id TEXT PRIMARY KEY, user_name TEXT, properties_json TEXT, created_at TEXT)""")
    conn.commit(); conn.close()

def list_attributes(db_path=DB_PATH):
    conn = _get_db_conn(db_path); cur = conn.cursor()
    cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='Attributes'")
    if not cur.fetchone():
        conn.close(); return []
    cur.execute("SELECT attributeName FROM Attributes ORDER BY attributeID")
    rows = [r[0] for r in cur.fetchall()]; conn.close(); return rows

def insert_final_work(work_id, user_name, properties_dict, db_path=DB_PATH):
    conn = _get_db_conn(db_path); cur = conn.cursor()
    cur.execute("INSERT OR REPLACE INTO work_properties (work_id, user_name, properties_json, created_at) VALUES (?, ?, ?, ?)", 
                (work_id, user_name, json.dumps(properties_dict, ensure_ascii=False), datetime.datetime.utcnow().isoformat()))
    conn.commit(); conn.close()

# ---------- GUI widget constructors ----------
def DrawTheDateEntry(frame, attr_name, default=None):
    lbl = ttk.Label(frame, text=attr_name + " (Date):")
    ent = ttk.Entry(frame)
    if default:
        ent.insert(0, default)
    lbl.pack(fill="x", padx=4, pady=(4,0))
    ent.pack(fill="x", padx=4, pady=(0,6))
    return ent

def DrawEntryWidget(frame, attr_name, default=None):
    lbl = ttk.Label(frame, text=attr_name + ":")
    ent = ttk.Entry(frame)
    if default:
        ent.insert(0, default)
    lbl.pack(fill="x", padx=4, pady=(4,0))
    ent.pack(fill="x", padx=4, pady=(0,6))
    return ent

def DrawTheCombobox(frame, attr_name, items, default=None):
    lbl = ttk.Label(frame, text=attr_name + " (Select):")
    combo = ttk.Combobox(frame, values=items)
    if default:
        combo.set(default)
    lbl.pack(fill="x", padx=4, pady=(4,0))
    combo.pack(fill="x", padx=4, pady=(0,6))
    btn = ttk.Button(frame, text="Add item", command=lambda: handleAddDropdownItem(attr_name, combo))
    btn.pack(anchor="e", padx=4, pady=(0,6))
    return combo

def handleAddDropdownItem(attr_name, combobox_widget):
    new_item = simpledialog.askstring("Add dropdown item", f"New item for {attr_name}:")
    if not new_item: return
    props = get_attribute_properties(attr_name) or {}
    items = props.get("DropdownItems", [])
    if not isinstance(items, list): items = []
    items.append(new_item)
    props["DropdownItems"] = items
    conn = _get_db_conn()
    cur = conn.cursor()
    cur.execute("UPDATE attribute_properties SET properties_json = ? WHERE attribute_name = ?", (json.dumps(props, ensure_ascii=False), attr_name))
    conn.commit(); conn.close()
    combobox_widget['values'] = items
    combobox_widget.set(new_item)
    messagebox.showinfo("Added", f"Added '{new_item}' to {attr_name} dropdown items.")

# ---------- Main form builder ----------
class DynamicFormApp:
    def __init__(self, master, user_name="default"):
        self.master = master
        self.user_name = user_name
        master.title("WDYD Dynamic Form")
        ensure_work_tables()
        self.cfg = load_config()
        self.universal = self._build_universal_dict()
        self.mandatory_attrs = self.universal.get("Mandatory", [])
        if not self.mandatory_attrs:
            self.mandatory_attrs = list_attributes()
        self.widgets = {}
        self._build_ui()

    def _build_universal_dict(self):
        keys = ["Mandatory","HasDropdown","IsDate","HasDefault","HasBinded","CanHaveMultipleValueInLifetime"]
        d = {k: [] for k in keys}
        conn = _get_db_conn(); cur = conn.cursor()
        cur.execute("SELECT attribute_name, properties_json FROM attribute_properties")
        for name, pjson in cur.fetchall():
            try:
                props = json.loads(pjson)
            except Exception:
                continue
            for k in keys:
                for pk, pv in props.items():
                    if pk.replace(" ", "").lower() == k.replace(" ",").lower():
                        if pv:
                            d[k].append(name)
                        break
        conn.close()
        return d

    def _build_ui(self):
        style = tb.Style(theme="litera")
        frame = ttk.Frame(self.master, padding=12)
        frame.pack(fill="both", expand=True)
        form_area = ttk.Frame(frame)
        form_area.pack(fill="both", expand=True)
        for attr in self.mandatory_attrs:
            if is_flag_true(attr, "IsDate"):
                default = get_default_value(attr)
                wid = DrawTheDateEntry(form_area, attr, default=default)
            elif is_flag_true(attr, "HasDropdown"):
                items = get_dropdown_items(attr)
                default = get_default_value(attr)
                wid = DrawTheCombobox(form_area, attr, items, default=default)
            else:
                default = get_default_value(attr)
                wid = DrawEntryWidget(form_area, attr, default=default)
            self.widgets[attr] = wid
        btn = ttk.Button(frame, text="Submit", bootstyle="success", command=self.submit)
        btn.pack(pady=8)

    def submit(self):
        data = {}
        for attr, widget in self.widgets.items():
            try:
                val = widget.get()
            except Exception:
                val = ""
            data[attr] = val
        wid = formWorkID()
        insert_final_work(wid, self.user_name, data)
        messagebox.showinfo("Saved", f"Work saved with ID: {wid}")

def main():
    root = tb.Window(themename="litera")
    app = DynamicFormApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()
'''

try:
    with open(OUTFILE, "w", encoding="utf-8") as f:
        f.write(code)
    created = True
except Exception as e:
    created = False
    err = str(e)

{"created_file": OUTFILE, "created": created, "error": err if not created else None}