from flask import Flask, request, jsonify, abort, send_file, send_from_directory
import sqlite3
import os
import telebot
from telebot import types
import random
import string
import json
import zipfile
import shutil
import time
import re
import requests

app = Flask(__name__)

@app.route('/login_data', methods=['GET'])
def get_login_and_vrd_pass():
    vrd_login = "Spb_216"
    vrd_password = "Spb123123"

    try:
        with sqlite3.connect('/var/www/flask-api/base/personal.db') as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT login, password FROM vardek_connection LIMIT 1")
            row = cursor.fetchone()

        if not row:
            return jsonify({"login": vrd_login, "password": vrd_password}), 404

        vrd_login, vrd_password = row

        return jsonify({"login": vrd_login, "password": vrd_password})

    except Exception as e:
        return jsonify({"login": vrd_login, "password": vrd_password}), 500

def get_version_msm(mt):
    try:
        if mt is None:
            file_path = "/var/www/flask-api/base/temp/msm_update/version.txt"
        elif mt == "tech":
            file_path = "/var/www/flask-api/base/temp/msm_update/version_t/version.txt"
        elif mt == "saller":
            file_path = "/var/www/flask-api/base/temp/msm_update/version_s/version.txt"
        elif mt == "salon":
            file_path = "/var/www/flask-api/base/temp/msm_update/version_sn/version.txt"
        else:
            return None

        with open(file_path, "r") as file:
            version = file.read().strip()
        return version

    except FileNotFoundError:
        return None
    except Exception as e:
        return None

@app.route('/check_msm_update', methods=['POST'])
def check_update_msm():
    client_version = request.json.get('version', None)
    mt = request.json.get('mt', None)
    if client_version is None:
        return jsonify({"error": "Version not provided"}), 400
    SERVER_VERSION = get_version_msm(mt)
    if client_version == SERVER_VERSION:
        return jsonify({"update": False, "message": "Your version is up-to-date"}), 200

    return jsonify({"update": True, "version": SERVER_VERSION, "message": "Update available"}), 200

@app.route('/download_msm_update', methods=['GET'])
def download_update_msm():
    UPDATE_FILE_PATH = "/var/www/flask-api/base/temp/msm_update/update_msm.zip"
    try:
        return send_file(UPDATE_FILE_PATH, mimetype='application/zip', as_attachment=True)
    except FileNotFoundError:
        return jsonify({"error": "Update file not found"}), 404

@app.route('/download_msm_update_tech', methods=['GET'])
def download_update_msm_tech():
    UPDATE_FILE_PATH_TECH = "/var/www/flask-api/base/temp/msm_update/update_msm_tech.zip"
    try:
        return send_file(UPDATE_FILE_PATH_TECH, mimetype='application/zip', as_attachment=True)
    except FileNotFoundError:
        return jsonify({"error": "Update file not found"}), 404

@app.route('/download_msm_update_salon', methods=['GET'])
def download_update_msm_salon():
    UPDATE_FILE_PATH_SALON = "/var/www/flask-api/base/temp/msm_update/update_msm_salon.zip"
    try:
        return send_file(UPDATE_FILE_PATH_SALON, mimetype='application/zip', as_attachment=True)
    except FileNotFoundError:
        return jsonify({"error": "Update file not found"}), 404

@app.route("/check_access_msm", methods=["POST"])
def check_access():
    data = request.json
    key = data.get("key", "").strip()
    if not key:
        return jsonify({"access": False, "message": "Ключ не предоставлен"}), 400

    conn = sqlite3.connect('/var/www/flask-api/base/personal.db')
    cursor = conn.cursor()
    try:
        cursor.execute("SELECT COUNT(*) FROM keys_constructor WHERE key = ?", (key,))
        result = cursor.fetchone()

        if result[0] > 0:
            return jsonify({"access": True, "message": "Доступ разрешён"}), 200
        else:
            return jsonify({"access": False, "message": "Доступ запрещён"}), 200

    except sqlite3.Error as e:
        return jsonify({"access": False, "message": "Ошибка сервера"}), 500
    finally:
        conn.close()

@app.route('/get_multiplication', methods=['POST'])
def get_multiplication():
    try:
        data = request.get_json()
        seltech = data.get("seltech")
        if seltech not in ["seller", "tech", "salon"]:
            return jsonify({"multiplication": "2.5"}), 400

        with sqlite3.connect('/var/www/flask-api/base/personal.db') as conn:
            cursor = conn.cursor()
            if seltech == "seller":
                cursor.execute("SELECT seller FROM multiplication")
            elif seltech == "salon":
                cursor.execute("SELECT salon FROM multiplication")
            else:
                cursor.execute("SELECT tech FROM multiplication")

            row = cursor.fetchone()

        if not row:
            return jsonify({"multiplication": "2.5"}), 404

        multiplication_value = str(row[0])
        return jsonify({"multiplication": multiplication_value})

    except Exception as e:
        return jsonify({"multiplication": "2.5"}), 500

@app.route('/get_dop_position', methods=['GET'])
def get_dop_position():
    try:
        base_dir = '/var/www/flask-api/base/temp'
        filename = 'dop_position.json'
        file_path = os.path.join(base_dir, filename)

        if not os.path.exists(file_path):
            return jsonify({"error": "File not found"}), 404

        return send_from_directory(base_dir, filename, as_attachment=False)

    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/get_dop_image/<filename>', methods=['GET'])
def get_dop_image(filename):
    try:
        base_dir = '/var/www/flask-api/base/temp/dop_positions'

        if '..' in filename or filename.startswith('/'):
            return jsonify({"error": "Invalid filename"}), 400

        file_path = os.path.join(base_dir, filename)
        if not os.path.exists(file_path):
            return jsonify({"error": "File not found"}), 404

        return send_from_directory(base_dir, filename)

    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/table_top/<manufacturer>/<image_type>/<filename>', methods=['GET'])
def get_table_top_image(manufacturer, image_type, filename):
    try:
        base_dir = f'/var/www/flask-api/base/temp/table_top/{manufacturer}/{image_type}'

        if '..' in filename or filename.startswith('/'):
            return jsonify({"error": "Invalid filename"}), 400

        file_path = os.path.join(base_dir, filename)
        if not os.path.exists(file_path):
            return jsonify({"error": "File not found"}), 404

        return send_from_directory(base_dir, filename)

    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/fasades/<manufacturer>/<image_type>/<filename>', methods=['GET'])
def get_fasades_image(manufacturer, image_type, filename):
    try:
        base_dir = f'/var/www/flask-api/base/temp/fasades/{manufacturer}/{image_type}'

        if '..' in filename or filename.startswith('/'):
            return jsonify({"error": "Invalid filename"}), 400

        file_path = os.path.join(base_dir, filename)
        if not os.path.exists(file_path):
            return jsonify({"error": "File not found"}), 404

        return send_from_directory(base_dir, filename)

    except Exception as e:
        return jsonify({"error": str(e)}), 500


#блок для телеграмм бота BEGIN
TOKEN = "8403765292:AAHhZ2yn1-YGQivNxNxT7y5EzyYMsNTIqzs"
bot = telebot.TeleBot(TOKEN)

@app.route("/webhook", methods=["POST"])
def bot_webhook_func():
    try:
        json_str = request.get_json(force=True)
        update = telebot.types.Update.de_json(json_str)
        bot.process_new_updates([update])
    except Exception as e:
        pass
        
    return "OK", 200

def perform_authenticated_request(save_path_data_file, trigger=None):
    vrd_login = "Spb_216"
    vrd_password = "Spb123123"
    
    try:
        with sqlite3.connect('/var/www/flask-api/base/personal.db') as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT login, password FROM vardek_connection LIMIT 1")
            row = cursor.fetchone()
        if not row:
            pass
        
        vrd_login, vrd_password = row
        
    except Exception as e:
        pass
        
    login_url = "https://lego-format.ru/login/index.php?login=yes"
    login_data = {
        "AUTH_FORM": "Y",
        "TYPE": "AUTH",
        "backurl": "/login/index.php",
        "USER_LOGIN": vrd_login,
        "USER_PASSWORD": vrd_password
    }

    data_url_1 = "https://lego-format.ru/local/templates/constructor/API/data.get.php?config=43830&style_id=1295106"
    data_url_2 = "https://lego-format.ru/local/templates/constructor/js/constructor.min.js"
    headers = {
        "accept": "application/json, text/javascript, */*; q=0.01",
        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
        "x-requested-with": "XMLHttpRequest"
    }
    
    with requests.Session() as session:
        auth_response = session.post(login_url, data=login_data, headers=headers, verify=False)
        if auth_response.status_code == 200:
            file_response_1 = session.get(data_url_1, headers=headers, verify=False)
            if file_response_1.status_code == 200:
                os.makedirs(save_path_data_file, exist_ok=True)
                full_save_path_0 = os.path.join(save_path_data_file, "data.get.json")
                with open(full_save_path_0, "wb") as f0:
                    f0.write(file_response_1.content)
            
            if trigger in ['yes_constructor', 'tech_constructor', 'seller_constructor', 'salon_constructor']:
                file_response_2 = session.get(data_url_2, headers=headers, verify=False)
                if file_response_2.status_code == 200:
                    if trigger in ['yes_constructor', 'tech_constructor']:
                        full_save_path_1 = os.path.join("/var/www/flask-api/base/temp/msm_update/msm_tech/data/", "constructor_tech.min.js")
                        with open(full_save_path_1, "wb") as f1:
                            f1.write(file_response_2.content)
                            
                    if trigger in ['yes_constructor', 'seller_constructor']:
                        full_save_path_2 = os.path.join("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/", "constructor.min.js")
                        with open(full_save_path_2, "wb") as f2:
                            f2.write(file_response_2.content)

                    if trigger in ['yes_constructor', 'salon_constructor']:
                        full_save_path_3 = os.path.join("/var/www/flask-api/base/temp/msm_update/msm_salon/data/", "constructor_salon.min.js")
                        with open(full_save_path_3, "wb") as f3:
                            f3.write(file_response_2.content)

def update_version_with_limits(file_path):
    with open(file_path, 'r') as file:
        content = file.read()
    
    version_match = re.search(r'\d+\.\d+\.\d+', content)
    if version_match:
        version = version_match.group(0)
        parts = list(map(int, version.split('.')))
        for i in range(len(parts) - 1, -1, -1):
            parts[i] += 1
            if parts[i] > 70:
                parts[i] = 0
            else:
                break
        
        new_version = '.'.join(map(str, parts))
        updated_content = content.replace(version, new_version)
        with open(file_path, 'w') as file:
            file.write(updated_content)

def delete_files(file_paths):
    for file_path in file_paths:
        try:
            os.remove(file_path)
        except FileNotFoundError:
            pass
        except PermissionError:
            pass
        except Exception as e:
            pass

def move_file(src_path, dest_path):
    try:
        shutil.copy2(src_path, dest_path)
    except FileNotFoundError:
        print(f"Файл {src_path} не найден.")
    except Exception as e:
        print(f"Ошибка при копировании файла: {e}")

def create_json_for_autorsf(data, output_file, manufacturer):
    if 'FASADE' in data:
        fasade_data = data['FASADE']
        
        processed_fasade_data = {}
        for key, element in fasade_data.items():
            processed_element = {
                'NAME': element.get('NAME', ''),
                'MATERIAL': element.get('MATERIAL', ''),
                'MANUFACTURER': element.get('MANUFACTURER', '')
            }
            
            if 'MANUFACTURER' not in element:
                processed_element['MANUFACTURER'] = manufacturer
            
            processed_fasade_data[key] = processed_element

        data = {
            'FASADE': processed_fasade_data
        }
    else:
        return

    with open(output_file, 'w', encoding='utf-8') as file:
        json.dump(data, file, separators=(',', ':'), ensure_ascii=False)

def create_zip(file_paths_for_zip, output_dir_for_zip, root_folder, file_name):
    for file_path in file_paths_for_zip:
        if not os.path.isfile(file_path):
            return

    if not os.path.isdir(output_dir_for_zip):
        return

    zip_name = os.path.join('/var/www/flask-api/base/temp/msm_update/', f"{file_name}.zip")
    try:
        with zipfile.ZipFile(zip_name, 'w', compression=zipfile.ZIP_DEFLATED) as zipf:
            for file_path in file_paths_for_zip:
                relative_path = os.path.relpath(file_path, root_folder)
                zipf.write(file_path, relative_path)
    except Exception as e:
        pass

def load_created_ids(ids_file):
    with open(ids_file, 'r', encoding='utf-8') as f:
        return [line.strip() for line in f.readlines()]

def remove_elements(json_data, keywords, ids_to_remove):
    ids_to_remove = set(map(str, ids_to_remove))
    removed_ids = []
    if "CATALOG" in json_data and "PRODUCTS" in json_data["CATALOG"]:
        products = json_data["CATALOG"]["PRODUCTS"]
        json_data["CATALOG"]["PRODUCTS"] = {
            k: v for k, v in products.items()
            if not (
                str(v.get("ID")) in ids_to_remove or
                any(re.search(keyword, v.get("NAME", ""), re.IGNORECASE) for keyword in keywords)
            )
        }
        
        removed_ids = [
            v["ID"] for v in products.values() 
            if str(v.get("ID")) in ids_to_remove or
               any(re.search(keyword, v.get("NAME", ""), re.IGNORECASE) for keyword in keywords)
        ]
        
    keys_to_remove = {"vann", "hitechprem", "premium", "sweet"}
    if "CATALOG" in json_data and "SECTIONS_TYPE" in json_data["CATALOG"]:
        for key in keys_to_remove:
            if key in json_data["CATALOG"]["SECTIONS_TYPE"]:
                json_data["CATALOG"]["SECTIONS_TYPE"].pop(key)

    json_data["CATALOG"]["SECTIONS"]["44012"]["PRODUCTS"].remove(2475723)
    json_data["CATALOG"]["SECTIONS"]["44012"]["PRODUCTS"].remove(2475724)
    section_keys_for_dell = ["7292933", "7358946", "7360269", "7360473", "6587528"]
    for key in section_keys_for_dell:
        json_data["CATALOG"]["SECTIONS"][key] = {}

    return json_data, removed_ids

def remove_elements_with_iblock_section(json_data, iblock_section_ids, ids_to_remove):
    iblock_section_ids = set(map(str, iblock_section_ids))
    ids_to_remove = set(map(str, ids_to_remove))

    removed_ids = {}
    def recursive_remove(parent, parent_key=None):
        if isinstance(parent, dict):
            keys_to_remove = []
            for key, value in parent.items():
                if isinstance(value, (dict, list)):
                    recursive_remove(value)

                if key == "IBLOCK_SECTION_ID" and str(value) in iblock_section_ids:
                    keys_to_remove.append(key)
                    id_value = str(parent.get("ID", None))
                    removed_ids.setdefault(str(value), []).append(id_value)
                if key == "ID" and str(value) in ids_to_remove:
                    keys_to_remove.append(key)
                    removed_ids.setdefault(None, []).append(str(value))

            for key in keys_to_remove:
                if parent_key:
                    parent[parent_key] = None
                else:
                    parent.clear()

        elif isinstance(parent, list):
            items_to_remove = []
            for idx, item in enumerate(parent):
                if isinstance(item, (dict, list)):
                    recursive_remove(item)

                if isinstance(item, (str, int)) and str(item) in ids_to_remove:
                    items_to_remove.append(idx)

            for idx in reversed(items_to_remove):
                del parent[idx]

            if len(parent) == 0 and parent_key:
                parent[parent_key] = None

    recursive_remove(json_data)
    
    return json_data, removed_ids

def remove_elements_by_id_in_file(json_data, ids_to_remove):
    if isinstance(json_data, dict):
        for key in list(json_data.keys()):
            if isinstance(json_data[key], dict):
                remove_elements_by_id_in_file(json_data[key], ids_to_remove)
            elif key == "ID" and json_data[key] in ids_to_remove:
                del json_data[key]
    elif isinstance(json_data, list):
        for item in json_data:
            remove_elements_by_id_in_file(item, ids_to_remove)

    return json_data

def restructure_universe_module_color(json_data):
    ids_to_update = ["3954672", "1942652", "5168676", "1446864"]
    new_values = [199675, 768686, 7403]
    
    for product_id in ids_to_update:
        path_to_key = ["CATALOG", "PRODUCTS", product_id, "MODULECOLOR"]
        current = json_data
        for key in path_to_key[:-1]:
            if isinstance(current, dict) and key in current:
                current = current[key]
            else:
                break
        
        final_key = path_to_key[-1]
        if isinstance(current, dict) and final_key in current:
            if isinstance(current[final_key], dict):
                current[final_key] = list(current[final_key].values())
            
            current[final_key] = new_values
            
    return json_data

def add_ids_to_facade(json_data, created_ids):
    if 'CATALOG' in json_data and isinstance(json_data['CATALOG'], dict):
        catalog = json_data['CATALOG']
        if 'PRODUCTS' in catalog and isinstance(catalog['PRODUCTS'], dict):
            products = catalog['PRODUCTS']
            for product_id, product_data in products.items():
                if isinstance(product_data, dict):
                    product_data["tabletop"] = None
                    if int(product_id) in {1281043, 1281044}:
                        continue

                    if 'FACADE' not in product_data or not isinstance(product_data['FACADE'], list):
                        product_data['FACADE'] = []

                    if None in product_data['FACADE']:
                        continue

                    for facade_id in created_ids:
                        if facade_id not in product_data['FACADE']:
                            product_data['FACADE'].append(int(float(facade_id)))
    
    return json_data

def generate_stol_elements(json_data):
    current_id = 91102011
    current_id_compact = 91103011
    created_ids = []
    created_ids_compact = []
    writ_lines = []
    products = json_data.setdefault("CATALOG", {}).setdefault("PRODUCTS", {})
    with sqlite3.connect('/var/www/flask-api/base/fastab.db') as conn:
        cursor = conn.cursor()
        cursor.execute('''
            SELECT manufacturer, name, url
            FROM table_top
        ''')
        rows = cursor.fetchall()

    for manufacturer, name, url in rows:
        stol_width = 3000
        max_stol_width = None
        folder_skif = ""
        depth_max = 600
        height_stol = 40
        prefix = ""
        models_stol = ""
        USLUGI = ""
        HEM = ""
        profile = ""
        CAN_HIDE_EL = 0
        texture_type = ""
        multiplikation = 1
        if manufacturer == "SKIF42":
            multiplikation = 3
            depth_max = 1200
            stol_width = 4200
            height_stol = 40
            max_stol_width = 4200
            prefix = "№"
            new_id = current_id
            current_id += 1
            models_stol = 53981
            CAN_HIDE_EL = 1
            HEM = [1585456, 1585461, 1585463, 1585464, 1585469, 1585471, 1183368, 1183367, 1183366, 1183042, 1183040, 1125807, 1125808, 1058473, 1045109, 1045110, 692790, 692788, 692787, 692786, 692785, 66561, 66318, 99136, 66689, 66555, 66319, 182800, 182804, 182801, 182828, 25660, 25661, 25685, 76456, 249487, 249488, 249489, 249490, 249492, 725525, 746598, 1042210, 1042209, 4610972, 5547920, 182802, 66320, 66321, 211247, 249493, 1042211, 1183369, 1368767, 1585459, 1585460, 1585472, 4136221, 4136222, 4136224, 4136225, 4136231, 4136232, 4136233, 4136234, 4136237, 4136239, 4136241, 5547906, 5547907, 5547908, 5547909, 5547910, 5547911, 5547912, 5547913, 5547914, 5547915, 5547916, 5547917, 5547918, 5547919, 5547922, 5547923, 5547926, 5547927, 5547928, 5547929, 5547930, 5547931, 5547932, 5547933, 5547934, 5547935, 5547936, 5547937, 5547938, 5547939, 5547940, 5547941, 5547943, 5547946, 5547947, 5547948, 5547950, 5547951, 5547952, 5547955, 5548780, 5798650, 5798656, 5798667]
            USLUGI = [98683]
            profile = [251701, 251698, 251699]
            texture_type = "fill"
        elif manufacturer == "SKIF":
            multiplikation = 1
            height_stol = 40
            prefix = "№"
            new_id = current_id
            current_id += 1
            models_stol = 53981
            CAN_HIDE_EL = 1
            HEM = [1585456, 1585461, 1585463, 1585464, 1585469, 1585471, 1183368, 1183367, 1183366, 1183042, 1183040, 1125807, 1125808, 1058473, 1045109, 1045110, 692790, 692788, 692787, 692786, 692785, 66561, 66318, 99136, 66689, 66555, 66319, 182800, 182804, 182801, 182828, 25660, 25661, 25685, 76456, 249487, 249488, 249489, 249490, 249492, 725525, 746598, 1042210, 1042209, 4610972, 5547920, 182802, 66320, 66321, 211247, 249493, 1042211, 1183369, 1368767, 1585459, 1585460, 1585472, 4136221, 4136222, 4136224, 4136225, 4136231, 4136232, 4136233, 4136234, 4136237, 4136239, 4136241, 5547906, 5547907, 5547908, 5547909, 5547910, 5547911, 5547912, 5547913, 5547914, 5547915, 5547916, 5547917, 5547918, 5547919, 5547922, 5547923, 5547926, 5547927, 5547928, 5547929, 5547930, 5547931, 5547932, 5547933, 5547934, 5547935, 5547936, 5547937, 5547938, 5547939, 5547940, 5547941, 5547943, 5547946, 5547947, 5547948, 5547950, 5547951, 5547952, 5547955, 5548780, 5798650, 5798656, 5798667]
            USLUGI = [98683]
            profile = [251701, 251698, 251699]
            texture_type = "fill"
        elif manufacturer == "SENSOLA":
            multiplikation = 1
            depth_max = 1300
            stol_width = 3000
            height_stol = 12
            prefix = "Compact ламинат "
            new_id = current_id_compact
            current_id_compact += 1
            models_stol = 85461
            CAN_HIDE_EL = 0
            USLUGI = [98683]
            HEM = [None]
            profile = [None]
            texture_type = [None]
            
        new_element = {
            "ID": new_id,
            "SORT": 500,
            "NAME": f"Столешница {prefix}{name} HPL {stol_width}*{depth_max}*{height_stol}",
            "IPROPERTY_VALUES": {
                "ELEMENT_PAGE_TITLE": None,
                "ELEMENT_META_TITLE": None,
                "ELEMENT_META_DESCRIPTION": None,
                "SECTION_META_TITLE": None,
                "SECTION_META_DESCRIPTION": None,
                "SECTION_PAGE_TITLE": None
            },
            "FACADE": [
                None
            ],
            "OPTION": [
                None
            ],
            "GLASS": [
                None
            ],
            "MILLING": [
                None
            ],
            "CITY": [
                None
            ],
            "COLOR": [
                None
            ],
            "SIZE_EDIT": "optional",
            "SIZE_EDIT_HEIGHT": [
                None
            ],
            "SIZE_EDIT_WIDTH_MIN": None,
            "SIZE_EDIT_WIDTH_MAX": max_stol_width,
            "SIZE_EDIT_HEIGHT_MIN": None,
            "SIZE_EDIT_HEIGHT_MAX": None,
            "SIZE_EDIT_WIDTH": [
                None
            ],
            "models": [
                models_stol
            ],
            "width": 3000,
            "depth": 600,
            "element_type": None,
            "tabletop": None,
            "height": height_stol,
            "HEM": HEM,
            "SIZE_EDIT_STEP_WIDTH": "#Y# <= 600 ? 1 : 2;",
            "SIZE_EDIT_TERMS_MULTIPLICITY": "#Z# <= 600 ? 1 : 2;",
            "SIZE_EDIT_STEP_HEIGHT": None,
            "texture": {
                "src": f"https://shadow-diaso.su/api/table_top/{manufacturer}/TEXTURE/{url}",
                "width": 600,
                "height": 960,
                "size": 45224
            },
            "INCITY": [
                None
            ],
            "plinth_length": None,
            "disable_raycast": 0,
            "count_in_basket": None,
            "SIZE_EDIT_STEP_DEPTH": 10,
            "SIZE_EDIT_DEPTH": [
                None
            ],
            "SIZE_EDIT_DEPTH_MIN": 200,
            "SIZE_EDIT_DEPTH_MAX": depth_max,
            "MILLING_ALT": None,
            "USLUGI": USLUGI,
            "SIZE_EDIT_CALC_TYPE": "multiplicity_conditions",
            "FILLING": [
                None
            ],
            "leg_length": 0,
            "profile": profile,
            "FACADEALIGNSELECT": None,
            "substitution_width": None,
            "substitution_height": None,
            "substitution_depth": None,
            "texture_type": texture_type,
            "texture_rotation": None,
            "texture_scale": None,
            "EN_NAME": None,
            "MODULECOLOR": [
                None
            ],
            "SHELFQUANT": None,
            "type_showcase": [
                None
            ],
            "fasade_type": [
                None
            ],
            "other_models": [
                None
            ],
            "DE_NAME": None,
            "FASADE_SIZES": [
                None
            ],
            "texture_map": None,
            "ACTUAL_DEPT": None,
            "IS_BOX_SECTION": 0,
            "CAN_HIDE_EL": CAN_HIDE_EL,
            "SIZE_EDIT_JOINDEPTH_MIN": None,
            "SIZE_EDIT_JOINDEPTH_MAX": None,
            "PRODUCT_MECHANISM": [
                None
            ],
            "DATA_PETROVICH": None,
            "CNSTR_MIN_WIDTH": None,
            "NULL_PRICE": 0,
            "TEST": 0,
            "MIN_FASADE_SIZE": None,
            "MAX_FASADE_SIZE": None,
            "LOOPSIDE": [
                None
            ],
            "REC_HEM": [
                None
            ],
            "productType": None,
            "DOP_PRODUCT": [
                "11381553"
            ],
            "HANDLES": [
                None
            ],
            "canSetSideProfile": 0,
            "BACKWALL": [
                None
            ],
            "SIDEWALL": [
                None
            ],
            "ALTERNATIVE_PRODUCT": [
                41055,
                66552,
            ],
            "DOUBLE_TABLE": 0,
            "LANG": "ru",
            "OPTIONSECTION_ID": False,
            "PREVIEW_PICTURE": f"https://shadow-diaso.su/api/table_top/{manufacturer}/PREVIEW_PICTURE/{url}",
            "FILLING_SECTION": False,
            "MULTIPLIKATION": multiplikation
        }

        products[new_id] = new_element
        if manufacturer == "SENSOLA":
            created_ids_compact.append(new_id)
        else:
            created_ids.append(new_id)
        
        writ_line = {
            "id": new_id,
            "name": f"Столешница {prefix}{name} HPL {stol_width}*{depth_max}*{height_stol}"
        }
        writ_lines.append(writ_line)
    return json_data, created_ids, created_ids_compact, writ_lines

def generate_sten_elements(json_data):
    current_id = 91104011
    current_id_compact = 91105011
    created_ids = []
    created_ids_compact = []
    writ_lines = []
    products = json_data.setdefault("CATALOG", {}).setdefault("PRODUCTS", {})
    with sqlite3.connect('/var/www/flask-api/base/fastab.db') as conn:
        cursor = conn.cursor()
        cursor.execute('''
            SELECT manufacturer, name, url
            FROM table_top
        ''')
        rows = cursor.fetchall()

    for manufacturer, name, url in rows:
        stol_width = 3000
        max_stol_width = None
        folder_skif = ""
        depth_max = 600
        height_stol = 40
        prefix = ""
        if manufacturer == "SKIF42":
            stol_width = 4200
            height_stol = 6
            max_stol_width = 4200
            prefix = "№"
            new_id = current_id
            current_id += 1
        elif manufacturer == "SKIF":
            height_stol = 6
            prefix = "№"
            new_id = current_id
            current_id += 1
        elif manufacturer == "SENSOLA":
            depth_max = 1300
            stol_width = 3000
            height_stol = 4
            prefix = "Compact ламинат "
            new_id = current_id_compact
            current_id_compact += 1
            
        new_element = {
            "ID": new_id,
            "SORT": 500,
            "NAME": f"Фальш-панель {prefix}{name} HPL {stol_width}*{depth_max}*{height_stol}",
            "IPROPERTY_VALUES": {
                "ELEMENT_PAGE_TITLE": None,
                "ELEMENT_META_TITLE": None,
                "ELEMENT_META_DESCRIPTION": None,
                "SECTION_META_TITLE": None,
                "SECTION_META_DESCRIPTION": None,
                "SECTION_PAGE_TITLE": None
            },
            "FACADE": [
                None
            ],
            "OPTION": [
                None
            ],
            "GLASS": [
                None
            ],
            "MILLING": [
                None
            ],
            "CITY": [
                None
            ],
            "COLOR": [
                None
            ],
            "SIZE_EDIT": "optional",
            "SIZE_EDIT_HEIGHT": [
                None
            ],
            "SIZE_EDIT_WIDTH_MIN": stol_width,
            "SIZE_EDIT_WIDTH_MAX": None,
            "SIZE_EDIT_HEIGHT_MIN": None,
            "SIZE_EDIT_HEIGHT_MAX": depth_max,
            "SIZE_EDIT_WIDTH": [
                None
            ],
            "models": [
                66339
            ],
            "width": 3000,
            "depth": height_stol,
            "element_type": "element_up",
            "tabletop": None,
            "height": 600,
            "HEM": [
                None
            ],
            "SIZE_EDIT_STEP_WIDTH": 1,
            "SIZE_EDIT_TERMS_MULTIPLICITY": "#Y# <= 600 ? 1 : 2;",
            "SIZE_EDIT_STEP_HEIGHT": 5,
            "texture": {
                "src": f"https://shadow-diaso.su/api/table_top/{manufacturer}/TEXTURE/{url}",
                "width": 600,
                "height": 960,
                "size": 45224
            },
            "INCITY": [
                None
            ],
            "plinth_length": None,
            "disable_raycast": 1,
            "count_in_basket": None,
            "SIZE_EDIT_STEP_DEPTH": None,
            "SIZE_EDIT_DEPTH": [
                None
            ],
            "SIZE_EDIT_DEPTH_MIN": None,
            "SIZE_EDIT_DEPTH_MAX": None,
            "MILLING_ALT": None,
            "USLUGI": [
                None
            ],
            "SIZE_EDIT_CALC_TYPE": "multiplicity_conditions",
            "FILLING": [
                None
            ],
            "leg_length": 0,
            "profile": [
                None
            ],
            "FACADEALIGNSELECT": None,
            "substitution_width": None,
            "substitution_height": None,
            "substitution_depth": None,
            "texture_type": None,
            "texture_rotation": None,
            "texture_scale": None,
            "EN_NAME": None,
            "MODULECOLOR": [
                None
            ],
            "SHELFQUANT": None,
            "type_showcase": [
                None
            ],
            "fasade_type": [
                None
            ],
            "other_models": [
                None
            ],
            "DE_NAME": None,
            "FASADE_SIZES": [
                None
            ],
            "texture_map": None,
            "ACTUAL_DEPT": None,
            "IS_BOX_SECTION": 0,
            "CAN_HIDE_EL": 0,
            "SIZE_EDIT_JOINDEPTH_MIN": None,
            "SIZE_EDIT_JOINDEPTH_MAX": None,
            "PRODUCT_MECHANISM": [
                None
            ],
            "DATA_PETROVICH": None,
            "CNSTR_MIN_WIDTH": None,
            "NULL_PRICE": 0,
            "TEST": 0,
            "MIN_FASADE_SIZE": None,
            "MAX_FASADE_SIZE": None,
            "LOOPSIDE": [
                None
            ],
            "REC_HEM": [
                None
            ],
            "productType": None,
            "DOP_PRODUCT": [
                "11381553"
            ],
            "HANDLES": [
                None
            ],
            "canSetSideProfile": 0,
            "BACKWALL": [
                None
            ],
            "SIDEWALL": [
                None
            ],
            "ALTERNATIVE_PRODUCT": [
                41055,
                66552,
            ],
            "DOUBLE_TABLE": 0,
            "LANG": "ru",
            "OPTIONSECTION_ID": False,
            "PREVIEW_PICTURE": f"https://shadow-diaso.su/api/table_top/{manufacturer}/PREVIEW_PICTURE/{url}",
            "FILLING_SECTION": False
        }

        products[new_id] = new_element
        if manufacturer == "SENSOLA":
            created_ids_compact.append(new_id)
        else:
            created_ids.append(new_id)

        writ_line = {
            "id": new_id,
            "name": f"Столешница {prefix}{name} HPL {stol_width}*{depth_max}*{height_stol}"
        }
        writ_lines.append(writ_line)

    return json_data, created_ids, created_ids_compact, writ_lines

def generate_fasades_elements(json_data):
    current_id = 91100011
    created_ids = []
    if "FASADE" not in json_data:
        json_data["FASADE"] = {}

    fasade_data = json_data["FASADE"]
    
    with sqlite3.connect('/var/www/flask-api/base/fastab.db') as conn:
        cursor = conn.cursor()
        cursor.execute('''
            SELECT manufacturer, name, url
            FROM fasades
        ''')
        rows = cursor.fetchall()

    for manufacturer, name, url in rows:
        eg_lam = None
        width_img = None
        
        if manufacturer == "lamarty":
            eg_lam = 878
            width_img = 768
        elif manufacturer == "egger":
            eg_lam = 1628
            width_img = 713
        else:
            eg_lam = 0
            width_img = 0
        
        new_element = {
            "ID": current_id,
            "NAME": name,
            "IBLOCK_SECTION_ID": f"{eg_lam}",
            "DETAIL_PICTURE": f"https://shadow-diaso.su/api/fasades/{manufacturer}/DETAIL_PICTURE/{url}",
            "SORT": 0,
            "TEST": None,
            "EN_NAME": None,
            "ADMIN_COMMENT": None,
            "ARTICLE": None,
            "date_shipment": None,
            "delay_date": 0,
            "date_build": 7,
            "DEPTH": 16,
            "CNAME": None,
            "TEXTURE_DIRECTION": None,
            "NOT_IN_KONSTRUKTOR": "N",
            "TEXTURE": f"https://shadow-diaso.su/api/fasades/{manufacturer}/TEXTURE/{url}",
            "SHININESS": 10,
            "SCALE": 1,
            "COLOR": False,
            "TYPE": "standart",
            "EDGE_COLOR": False,
            "MODEL": None,
            "EDGE_TEXTURE": None,
            "SIBLINGS_COLOR": None,
            "ATTACH_MILLINGS": [None],
            "ALT_MILLINGS": [None],
            "ATTACH_GLASS": [
                76033, 7383, 76034, 76032, 1451550, 1451548, 1451547,
                1451546, 1941974, 2897608, 2897607
            ],
            "no_fasade": "N",
            "FACADEALIGNSELECT": 0,
            "HANDLECOLOR": [None],
            "PATINA": [None],
            "PALETTE": [None],
            "type_showcase": [None],
            "ELEMENT_TYPE": None,
            "fasade_type": [None],
            "REACH": None,
            "GLASS_ONLY": 0,
            "options": [4722787, 4722786],
            "back_color": 199675,
            "MATERIAL": "ЛДСП 18 мм",
            "BUMP": 0,
            "INCITY": [None],
            "CITY": [None],
            "MIN_WIDTH": [None],
            "MIN_HEIGHT": [None],
            "DENSITY": "680",
            "DISCOUNT_25": None,
            "PREVIEW_PICTURE": f"https://shadow-diaso.su/api/fasades/{manufacturer}/PREVIEW_PICTURE/{url}",
            "TEXTURE_HEIGHT": 1536,
            "TEXTURE_WIDTH": width_img,
            "MANUFACTURER": manufacturer
        }

        fasade_data[current_id] = new_element
        created_ids.append(current_id)
        current_id += 1

    return json_data, created_ids

def add_option_sves_and_replace_vrd_names(data):
    options_to_remove = [999079, 3967991, 2060375, 7117874, 7117897, 5718427, 5718428, 5718429, 5718430, 5718431, 5718433, 5718434, 5718435, 5718436, 1000284, 4567387, 5543582, 5543583, 5546672, 5546673, 5546674, 5546675, 5552648, 5552651, 5709662, 5709663, 5709666, 5709667, 5733273, 5543585, 5543588, 5673968, 5673969, 5543594, 5543595, 5673957, 5673958, 1807483, 4682392, 3967991, 1792593, 589399, 4682392]
    def replace_values(obj):
        if isinstance(obj, dict):
            for key, value in obj.items():
                if isinstance(value, str):
                    obj[key] = value.replace("Лего Формат 5", "Общий итог").replace("KRONO 18мм", "KRONO & LAMARTY").replace("EGGER 18мм", "EGGER").replace("Нестандартный корпус Вардек, задняя стенка ХДФ", "Нестандартный корпус, задняя стенка ХДФ").replace("VRD", "").replace("Вардек", "DIA").replace("ЛДСП", "HPL").replace("VARDEK", "DIA").replace("ВАРДЕК", "DIA")
                else:
                    replace_values(value)
        elif isinstance(obj, list):
            for item in obj:
                replace_values(item)

    replace_values(data)

    if 'CATALOG' in data and isinstance(data['CATALOG'], dict):
        if 'PRODUCTS' in data['CATALOG'] and isinstance(data['CATALOG']['PRODUCTS'], dict):
            for model_id, model_data in data['CATALOG']['PRODUCTS'].items():
                if isinstance(model_data, dict):
                    name = model_data.get('NAME', '').strip().lower()
                    model_data['OPTION'] = [opt for opt in model_data['OPTION'] if opt not in options_to_remove]
                    if 'шкаф' in name or 'шкаф-витрина' in name or 'модуль нестандарт' in name or 'нестандартный корпус' in name or 'нестандартный фасад' in name or 'нестандартное полотно' in name:
                        if model_data.get("tabletop") is None:
                            if 'OPTION' in model_data and isinstance(model_data['OPTION'], list):
                                if 9110000 not in model_data['OPTION']:
                                    model_data['OPTION'].append(9110000)
                            else:
                                model_data['OPTION'] = [9110000]

    new_option = {
        "ID": "9110000",
        "NAME": "Свес Фасада (+20мм)",
        "IBLOCK_SECTION_ID": [],
        "IMG": None,
        "CITY": [],
        "INCITY": [],
        "FILLING": [],
        "CLOSE_OTHER_OPTIONS": "0",
        "SHOW_ON_FASADE": [],
        "SHOW_ON_WITH": [],
        "GROUP": None
    }

    if 'OPTION' not in data:
        data['OPTION'] = {new_option['ID']: new_option}
    else:
        if isinstance(data['OPTION'], dict):
            if new_option['ID'] not in data['OPTION']:
                data['OPTION'][new_option['ID']] = new_option
    
    return data

def write_line_ids(ids_file_path, created_ids):
    with open(ids_file_path, 'w', encoding='utf-8') as f:
        for id_value in created_ids:
            f.write(str(id_value) + '\n')

new_functions_replace = """
let multiplicationValue = null;
this.getBasketPrice = function (callback) {
    self.scope.app.block_cart = true;
    self.scope.$applyAsync();
    if (self.timer) {
        clearTimeout(self.timer);
    }
    callback = callback || new Function();
    if (!Object.keys(self.scope.app.basket).length && self.scope.app.oldPrice) return;
    self.calcElementsGroup();
    chrome.storage.local.get("multiplicationValue", function(data) {
        if (multiplicationValue === null) {
            if (data.multiplicationValue !== undefined) {
                multiplicationValue = data.multiplicationValue;
                console.log("Loaded multiplication value from storage:", multiplicationValue);
            } else {
                console.log("Multiplication value not found in storage.");
            }
        } else {
            console.log("Using already defined multiplication value:", multiplicationValue);
        }
    });
    self.timer = setTimeout(function () {
        var data = {
            options: JSON.stringify(self.scope.project.options),
            basket: JSON.stringify(self.scope.app.basket),
            city: self.scope.project.city,
            custom_price_type: self.scope.app.SETTINGS.PRICE_TYPE_STYLE,
        };
        const facadeRanges = [
            { min: 91100011, max: 91102000, replacement: 178591 },
            { min: 91102011, max: 91103000, replacement: 38916, useMultiplikationField: false },
            { min: 91103011, max: 91104000, replacement: 5979586, multiplier: 1.4 },
            { min: 91104011, max: 91105000, replacement: 66592 },
            { min: 91105011, max: 91106000, replacement: 66592, multiplier: 5 }
        ];
        function adjustBasketItems(basket) {
            for (let itemKey in basket) {
                if (basket.hasOwnProperty(itemKey)) {
                    let item = basket[itemKey];
                    for (let range of facadeRanges) {
                        if (range.min === 91100011 && range.max === 91102000) {
                            if (item.PROPS && item.PROPS.FASADE1) {
                                let facadeKey = Object.keys(item.PROPS.FASADE1)[0];
                                let facadeValue = item.PROPS.FASADE1[facadeKey];
                                
                                if (facadeValue >= range.min && facadeValue <= range.max) {
                                    item.PROPS.FASADE1[facadeKey] = range.replacement;
                                }
                            }
                        } else {
                            if (item.ID >= range.min && item.ID <= range.max) {
                                if (range.useMultiplikationField && self.scope.app.CATALOG.PRODUCTS[item.ID]?.MULTIPLIKATION) {
                                    const multiplier = self.scope.app.CATALOG.PRODUCTS[item.ID].MULTIPLIKATION;
                                    item.QUANTITY = (item.QUANTITY || 1) * multiplier;
                                } else if (range.multiplier) {
                                    item.QUANTITY = (item.QUANTITY || 1) * range.multiplier;
                                }
                                item.ID = range.replacement;
                                break;
                            }
                        }
                    }
                }
            }
        }
        let modifiedBasket = JSON.parse(JSON.stringify(self.scope.app.basket));
        adjustBasketItems(modifiedBasket);
        let modifiedData = {
            options: JSON.stringify(self.scope.project.options),
            basket: JSON.stringify(modifiedBasket),
            city: self.scope.project.city,
            custom_price_type: self.scope.app.SETTINGS.PRICE_TYPE_STYLE,
        };
        $.ajax({
            type: "POST",
            url: self.scope.TEMPLATE_PATH + "/API/data.basket.getprice.php",
            data: modifiedData,
            dataType: "json"
        }).then(function (response) {
            let total = parseFloat(response.total.replace(/[^\d.]/g, '')) || 0;
            let finalPrice = Math.round(total * multiplicationValue);
            self.scope.app.totalprice = finalPrice + ' руб';
            self.scope.app.oldPrice = response.oldPrice;
            self.scope.$apply();
            callback();
            self.scope.app.block_cart = false;
            self.scope.$applyAsync();
        }).catch(function (error) {
            self.scope.app.block_cart = false;
            self.scope.$applyAsync();
        });

        self.autoSave();
    }, 500);
    return null;
};
"""
new_functions_replace_2 = """
this.getBasket = function (callback, getprice) {
    var callback = callback || new Function();
    self.scope.app.block_cart = true
    self.scope.$applyAsync();
    self.calcElementsGroup();
    $.ajax({
        type: "POST",
        url: self.scope.TEMPLATE_PATH + "/API/data.basket.get.php",
        data: {
            options: JSON.stringify(self.scope.project.options),
            basket: JSON.stringify(self.scope.app.basket),
            city: self.scope.project.city,
            dataProvider: self.scope.app.config.barcode_id
                ? self.scope.app.config.barcode_id
                : self.scope.app.config.dataProvider,
            basketgroup: self.scope.app.config.basketgroup,
            config: self.scope.app.config.config,
            style: self.scope.app.config.style,
            custom_price_type: self.scope.app.SETTINGS.PRICE_TYPE_STYLE,
        },
        dataType: "json",
        success: function (dta, s) {
            var products = self.filterErrorProduct(dta.items);
            self.scope.app.basketFrame = products.ok;
            self.scope.app.basketMessage = dta.message;
            self.scope.app.basketFrameOther = products.other;
            self.scope.app.basketFrameError = products.err;
            self.scope.app.basketFramePropError = products.propErr;
            self.scope.$apply();

            self.scope.app.block_cart = false
            self.scope.$applyAsync();

            if (!getprice) {
                self.getBasketPrice(callback);
            } else {
                callback()
            }
            return dta;
        },
    });
};
"""

new_functions_replace_3 = """
this.filterErrorProduct = function (product) {
    var result = {
        ok: [],
        err: [],
        propErr: [],
        other: [],
        decor: [],
        propDepthError: [],
    };
    angular.forEach(product, function (i) {
        var type = "ok";
        let errorMessages = [];
        const catalogProduct = self.scope.app.CATALOG.PRODUCTS[self.scope.app.basket[i.obj_id]?.ID];
        if (catalogProduct) {
            i.NAME = catalogProduct.NAME || "Неизвестный элемент";
        } else {
            errorMessages.push(`Элемент ID ${i.obj_id} отсутствует в CATALOG.PRODUCTS, NAME не найден.`);
        }
        if (
            self.scope.project.items[i.obj_id]?.["TYPE"] !== undefined &&
            self.scope.project.items[i.obj_id]?.TYPE === "CATALOG"
        ) {
            type = i.ACTIVE === "Y" ? "other" : "err";
            if (type === "err") {
                errorMessages.push("Элемент неактивен (ACTIVE !== 'Y').");
            }
        } else if (
            self.scope.project.items[i.obj_id] === undefined ||
            self.scope.app.basket[i.obj_id]?.["ID"] === undefined ||
            catalogProduct === undefined || // проверка, есть ли элемент в CATALOG.PRODUCTS
            catalogProduct.count_in_basket === 0 ||
            (i.PRICE === 0 && !self.scope.app.decor) ||
            i.ACTIVE === "N"
        ) {
            type = "err";
            if (!self.scope.project.items[i.obj_id]) {
                errorMessages.push("Элемент не найден в project.items.");
            }
            if (!self.scope.app.basket[i.obj_id]?.["ID"]) {
                errorMessages.push("Элемент не имеет ID в basket.");
            }
            if (!catalogProduct) {
                errorMessages.push("Элемент отсутствует в CATALOG.PRODUCTS.");
            }
            if (i.ACTIVE === "N") {
                errorMessages.push("Элемент не активен.");
            }
        } else if (i.props_error != null) {
            if (i.props_error[0]) {
                type = "propErr";
                errorMessages.push("Ошибка свойств элемента (props_error).");
            }
        }
        for (let secNumber = 1; secNumber <= 10; secNumber++) {
            const sect = "SECTIONSFILLING" + secNumber;
            if (i.PROPS[sect]) {
                angular.forEach(i.PROPS[sect], function (el) {
                    const product = self.scope.app.CATALOG.PRODUCTS[el.ID];
                    if (!product) {
                        errorMessages.push(`Элемент ID ${el.ID} не найден в CATALOG.PRODUCTS.`);
                        type = "propErr";
                    } else {
                        if (product.ACTUAL_DEPT && product.ACTUAL_DEPT >= i.PROPS.SIZEEDITDEPTH) {
                            errorMessages.push(
                                `Превышена разрешенная глубина для ID ${el.ID}: ACTUAL_DEPT ${product.ACTUAL_DEPT} >= SIZEEDITDEPTH ${i.PROPS.SIZEEDITDEPTH}`
                            );
                            type = "propErr";
                        }
                        if (product.CNSTR_MIN_WIDTH && i.PROPS["SECTIONS" + secNumber] &&
                            product.CNSTR_MIN_WIDTH > i.PROPS["SECTIONS" + secNumber]) {
                            errorMessages.push(
                                `Превышена минимальная ширина для ID ${el.ID}: CNSTR_MIN_WIDTH ${product.CNSTR_MIN_WIDTH} > SECTIONS${secNumber} ${i.PROPS["SECTIONS" + secNumber]}`
                            );
                            type = "propErr";
                        }
                        if (el.VALUE !== null && el.VALUE === 0) {
                            errorMessages.push(`Значение VALUE для ID ${el.ID} равно нулю.`);
                            type = "propErr";
                        }
                    }
                });
            }
        }
        if (i.QUANTITY) i.QUANTITY = +i.QUANTITY;
        result[type].push(i);
    });
    return result;
};
"""

new_functions_replace_4 = """
this.export = function () {
    self.exportGLTF(self.scene);
};
"""

new_functions_replace_5 = """
this.exportGLTF = function (input) {
    var gltfExporter = new THREE.GLTFExporter();

    const fileName = self.scope.project.name || "scene";
    input.traverse((child) => {
        if (child.isMesh && child.material.opacity < 1) {
            const color = child.material.color.getHex();
            if (color !== 0x000000) {
                child.visible = false;
            }
        }
    });

    var options = {
        binary: false,
        onlyVisible: true,
        embedImages: true,
        forcePowerOfTwoTextures: true,
    };

    gltfExporter.parse(
        input,
        function (result) {
            if (result instanceof ArrayBuffer) {
                self.saveArrayBuffer(result, `${fileName}.glb`);
            } else {
                var output = JSON.stringify(result);
                self.saveString(output, `${fileName}.gltf`);
            }
        },
        options
    );

    self.ExportLink = document.createElement("a");
    self.ExportLink.style.display = "none";
    document.body.appendChild(self.ExportLink);
};
"""

new_functions_replace_backhome = """
this.getNewProject = function () {
    $("#newProject").modal({keyboard: false, backdrop: "static", handleUpdate: true});
};

this.sub_main = function () {
    window.location.href = "file://" + nw.__dirname + "/index.html";
};
"""

replace_comment_export = """
export: {
                    name: 'Экспорт', 
                    icon: 'glyphicon glyphicon-share',
                    type: 'func', 
                    tooltip: 'Экспорт', 
                    placement: 'left', 
                    parent:'right'
                },
"""

def replace_js_function(constructor_path):
    replaces = {
        "getBasketPrice": {"code": new_functions_replace, "count": 0},
        "getBasket": {"code": new_functions_replace_2, "count": 0},
        "filterErrorProduct": {"code": new_functions_replace_3, "count": 0},
        "export": {"code": new_functions_replace_4, "count": 0},
        "exportGLTF": {"code": new_functions_replace_5, "count": 0},
        "getNewProject": {"code": new_functions_replace_backhome, "count": 0}
    }
    with open(constructor_path, 'r', encoding='utf-8') as file:
        pre_content = file.read()
        
    pattern_export = r"\s*/\*'export': \{name: 'Экспорт', icon: 'glyphicon glyphicon-edit', type: 'func', tooltip: 'Экспорт', placement: 'left', parent:'right'\},\*/"
    content = re.sub(pattern_export, replace_comment_export, pre_content)
    for function_name, data in replaces.items():
        if data["count"] == 0:
            new_functions_code = data["code"]
            function_start_pattern = rf"([ \t]*)this\.{function_name}\s*=\s*function\s*\([^)]*\)\s*{{"
            match = re.search(function_start_pattern, content, flags=re.MULTILINE)
            if match:
                start_pos = match.start()
                indent = match.group(1)
                open_brackets = 1
                end_pos = match.end()

                while open_brackets > 0 and end_pos < len(content):
                    if content[end_pos] == '{':
                        open_brackets += 1
                    elif content[end_pos] == '}':
                        open_brackets -= 1
                    end_pos += 1

                if content[end_pos:end_pos + 1] == ";":
                    end_pos += 1

                indented_code = "\n".join(indent + line for line in new_functions_code.splitlines())
                content = content[:start_pos] + indented_code + content[end_pos:]
                
                data["count"] += 1


    with open(constructor_path, 'w', encoding='utf-8') as file:
        file.write(content)

def replace_js_consts(constructor_path, color_replacements):
    with open(constructor_path, 'r', encoding='utf-8') as file:
        content = file.read()
        
    for old_color, new_color in color_replacements.items():
        set_clear_color_pattern = rf'self\.renderer\.setClearColor\(self\.scope\.outlineType\s*\?\s*["\']#ffffff["\']\s*:\s*["\']{old_color}["\']\);'
        content = re.sub(set_clear_color_pattern, f'self.renderer.setClearColor(self.scope.outlineType ? "#ffffff" : "{new_color}");', content)
        line_color_pattern = rf'lineColor:\s*["\']{old_color}["\']'
        content = re.sub(line_color_pattern, f'lineColor: "{new_color}"', content)

    block_pattern = re.compile(r'(sub_main:\s*{[^}]*type:\s*)"tab"(.*?})', re.DOTALL)
    content = re.sub(block_pattern, r'\1"func"\2', content)
    name_pattern = re.compile(r'name:\s*"Новый проект"')
    content = re.sub(name_pattern, 'name: "AP000000"', content)
    technologist_pattern = re.compile(r'technologist\s*:\s*{[^}]*\}\s*,?\s*', re.DOTALL)
    content = re.sub(technologist_pattern, "", content)
    block_patterns = [
        re.compile(r"/\*Начало работы формы технолога\*/(.*?)/\*Конец работы формы технолога\*/", re.DOTALL)
    ]
    for pattern in block_patterns:
        content = re.sub(pattern, "", content)

    content = content.replace("var user_hash = false;", "var user_hash = true;")
    with open(constructor_path, 'w', encoding='utf-8') as file:
        file.write(content)

def start_reconstructors(trigger):
    color_replacements_sale = {
        "#cccccc": "#00ff90",
        "#2F96B4": "#00ff90",
        "red": "#00ff90"
    }
    color_replacements_tech = {
        "#cccccc": "#b267ff",
        "#2F96B4": "#b267ff",
        "red": "#b267ff"
    }
    color_replacements_salon = {
        "#cccccc": "#ffde00",
        "#2F96B4": "#ffde00",
        "red": "#ffde00"
    }
    try:
        if trigger == "yes_constructor":
            replace_js_function("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/constructor.min.js")
            move_file("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/constructor.min.js", "/var/www/flask-api/base/temp/msm_update/msm_tech/data/constructor_tech.min.js")
            move_file("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/constructor.min.js", "/var/www/flask-api/base/temp/msm_update/msm_salon/data/constructor_salon.min.js")
            replace_js_consts("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/constructor.min.js", color_replacements_sale)
            replace_js_consts("/var/www/flask-api/base/temp/msm_update/msm_tech/data/constructor_tech.min.js", color_replacements_tech)
            replace_js_consts("/var/www/flask-api/base/temp/msm_update/msm_salon/data/constructor_salon.min.js", color_replacements_salon)
        elif trigger == "seller_constructor":
            replace_js_function("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/constructor.min.js")
            replace_js_consts("/var/www/flask-api/base/temp/msm_update/msm_sallers/data/constructor.min.js", color_replacements_sale)
        elif trigger == "tech_constructor":
            replace_js_function("/var/www/flask-api/base/temp/msm_update/msm_tech/data/constructor_tech.min.js")
            replace_js_consts("/var/www/flask-api/base/temp/msm_update/msm_tech/data/constructor_tech.min.js", color_replacements_tech)
        elif trigger == "salon_constructor":
            replace_js_function("/var/www/flask-api/base/temp/msm_update/msm_salon/data/constructor_salon.min.js")
            replace_js_consts("/var/www/flask-api/base/temp/msm_update/msm_salon/data/constructor_salon.min.js", color_replacements_salon)
            
        return True
    except Exception as e:
        return (f'Ошибка: {e}')

def debug_liner(text):
    with open('/var/www/app.log', 'a') as file:
        file.write(str(text) + '\n')

def start_structure_data_get_php(trigger=None, new_version=None):
    json_file_path = "/var/www/flask-api/base/temp/msm_update/data.get.json"
    ids_file_path = "/var/www/flask-api/base/temp/msm_update/fasades_ids.txt"
    output_file_for_autorsf = "/var/www/flask-api/base/temp/autorsf/fasade_vrd.json"
    msm_update_dir = "/var/www/flask-api/base/temp/msm_update"
    file_list_delete_1 = ["/var/www/flask-api/base/temp/autorsf/fasade_vrd.json"]
    file_list_delete_2 = ["/var/www/flask-api/base/temp/msm_update/fasades_ids.txt", "/var/www/flask-api/base/temp/msm_update/data.get.json"]
    msm_move_patchs = [
        "/var/www/flask-api/base/temp/msm_update/msm_sallers/data/data.get.php",
        "/var/www/flask-api/base/temp/msm_update/msm_tech/data/data.get.php",
        "/var/www/flask-api/base/temp/msm_update/msm_salon/data/data.get.php"
    ]
    folders_for_create_zips = [
        "/var/www/flask-api/base/temp/msm_update/msm_sallers",
        "/var/www/flask-api/base/temp/msm_update/msm_tech",
        "/var/www/flask-api/base/temp/msm_update/msm_salon"
    ]
    files_version = [
        "/var/www/flask-api/base/temp/msm_update/version.txt",
        "/var/www/flask-api/base/temp/msm_update/version_s/version.txt",
        "/var/www/flask-api/base/temp/msm_update/version_t/version.txt",
        "/var/www/flask-api/base/temp/msm_update/version_sn/version.txt"
    ]
    keywords = ["столешница", "Столешница", "фальш-панель", "Фальш-панель"]
    add_handles = [69920, 594332, 760249, 1441464, 1441471, 1477069, 1477077, 1485393, 1477076, 1477078, 1477080]
    iblock_section_ids = [
        #878, 1461, 1462, 1628, 1853, 1903, 1904, 2226, 2163, 2284, 2294, 2329, 2296, 2562, 2565, 2325, 
        #1852, 2528, 2557, 2392, 2393, 2534, 2531, 2765, 2756, 2550, 2552, 2560, 2305, 1649, 2291, 2292, 
        #2293, 2822, 2390, 2391, 2394, 2306, 2389, 2295, 2821, 1876
    ]
    ids_to_remove_stock_0 = [
        #1931367, 5581912, 5581906, 5581904, 5716095, 1887568, 1833137, 5577864, 4209789, 4203681, 4203683, 
        #4861615, 192412, 5978891, 5978889, 5630717, 3266968, 1550469, 3712979, 5996005, 2565, 2325, 1852, 
        #2528, 2557, 2392, 2393, 2534, 2531, 2765, 2756, 2560, 2305, 1649, 2293, 2822, 7396
    ]
    ids_to_remove_stock = [
        #4066731, 594296, 594320, 594358, 594357, 594356, 594355, 201361,
        #201362, 201366, 201367, 215450, 215452, 594293, 594295, 594298,
        #594302, 594305, 594306, 594309, 594318, 594319, 594323, 594326,
        #594336, 594342, 594349, 596357, 201360, 215448, 594308, 754755,
        #754758, 754759, 754760, 754761, 754762, 754763, 754764, 754765,
        #754766, 754767, 754768, 754771, 754772, 754773, 754774, 745596,
        #745597, 745599, 745603, 745604, 745601, 745605, 745600, 594297,
        #594300, 594301, 594307, 594329, 594330, 594331, 690505, 745602,
        #998851, 1042522, 1042626, 1042627, 1044355, 1044356, 1044357,
        #1044358, 1044361, 1044363, 1048695, 1048696, 1048697, 1048698,
        #1048699, 1048700, 1072833, 1151276, 1151277, 1151278, 1401095,
        #1441461, 1441463, 1441465, 1441466, 1477064, 1477065, 1477070,
        #1477072, 1479516, 1479519, 1485396, 1491147, 1491148, 1491149,
        #1491150, 1491155, 1491158, 1491159, 1491160, 1491161, 1491162,
        #1491163, 1491164, 1491165, 1491166, 1491167, 1491169, 1491170,
        #1506092, 1507585, 1507586, 1507587, 1507588, 1507589, 1507590,
        #1507591, 1507592, 1507593, 1507594, 1441467, 1477066, 1477071,
        #1491168, 6222170, 6222389
    ]
    
    ids_fasades_to_remove = [
        #6698759, 6698758, 6698757, 6698756, 6698677, 6698676, 6698671, 
        #6698668, 6698667, 6698666, 6698664, 6698670, 6698690, 6698739,
        #6698755, 6698751, 6698748, 6698741, 5581902, 5581897, 5581909,
        #5581910, 5581911, 5990531, 5990532, 5990530
    ]
    try:
        perform_authenticated_request(msm_update_dir, trigger=trigger)
        with open(json_file_path, 'r', encoding='utf-8') as f:
            json_data = json.load(f)
        json_data = add_option_sves_and_replace_vrd_names(json_data)
        json_data, removed_ids = remove_elements_with_iblock_section(json_data, iblock_section_ids, ids_to_remove_stock_0)
        ids_to_remove = []
        for ids in removed_ids.values():
            ids_to_remove.extend(ids)
        
        json_data = remove_elements_by_id_in_file(json_data, ids_to_remove)
        json_data, created_ids_for_write = generate_fasades_elements(json_data)
        write_line_ids(ids_file_path, created_ids_for_write)
        json_data, removed_ids = remove_elements(json_data, keywords, ids_to_remove_stock)
        json_data, created_ids, created_ids_compact, writ_lines = generate_stol_elements(json_data)
        created_ids_with_exclude = [69919] + created_ids
        json_data["CATALOG"]["SECTIONS"]["7358837"]["NAME"] = "Столешницы 38мм"
        json_data["CATALOG"]["SECTIONS"]["7358837"]["PRODUCTS"] = list(created_ids_with_exclude)
        json_data["CATALOG"]["SECTIONS"] = json_data["CATALOG"].get("SECTIONS", {})
        json_data["CATALOG"]["SECTIONS"]["4066731"] = json_data["CATALOG"]["SECTIONS"].get("4066731", {})
        json_data["CATALOG"]["SECTIONS"]["167373"] = json_data["CATALOG"]["SECTIONS"].get("167373", {})
        json_data["CATALOG"]["SECTIONS"]["4066731"]["NAME"] = "Столешницы компакт-ламинат"
        json_data["CATALOG"]["SECTIONS"]["4066731"]["PRODUCTS"] = list(created_ids_compact)
        json_data, created_ids_sten, created_ids_compact_sten, writ_lines_sten = generate_sten_elements(json_data)
        json_data["HANDLES"] = {str(id_value): id_value for id_value in add_handles}
        json_data["CATALOG"]["SECTIONS"]["167373"]["PRODUCTS"] = list(created_ids_compact_sten) + list(created_ids_sten)
        for id_fasad in ids_fasades_to_remove:
            json_data["FASADE"][f"{id_fasad}"] = {}
            json_data["CUSTOM_SIDE_COLORS"][f"{id_fasad}"] = {}
            
        created_ids_2 = load_created_ids(ids_file_path)
        json_data = add_ids_to_facade(json_data, created_ids_2)
        json_data = restructure_universe_module_color(json_data)
        delete_files(file_list_delete_1)
        create_json_for_autorsf(json_data, output_file_for_autorsf, 'VRD')
        with open(json_file_path, 'w', encoding='utf-8') as file:
            json.dump(json_data, file, separators=(',', ':'), ensure_ascii=False)
            
        for move_patch in msm_move_patchs:
            move_file(json_file_path, move_patch)
        
        if trigger in ['yes_constructor', 'seller_constructor', 'tech_constructor', 'salon_constructor']:
            start_reconstructors(trigger=trigger)
        
        for folder in folders_for_create_zips:
            file_paths_for_zip = []
            zip_name = ""
            if folder.endswith("sallers"):
                zip_name = "update_msm"
            elif folder.endswith("tech"):   
                zip_name = "update_msm_tech"
            elif folder.endswith("salon"):   
                zip_name = "update_msm_salon"
            if trigger is None:
                file_paths_for_zip.append(os.path.join(folder, 'data', 'data.get.php'))
            elif trigger is not None:
                for root, _, files in os.walk(folder):
                    file_paths_for_zip.extend(os.path.join(root, file) for file in files)
        
            create_zip(file_paths_for_zip, msm_update_dir, folder, zip_name)
        delete_files(file_list_delete_2)
        result = 0
        if new_version == "yes":
            result += 10
            for file_version in files_version:
                update_version_with_limits(file_version)
        
        if trigger == "seller_constructor":
            result += 1
        elif trigger == "tech_constructor":
            result += 2
        elif trigger == "yes_constructor":    
            result += 3
        elif trigger == "salon_constructor":    
            result += 4    
        else:
            result = 0
        return result
            
    except Exception as e:
        return e

def get_personal_data(table_name, column_name):
    try:
        with get_db_connection() as conn:
            cursor = conn.cursor()
            query = f"SELECT {column_name} FROM {table_name}"
            cursor.execute(query)
            rows = cursor.fetchall()
                
        return [row[0] for row in rows]
    except sqlite3.Error as e:
        pass
    except Exception as e:
        pass

def create_inline_buttons(button_data):
    keyboard = types.InlineKeyboardMarkup(row_width=3)
    buttons = [
        types.InlineKeyboardButton(button, callback_data=f"kick:{button}")
        for button in button_data if button is not None
    ]
    close = types.InlineKeyboardButton("Закрыть", callback_data=f"close")
    keyboard.add(*buttons)
    keyboard.add(close)
    return keyboard

def generate_key(length):
    characters = string.ascii_uppercase + string.digits
    random_string = ''.join(random.choices(characters, k=length))
    
    return random_string

def get_db_connection():
    conn = sqlite3.connect('/var/www/flask-api/base/personal.db')
    return conn

def add_or_update(table_name, data, where_column):
    try:
        with get_db_connection() as conn:
            cursor = conn.cursor()
            where_value = data.get(where_column)
            cursor.execute(f"SELECT 1 FROM {table_name} WHERE {where_column} = ?", (where_value,))
            exists = cursor.fetchone()
            if exists:
                set_clause = ", ".join([f"{col} = ?" for col in data.keys()])
                values = list(data.values()) + [where_value]
                query = f"UPDATE {table_name} SET {set_clause} WHERE {where_column} = ?"
            else:
                columns = ", ".join(data.keys())
                placeholders = ", ".join(["?"] * len(data))
                values = list(data.values())
                query = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"

            cursor.execute(query, values)
            conn.commit()
    except Exception as e:
        return e

def kick_user(table, username):
    try:
        with get_db_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(f"DELETE FROM {table} WHERE username = ?", (username,))
            conn.commit()
    except Exception as e:
        return e

def update_vardek_connection(column: str, value: str):
    try:
        with get_db_connection() as conn:
            cur = conn.cursor()
            cur.execute("SELECT COUNT(*) FROM vardek_connection")
            count = cur.fetchone()[0]

            if count == 0:
                cur.execute(f"INSERT INTO vardek_connection ({column}) VALUES (?)", (value,))
            else:
                cur.execute(f"UPDATE vardek_connection SET {column} = ?", (value,))

            conn.commit()
    except Exception as e:
        return e

def parse_number(value: str):
    if not isinstance(value, str):
        return None

    value = value.strip().replace(',', '.')

    try:
        return float(value)
    except ValueError:
        return None

def update_multiplication(column: str, value: str):
    try:
        with get_db_connection() as conn:
            cur = conn.cursor()
            cur.execute("SELECT COUNT(*) FROM multiplication")
            count = cur.fetchone()[0]
            if count == 0:
                cur.execute(f"INSERT INTO multiplication ({column}) VALUES (?)", (value,))
            else:
                cur.execute(f"UPDATE multiplication SET {column} = ?", (value,))
            
            conn.commit()
        return None

    except Exception as e:
        return e

def get_multiplication_value(column: str):
    try:
        with get_db_connection() as conn:
            cur = conn.cursor()
            cur.execute(f"SELECT {column} FROM multiplication LIMIT 1")
            row = cur.fetchone()
            return row[0] if row else None
    except Exception as e:
        return e

@bot.message_handler(commands=['start'])
def start_handler(message):
    try:
        keyboard = types.InlineKeyboardMarkup(row_width=2)
        button1 = types.InlineKeyboardButton("Создать ключ", callback_data="add_or_dell:add")
        button2 = types.InlineKeyboardButton("Удалить ключ", callback_data="add_or_dell:dell")
        button3 = types.InlineKeyboardButton("Новый логин VRD", callback_data="vrd_update:login")
        button4 = types.InlineKeyboardButton("Новый пароль VRD", callback_data="vrd_update:password")
        button5 = types.InlineKeyboardButton("Коэффициент", callback_data="kfc")
        button6 = types.InlineKeyboardButton("Обновить конструктор", callback_data="update_constructor")
        close = types.InlineKeyboardButton("Закрыть", callback_data=f"close")
        keyboard.add(button1, button2, button3, button4, button5, button6)
        keyboard.add(close)
        bot.send_message(message.chat.id, "Выбери, что необходимо сделать:", reply_markup=keyboard)
        bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
    except Exception as e:
        msg = bot.send_message(message.chat.id, f'Возникла ошибка: {e}')
        msgid = msg.message_id
        time.sleep(0.5)
        bot.delete_message(chat_id=message.chat.id, message_id=msgid)

@bot.callback_query_handler(func=lambda call: call.data.startswith("kfc"))
def kfc_update(call):
    try:
        bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
        tec_kfc = get_multiplication_value('seller')
        new_text = f'Укажи новый коэффициент в конструкторе (текущий: {tec_kfc}). Введи значение с десятичной частью через точку, например: 2.5:'
        msg = bot.send_message(call.message.chat.id, new_text, reply_markup=types.ReplyKeyboardRemove())
        msgid = msg.message_id
        bot.register_next_step_handler(call.message, kfc_update_result, msgid)
    except Exception as e:
        msg = bot.send_message(call.message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
        msgid = msg.message_id
        time.sleep(0.5)
        bot.delete_message(chat_id=call.message.chat.id, message_id=msgid)
    
def kfc_update_result(message, msgid):
    try:
        if message.text:
            bot.delete_message(chat_id=message.chat.id, message_id=msgid)
            bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
            kfc = parse_number(message.text)
            result = 2.5
            if kfc and kfc != 0:
                result = update_multiplication('seller', kfc)
                if not result:
                    new_text = f'Установлен новый коэффициент для конструктора - {kfc}'
                    msg = bot.send_message(message.chat.id, new_text, reply_markup=types.ReplyKeyboardRemove())
                    msgid = msg.message_id
                    time.sleep(1)
                    bot.delete_message(chat_id=message.chat.id, message_id=msgid)
                else:
                    msg = bot.send_message(message.chat.id, f'Возникла ошибка смены коэффициента: {result}', reply_markup=types.ReplyKeyboardRemove())
                    msgid = msg.message_id
                    time.sleep(0.5)
                    bot.delete_message(chat_id=message.chat.id, message_id=msgid)
        else:
            msg = bot.send_message(message.chat.id, f"Было отправлено пустое сообщение, введи коэффициент ещё раз:", reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            bot.register_next_step_handler(message, kfc_update_result, msgid)
    except Exception as e:
        msg = bot.send_message(call.message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
        msgid = msg.message_id
        time.sleep(0.5)
        bot.delete_message(chat_id=call.message.chat.id, message_id=msgid)

@bot.callback_query_handler(func=lambda call: call.data.startswith("vrd_update"))
def vrd_update_pass_and_login(call):
    _, logorpass = call.data.split(':')
    new_text = ''
    try:
        if logorpass == "login":
            bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
            new_text = 'Укажи новый логин кабинета Вардек:'
            msg = bot.send_message(call.message.chat.id, new_text, reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            bot.register_next_step_handler(call.message, new_pass_or_login, msgid, 1)
        elif logorpass == "password":
            new_text = 'Укажи новый пароль кабинета Вардек:'
            msg = bot.send_message(call.message.chat.id, new_text, reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            bot.register_next_step_handler(call.message, new_pass_or_login, msgid, 2)
            bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
        else:
            bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
            msg = bot.send_message(call.message.chat.id, f'\U0001F7E3 — Ошибка. Неверная команда.', reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            time.sleep(0.5)
            bot.delete_message(chat_id=call.message.chat.id, message_id=msgid)
            
    except Exception as e:
        bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
        msg = bot.send_message(call.message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
        msgid = msg.message_id
        time.sleep(0.5)
        bot.delete_message(chat_id=call.message.chat.id, message_id=msgid)

def new_pass_or_login(message, msgid, variable=False):
    try:
        if message.text:
            bot.delete_message(chat_id=message.chat.id, message_id=msgid)
            bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
            passorlog = ''
            result = ''
            if variable:
                if variable == 1:
                    passorlog = 'логин'
                    result = update_vardek_connection('login', message.text)
                elif variable == 2:
                    passorlog = 'пароль'
                    result = update_vardek_connection('password', message.text)
                else:
                    passorlog = ''
                    result = 'ошибка логики variable в функции new_pass_or_login'
           
                if not result:
                    new_text = f'Установлен новый {passorlog} для кабинета Вардек - {message.text}'
                    msg = bot.send_message(message.chat.id, new_text, reply_markup=types.ReplyKeyboardRemove())
                    msgid = msg.message_id
                    time.sleep(1)
                    bot.delete_message(chat_id=message.chat.id, message_id=msgid)
                else:
                    msg = bot.send_message(message.chat.id, f'Возникла ошибка: {result}', reply_markup=types.ReplyKeyboardRemove())
                    msgid = msg.message_id
                    time.sleep(0.5)
                    bot.delete_message(chat_id=message.chat.id, message_id=msgid)
            else:
                msg = bot.send_message(message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
                msgid = msg.message_id
                time.sleep(0.5)
                bot.delete_message(chat_id=message.chat.id, message_id=msgid)
        else:
            msg = bot.send_message(message.chat.id, f"Было отправлено пустое сообщение, введи никнейм ещё раз:", reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            bot.register_next_step_handler(message, new_pass_or_login, msgid)
            
    except Exception as e:
        msg = bot.send_message(message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
        msgid = msg.message_id
        time.sleep(0.5)
        bot.delete_message(chat_id=message.chat.id, message_id=msgid)

@bot.callback_query_handler(func=lambda call: call.data.startswith("add_or_dell"))
def add_or_dell_key(call):
    _, addordell = call.data.split(':')
    new_text = ''
    try:
        if addordell == "add":
            bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
            new_text = 'Укажи никнейм продавца:'
            msg = bot.send_message(call.message.chat.id, new_text, reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            bot.register_next_step_handler(call.message, new_key_for_user, msgid)
        elif addordell == "dell":
            button_data = get_personal_data("keys_constructor", 'username')
            keyboard = create_inline_buttons(button_data)
            new_text = f'\U0001F7E3 — Выбери из списка для удаления:'
            bot.edit_message_text(chat_id=call.message.chat.id, text=new_text, message_id=call.message.message_id, reply_markup=keyboard)    
        else:
            bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
            msg = bot.send_message(call.message.chat.id, f'\U0001F7E3 — Ошибка. Неверная команда.', reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            time.sleep(0.5)
            bot.delete_message(chat_id=call.message.chat.id, message_id=msgid)
          
    except Exception as e:
        bot.send_message(call.message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
        
@bot.callback_query_handler(func=lambda call: call.data.startswith("close"))
def close_menu(call):
    bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)

@bot.callback_query_handler(func=lambda call: call.data.startswith("kick"))
def kick(call):
    _, kick_username = call.data.split(':')
    kick_result = kick_user("keys_constructor", kick_username)
    if not kick_result:
        bot.answer_callback_query(call.id, f"Ключ для пользователя {kick_username} был успешно удалён.", show_alert=True)    
    else:
        bot.answer_callback_query(call.id, f"Возникла ошибка: {kick_result}", show_alert=True)  
    time.sleep(0.5)
    bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)

def new_key_for_user(message, msgid):
    try:
        if message.text:
            bot.delete_message(chat_id=message.chat.id, message_id=msgid)
            bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
            key = generate_key(16)
            data = {
                "key": key,
                "username": message.text
            }
            result = add_or_update("keys_constructor", data, "username")
            if result:
                bot.send_message(message.chat.id, f"Возникла ошибка {result}", reply_markup=types.ReplyKeyboardRemove())
            else: 
                bot.send_message(message.chat.id, f"Для продавца {message.text} создан ключ: `{key}`", parse_mode="Markdown", reply_markup=types.ReplyKeyboardRemove())
        else:
            msg = bot.send_message(message.chat.id, f"Было отправлено пустое сообщение, введи никнейм ещё раз:", reply_markup=types.ReplyKeyboardRemove())
            msgid = msg.message_id
            bot.register_next_step_handler(message, new_key_for_user, msgid)
            
    except Exception as e:
        msg = bot.send_message(message.chat.id, f'Возникла ошибка: {e}', reply_markup=types.ReplyKeyboardRemove())
        msgid = msg.message_id
        time.sleep(0.5)
        bot.delete_message(chat_id=message.chat.id, message_id=msgid)

@bot.callback_query_handler(func=lambda call: call.data.startswith("update_constructor"))
def update_constructor(call):
    bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
    result = start_structure_data_get_php(trigger='yes_constructor', new_version="yes")
    msg = ''
    if result:
        if result == -1:
            msg = bot.send_message(call.message.chat.id, "Ответ сервера на запрос обновления: Ошибка обновления, действие не выполнено.")
        elif result == 0:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены. Для внесения изменений у всех пользователей необходимо обновить версию.")
        elif result == 1:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлён конструктор продавцвов. Для внесения изменений у всех пользователей необходимо обновить версию.")
        elif result == 2:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлён конструктор технологов. Для внесения изменений у всех пользователей необходимо обновить версию.")
        elif result == 3:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлены конструкторы продавцвов, технологов и конструктор для салона. Для внесения изменений у всех пользователей необходимо обновить версию.")
        elif result == 4:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлён конструктор для салона. Для внесения изменений у всех пользователей необходимо обновить версию.")
        elif result == 10:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, изменения будут примененены у продавцов при следущем запуске конструктора.")
        elif result == 11:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлён конструктор продавцов, изменения будут примененены у продавцов при следущем запуске программы.")
        elif result == 12:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлён конструктор технологов, изменения будут примененены у технологов при следущем запуске программы.")
        elif result == 13:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлены конструкторы продавцов, технологов и конструктор для салона, изменения будут примененены у всех при следущем запуске программы.")
        elif result == 14:
            msg = bot.send_message(call.message.chat.id, "Данные фасадов и столешниц успешно обновлены, также обновлён конструктор для салона, изменения будут примененены у всех при следущем запуске программы.")
        else:
            msg = bot.send_message(call.message.chat.id, f"Неизвестный статус обновления: {result}")
    else:
        msg = bot.send_message(message.chat.id, f'Неизвестный статус обновления: {result}')
    
    msgid = msg.message_id
    time.sleep(3)
    bot.delete_message(chat_id=call.message.chat.id, message_id=msgid)
#блок для телеграмм бота END