import re
import telebot
import sympy as sp
from sympy.parsing.sympy_parser import parse_expr
from sympy import symbols, nsolve, sqrt, exp, log, sin, cos, tan, sinh, cosh, tanh, cbrt
import tensorflow as tf
import numpy as np
from tensorflow import keras
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD

# Machine Learning
def create_model():
    model = keras.Sequential([
        keras.layers.Dense(units=1, input_shape=(1,))
    ])
    model.compile(optimizer=SGD(), loss='mean_squared_error')
    return model


X = np.array([4, 5, 6])  # Convert the input data to numpy arrays
y = np.array([8, 10, 12])

model = create_model()
model.fit(X, y, epochs=10)

# Telegram Bot
TOKEN = '<TRUFFLEHOG_REDACTED_TELEGRAMBOTTOKEN>'
bot = telebot.TeleBot(TOKEN)


def correct_expression(text):
    text = re.sub(r'(\d)([a-zA-Z])', r'\1*\2', text)
    text = re.sub(r'([a-zA-Z])(\d)', r'\1*\2', text)
    return text


def preprocess_text(text):
    text = re.sub(r'\s*([-+/().^cosctanexplogsinhiscoshthcbrtnsolve])\s', r'\1', text)
    text = re.sub(r'(\d)([a-zA-Z])', r'\1*\2', text)
    text = re.sub(r'([a-zA-Z])(\d)', r'\1*\2', text)
    return text


@bot.message_handler(commands=['start'])
def send_welcome(message):
    bot.reply_to(message, "Привет! Я нейросеть, моя версия 001.0. Напиши /help, чтобы узнать, что я могу.")


@bot.message_handler(commands=['help'])
def send_help(message):
    bot.reply_to(message,
                 "Этот бот умеет выполнять простые и сложные математические операции.\nПримеры:\n1. 2+2\n2. 4/2\n3. sqrt(9)\n4. sin(30)\n5. x^2 + 2x - 1 = 0\n6. exp(2)\n7. log(10)\n8. sinh(1)\n9. cosh(2)\n10. tanh(3)\n11. cos(45)\n12. tan(60)\n13. cbrt(8)")


@bot.message_handler(func=lambda m: True)
def handle_message(message):
    msg = bot.reply_to(message, "Загружаю результат...⏳")
    try:
        text = preprocess_text(message.text)
        # Проверяем, что вводимое выражение содержит только поддерживаемые операции и функции
        allowed_functions = ['sqrt', 'exp', 'log', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'cbrt']
        for func in allowed_functions:
            if func not in text:
                continue
            if text.index(func) > 0 and text[text.index(func) - 1] not in ' ()':
                response = "Ошибка: Функция {} должна быть использована с оператором или в скобках.".format(func)
                break
        else:
            if '=' in text:
                parts = text.split('=')
                if 'nsolve' in parts[0]:
                    cubic_eq = parse_expr(parts[0][parts[0].index('nsolve')+6:])
                    initial_guess = 0  # Default initial guess
                    if '(' in parts[0]:
                        end_index = parts[0].index('(', parts[0].index('nsolve')+6) + 1
                        initial_guess_str = parts[0][end_index:parts[0].index(')', end_index)]
                        initial_guess = parse_expr(initial_guess_str)
                    roots = nsolve(Poly(cubic_eq, symbols('x')), symbols('x'), initial_guess)
                    response = f"Решения кубического уравнения {text}: {roots}"
                else:
                    eq = parse_expr(parts[0]) - parse_expr(parts[1])
                    solutions = solve(eq, symbols('x'))
                    response = f"Решение уравнения {text} : {solutions}"
            elif text.startswith('sqrt(') and text.endswith(')'):
                num = parse_expr(text[5:-1])
                if num >= 0:
                    result = sqrt(num)
                    response = f"Квадратный корень {num} равен {result}"
                else:
                    response = "Ошибка: Квадратный корень из отрицательного числа не определен в действительных числах."
            elif 'exp' in text:
                result = exp(parse_expr(text[text.index('exp') + 3:].strip()))
                response = f"exp({text[text.index('exp') + 3:].strip()}) = {result}"
            elif 'log' in text:
                result = log(parse_expr(text[text.index('log') + 3:].strip()))
                response = f"log({text[text.index('log') + 3:].strip()}) = {result}"
            elif 'sin' in text:
                result = sin(parse_expr(text[text.index('sin') + 3:].strip()))
                response = f"sin({text[text.index('sin') + 3:].strip()}) = {result}"
            elif 'cos' in text:
                result = cos(parse_expr(text[text.index('cos') + 3:].strip()))
                response = f"cos({text[text.index('cos') + 3:].strip()}) = {result}"
            elif 'tan' in text:
                result = tan(parse_expr(text[text.index('tan') + 3:].strip()))
                response = f"tan({text[text.index('tan') + 3:].strip()}) = {result}"
            elif 'sinh' in text:
                result = sinh(parse_expr(text[text.index('sinh') + 4:].strip()))
                response = f"sinh({text[text.index('sinh') + 4:].strip()}) = {result}"
            elif 'cosh' in text:
                result = cosh(parse_expr(text[text.index('cosh') + 4:].strip()))
                response = f"cosh({text[text.index('cosh') + 4:].strip()}) = {result}"
            elif 'tanh' in text:
                result = tanh(parse_expr(text[text.index('tanh') + 4:].strip()))
                response = f"tanh({text[text.index('tanh') + 4:].strip()}) = {result}"
            elif 'cbrt' in text:
                result = cbrt(parse_expr(text[text.index('cbrt') + 4:].strip()))
                response = f"cbrt({text[text.index('cbrt') + 4:].strip()}) = {result}"
            else:
                try:
                    result = parse_expr(text, transformations=(standard_transformations + (rationalize,)))
                    response = f"Результат: {result}"
                except:
                    response = "Ошибка: Не удалось распознать математическое выражение."
        # Проверяем, нет ли незначимых символов в конце выражения
        if response[-1] in '(),':
            response = response[:-1]
        bot.edit_message_text(response, message.chat.id,
                              msg.message_id)  # Заменяем сообщение "Загружаю результат...⏳" на ответ
    except Exception as e:
        response = "Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте еще раз."
        bot.edit_message_text(response, message.chat.id,
                              msg.message_id)  # Заменяем сообщение "Загружаю результат...⏳" на сообщение об ошибке

if __name__ == '__main__':
    bot.polling() исправь этот код