Further enhance (keep the g4f module and the components), and add an advanced detailed calculation and solutions without truncation. And also without vagueness or generalizations.

```
import os
import sys
import json
import time
import asyncio
import logging
import random
import requests
import threading
import subprocess
import numpy as np
from io import BytesIO
from PIL import Image, ImageTk
from scipy import stats
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from functools import lru_cache
import re
from concurrent.futures import ThreadPoolExecutor
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
import wolframalpha
import g4f 
from g4f.client import Client as GPTClient
import matplotlib.pyplot as plt
import csv

# ------------------------- Configuration -------------------------
CONFIG_FILE = 'config.json'

default_config = {
    "WOLFRAM_APP_ID": os.getenv("WOLFRAM_APP_ID", "YOUR_WOLFRAM_APP_ID"),  # Securely loaded from environment
    "GPT_MODEL": "gpt-4o",  # Updated to official model names
    "MAX_DEPTH": 20,
    "PRECISION": 100,
    "GPT_MAX_TOKENS": 4000,
    "DEBUG_MODE": False,
    "MAX_RESPONSE_LENGTH": 5000
}

def load_config():
    """Load configuration from the config file or create a default one."""
    if not os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, 'w') as f:
            json.dump(default_config, f, indent=4)
        return default_config.copy()
    else:
        with open(CONFIG_FILE, 'r') as f:
            return json.load(f)

def save_config(config):
    """Save the current configuration to the config file."""
    with open(CONFIG_FILE, 'w') as f:
        json.dump(config, f, indent=4)

config = load_config()

# ------------------------- Logging Setup -------------------------
LOG_FILE = 'math_solver.log'

logger = logging.getLogger('MathSolver')
logger.setLevel(logging.DEBUG if config.get("DEBUG_MODE", False) else logging.INFO)
logger.propagate = False  # Prevent duplicate logs

# Clear existing handlers
if logger.hasHandlers():
    logger.handlers.clear()

# File handler
file_handler = logging.FileHandler(LOG_FILE)
file_handler.setLevel(logging.DEBUG if config.get("DEBUG_MODE", False) else logging.INFO)
file_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)

# Console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG if config.get("DEBUG_MODE", False) else logging.INFO)
console_handler.setFormatter(file_formatter)
logger.addHandler(console_handler)

# ------------------------- Initialize Clients -------------------------
def initialize_clients():
    """Initialize the WolframAlpha client."""
    global wolfram_client, gpt_client
    try:
        wolfram_client = wolframalpha.Client(config["WOLFRAM_APP_ID"])
        logger.info("WolframAlpha client initialized successfully.")
    except Exception as e:
        logger.error(f"Failed to initialize WolframAlpha client: {e}")
        wolfram_client = None

    try:
        gpt_client = GPTClient()
        logger.info("GPT client initialized successfully.")
    except Exception as e:
        logger.error(f"Failed to initialize GPT client: {e}")
        gpt_client = None

initialize_clients()

# ------------------------- Global Variables -------------------------
history = []
history_lock = threading.Lock()  # Thread-safe access

executor = ThreadPoolExecutor(max_workers=5)  # For managing threads efficiently

# ------------------------- Utility Functions -------------------------

@lru_cache(maxsize=256)
def evaluate_expression(expression):
    """
    Evaluate the mathematical expression using WolframAlpha and GPT.

    Args:
        expression (str): The mathematical problem or expression to evaluate.

    Returns:
        str: Combined analytical and GPT evaluation results.
    """
    logger.debug(f"Evaluating expression: '{expression}'.")
    analytical_result, confidence, mean_conf, std_conf = query_wolframalpha(expression)
    gpt_result = query_gpt(f"Provide an advanced mathematical evaluation for the following expression: {expression}", suggestion=analytical_result)
    combined_result = f"**WolframAlpha Evaluation:**\n{analytical_result}\n\n**GPT Evaluation:**\n{gpt_result}"
    logger.debug("Evaluation completed using WolframAlpha and GPT.")
    return combined_result

def high_precision_calculation(expression, precision=config.get("PRECISION", 100)):
    """
    Perform high-precision calculations via WolframAlpha.

    Args:
        expression (str): The mathematical expression to calculate.
        precision (int): Number of decimal places for precision.

    Returns:
        str: High-precision calculation result or error message.
    """
    logger.debug(f"High precision calculation requested for '{expression}' with precision {precision}.")
    if not wolfram_client:
        logger.error("WolframAlpha client is not initialized.")
        return "WolframAlpha client is not available."
    try:
        res = wolfram_client.query(f"Calculate {expression} to {precision} decimal places")
        high_prec_result = next(res.results).text
        logger.debug(f"High precision result: {high_prec_result}")
        return high_prec_result
    except StopIteration:
        logger.warning("No results returned from WolframAlpha for high precision calculation.")
        return "WolframAlpha could not perform high precision calculation."
    except Exception as e:
        logger.error(f"Error in high precision calculation '{expression}': {e}")
        return f"Error performing high precision calculation: {e}"

def estimate_confidence(depth, accuracy, complexity, iterations):
    """
    Estimate the confidence level of the solution based on various metrics.

    Args:
        depth (int): Current depth in the solving process.
        accuracy (float): Accuracy metric of the solution.
        complexity (int): Complexity of the problem.
        iterations (int): Number of iterations performed.

    Returns:
        float: Confidence score between 0.0 and 1.0.
    """
    base_confidence = 0.5 + (depth * 0.05) + (accuracy * 0.2) - (complexity * 0.02) + (iterations * 0.01)
    confidence = round(min(max(base_confidence, 0.0), 1.0), 2)
    logger.debug(f"Estimated confidence: {confidence} (Depth: {depth}, Accuracy: {accuracy}, Complexity: {complexity}, Iterations: {iterations})")
    return confidence

def calculate_complexity(expression):
    """
    Estimate the complexity of the given mathematical expression.

    Args:
        expression (str): The mathematical expression.

    Returns:
        int: Complexity score.
    """
    try:
        complexity = len(expression) + expression.count('^') + expression.count('*') + expression.count('/')
        logger.debug(f"Calculated complexity for '{expression}': {complexity}")
        return complexity
    except Exception as e:
        logger.error(f"Error calculating complexity for '{expression}': {e}")
        return 15  # Default complexity if estimation fails

# ------------------------- Advanced Depth Calculation and Handler -------------------------

def dynamic_depth_adjustment(confidence, current_depth, max_depth):
    """
    Dynamically adjust the solving depth based on confidence levels.

    Args:
        confidence (float): Current confidence score.
        current_depth (int): Current depth level.
        max_depth (int): Maximum allowed depth.

    Returns:
        int: Adjusted depth level.
    """
    if confidence < 0.7 and current_depth < max_depth:
        return current_depth + 1
    return current_depth

def advanced_depth_system(problem, max_depth=config.get("MAX_DEPTH", 20), max_iterations=10):
    """
    Advanced system to iteratively solve the problem with increasing depth and iterations.

    Args:
        problem (str): The mathematical problem to solve.
        max_depth (int): Maximum depth allowed.
        max_iterations (int): Maximum iterations per depth level.

    Returns:
        tuple: Best result, its confidence, mean confidence, and standard deviation of confidence scores.
    """
    best_result = None
    best_confidence = 0.0
    results = []

    for depth in range(1, max_depth + 1):
        for iteration in range(1, max_iterations + 1):
            time.sleep(0.05 * random.random())  # Reduced sleep for performance

            refined_problem = refine_problem(problem, depth)
            potential_solution = f"{refined_problem} (Depth {depth}, Iteration {iteration})"
            accuracy = (depth * 0.05 + iteration * 0.02) * random.uniform(0.9, 1.1)
            complexity = calculate_complexity(problem)
            confidence = estimate_confidence(depth, accuracy, complexity, iteration)

            results.append((potential_solution, confidence))

            if confidence > best_confidence:
                best_result = potential_solution
                best_confidence = confidence

            if confidence > 0.95:
                logger.debug(f"Confidence threshold met at depth {depth}, iteration {iteration}.")
                break

        # Dynamic depth adjustment based on current best confidence
        if best_confidence > 0.9:
            logger.debug(f"Dynamic depth adjustment: Breaking early at depth {depth} due to high confidence.")
            break

    confidences = [r[1] for r in results]
    mean_confidence = np.mean(confidences) if confidences else 0.0
    std_confidence = np.std(confidences) if confidences else 0.0

    if len(confidences) > 1:
        z_scores = stats.zscore(confidences)
        outliers = np.abs(z_scores) > 2
    else:
        outliers = [False]

    filtered_results = [r for r, is_outlier in zip(results, outliers) if not is_outlier]

    if filtered_results:
        best_result, best_confidence = max(filtered_results, key=lambda x: x[1])
        logger.debug("Filtered outliers and selected the best result.")
    else:
        logger.debug("No filtered results available; using initial best result.")

    return best_result, best_confidence, mean_confidence, std_confidence

def refine_problem(problem, depth):
    """
    Refine the given problem based on the current depth.

    Args:
        problem (str): Original problem.
        depth (int): Current depth level.

    Returns:
        str: Refined problem statement.
    """
    try:
        refined = f"{problem} (Refinement Depth: {depth})"
        logger.debug(f"Refined problem at depth {depth}: {refined}")
        return refined
    except Exception as e:
        logger.error(f"Error refining problem '{problem}' at depth {depth}: {e}")
        return problem

# ------------------------- Advanced Self-Correction Specialty -------------------------

def self_correct_response(original_response):
    """
    Analyze and correct the original response using GPT for potential errors or improvements.

    Args:
        original_response (str): The initial response to analyze.

    Returns:
        str: Corrected and improved response.
    """
    logger.debug("Initiating self-correction process.")
    correction_prompt = f"""Analyze the following response for any potential errors, inconsistencies, or areas that can be improved. Provide a revised version if necessary.

Response:
{original_response}

Revised Response:
"""
    corrected_response = query_gpt(correction_prompt)
    logger.debug("Self-correction process completed.")
    return corrected_response

# ------------------------- Advanced Scoping-Tuning Analyzation AI Method -------------------------

def scoping_tuning_analysis(problem, response):
    """
    Analyze the response and adjust the problem-solving approach dynamically.

    Args:
        problem (str): The original mathematical problem.
        response (str): The initial response provided.

    Returns:
        str: Analysis and suggestions for improving the solution.
    """
    logger.debug("Starting scoping-tuning analysis.")
    analysis_prompt = f"""Given the problem and the initial response below, analyze the adequacy and thoroughness of the solution. Suggest any adjustments to the problem scope or focus areas that could enhance the solution's accuracy and completeness.

Problem:
{problem}

Initial Response:
{response}

Analysis and Suggestions:
"""
    analysis = query_gpt(analysis_prompt)
    logger.debug("Scoping-tuning analysis completed.")
    return analysis

# ------------------------- Translator and Query Functions -------------------------

def advanced_auto_translate_to_wolfram(query):
    """
    Translate common mathematical instructions to WolframAlpha-compatible queries.

    Args:
        query (str): The original user query.

    Returns:
        str: Translated query suitable for WolframAlpha.
    """
    query = query.lower()

    translation_map = {
        'solve': 'compute',
        'find': 'determine',
        'calculate': 'evaluate',
        'simplify': 'simplify the expression',
        'integrate': 'calculate the integral of',
        'differentiate': 'calculate the derivative of',
        'derivative': 'differentiate',
        'integral': 'integrate',
        'limit': 'evaluate the limit of',
        'roots': 'determine the roots of the equation',
        'factor': 'factorize',
        'expand': 'expand the expression',
        'series': 'find the series expansion of',
        'approximate': 'find a numerical approximation of',
        'solve system': 'solve the system of equations',
        'optimize': 'find the optimal value of',
    }

    for key, value in translation_map.items():
        query = query.replace(key, value)

    logger.debug(f"Translated query to WolframAlpha: {query}")
    return query

def query_wolframalpha(query, max_depth=config.get("MAX_DEPTH", 20)):
    """
    Query WolframAlpha with the given mathematical problem.

    Args:
        query (str): The mathematical problem.
        max_depth (int): Maximum depth for the depth system.

    Returns:
        tuple: Analytical result, confidence score, mean confidence, and standard deviation of confidence.
    """
    if not wolfram_client:
        logger.error("WolframAlpha client is not initialized.")
        return "WolframAlpha client is not available.", 0.0, 0.0, 0.0

    translated_query = advanced_auto_translate_to_wolfram(query)
    best_result = "WolframAlpha could not find an answer."
    best_confidence = 0.0
    analytical_result = "Could not perform analytical analysis."
    mean_confidence = std_confidence = 0.0

    try:
        res = wolfram_client.query(translated_query + ' explain step by step')
        wolfram_output = next(res.results).text
        logger.debug(f"WolframAlpha output: {wolfram_output}")
        best_result, best_confidence, mean_confidence, std_confidence = advanced_depth_system(wolfram_output, max_depth=max_depth)
        analytical_result = wolfram_to_analytical(best_result)
        logger.info("Queried WolframAlpha successfully.")
    except StopIteration:
        logger.warning("No results returned from WolframAlpha.")
    except Exception as e:
        logger.error(f"Error querying WolframAlpha: {e}")

    return analytical_result, best_confidence, mean_confidence, std_confidence

def wolfram_to_analytical(wolfram_result):
    """
    Convert WolframAlpha's result into a structured analytical format.

    Args:
        wolfram_result (str): The raw result from WolframAlpha.

    Returns:
        str: Structured analytical steps.
    """
    steps = wolfram_result.split('\n')
    analytical_steps = []

    for step in steps:
        step = re.sub(r'\d+(\.\d+)?', 'x', step)
        step = step.replace('Solve[', 'Solve the equation: ')
        step = step.replace('Integrate[', 'Integrate the function: ')
        step = step.replace('Differentiate[', 'Differentiate the function: ')
        analytical_steps.append(step)

    analytical_steps.extend([
        "To solve this problem analytically:",
        "1. **Identify the problem type** (e.g., algebraic, calculus, etc.).",
        "2. **Choose appropriate mathematical techniques** based on the problem type.",
        "3. **Apply relevant theorems or formulas** to set up the problem.",
        "4. **Simplify and solve step by step**, ensuring each step logically follows from the previous one.",
        "5. **Verify the solution** by substituting it back into the original equation or checking against known results.",
        "6. **Interpret the results** within the context of the original problem to provide meaningful conclusions."
    ])

    analytical = "\n".join(analytical_steps)
    logger.debug("Converted WolframAlpha result to analytical steps.")
    return analytical

# ------------------------- GPT Query Functions -------------------------

def query_gpt(message, suggestion=None):
    """
    Query the GPT model with a custom prompt.

    Args:
        message (str): The main message or problem statement.
        suggestion (str, optional): Additional context or suggestions for GPT.

    Returns:
        str: GPT's response to the prompt.
    """
    prompt = generate_custom_prompt(message, suggestion)
    logger.debug(f"GPT Prompt: {prompt}")

    try:
        response = gpt_client.chat.completions.create(
            model=config.get("GPT_MODEL", "gpt-4o"),
            messages=[{"role": "user", "content": prompt}],
            max_tokens=config.get("GPT_MAX_TOKENS", 12000),
            temperature=0.7,
            n=1,
            stop=None,
        )
        result = response.choices[0].message.content
        logger.debug(f"GPT Response: {result}")
        return result
    except Exception as e:
        logger.error(f"Error querying GPT: {e}")
        return "GPT could not generate a solution."

def generate_custom_prompt(user_input: str, suggestion: str = None) -> str:
    """
    Generate a customized prompt for GPT with advanced Chain-of-Thought specialization.

    Args:
        user_input (str): The mathematical problem.
        suggestion (str, optional): Analytical suggestions from WolframAlpha.

    Returns:
        str: The customized prompt for GPT.
    """
    # Advanced Chain-of-Thought Specialization
    base_prompt = f"""You are an advanced mathematical reasoning AI with specialized Chain-of-Thought capabilities. Your task is to provide a comprehensive solution to the following problem, including detailed explanations, multiple approaches, and rigorous proofs where applicable.

Problem: {user_input}

Your solution should include the following sections:

1. **Problem Analysis**: Thoroughly understand and decompose the problem. Identify key mathematical concepts involved.
2. **Approach Selection**: Decide on the most effective mathematical methods and techniques to tackle the problem.
3. **Detailed Step-by-Step Solution**: Execute the chosen methods systematically, providing clear and logical explanations for each step.
4. **Verification and Validation**: Confirm the accuracy of each step and the final solution. Check for alternative solutions or potential errors.
5. **Comprehensive Proof**: If applicable, supply a formal proof supporting the solution, ensuring all mathematical justifications are sound.
6. **Alternative Methods**: Present other viable methods to solve the problem, highlighting their advantages or different perspectives.

Ensure that each section is clearly marked and well-organized. If there are ambiguities or assumptions made to solve the problem, explicitly state them in the **Problem Analysis** section.
"""

    # Append analytical suggestion from WolframAlpha if available
    if suggestion:
        base_prompt += f"\n\n**Analytical Suggestion from WolframAlpha:**\n{suggestion}\n\n"
    else:
        base_prompt += "\n\n**Analytical Suggestion from WolframAlpha:**\nNo analytical approach available. Please proceed with your own method.\n\n"

    logger.debug("Generated custom prompt for GPT with advanced Chain-of-Thought specialization.")
    return base_prompt

# ------------------------- Step-by-Step and Proof Functions -------------------------

def show_step_by_step_solution(problem):
    """
    Generate a detailed, step-by-step solution using GPT.

    Args:
        problem (str): The mathematical problem.

    Returns:
        str: Detailed step-by-step solution.
    """
    logger.debug("Generating step-by-step solution using GPT.")
    step_prompt = f"Provide a detailed, step-by-step solution to the following problem:\n\n{problem}"
    step_solution = query_gpt(step_prompt)
    return step_solution

def advanced_proof_techniques(problem):
    """
    Generate a comprehensive mathematical proof for the solution.

    Args:
        problem (str): The mathematical problem.

    Returns:
        str: Comprehensive mathematical proof.
    """
    logger.debug("Generating advanced proof using GPT.")
    proof_prompt = f"Provide a comprehensive mathematical proof for the solution to the following problem:\n\n{problem}"
    proof = query_gpt(proof_prompt)
    return proof

# ------------------------- Advanced Response Truncater -------------------------

def truncate_response(response, max_length):
    """
    Truncate the response to the nearest sentence before the max_length.
    Adds a notice if the response was truncated.

    Args:
        response (str): The original response.
        max_length (int): Maximum allowed length.

    Returns:
        tuple: Truncated response and a boolean indicating if truncation occurred.
    """
    if len(response) <= max_length:
        return response, False
    # Find the last period before max_length
    truncated = response[:max_length]
    last_period = truncated.rfind('.')
    if last_period != -1:
        truncated = truncated[:last_period+1]
    else:
        truncated = truncated[:max_length]
    truncated += "\n\n*Response truncated for readability. Please refer to the detailed logs for the full response.*"
    logger.debug("Response was truncated.")
    return truncated, True

# ------------------------- Plotting Function -------------------------

def plot_expression(expression):
    """
    Generate and display a plot for the given mathematical expression using WolframAlpha.

    Args:
        expression (str): The mathematical expression to plot.

    Returns:
        matplotlib.figure.Figure or str: The plot figure or an error message.
    """
    if not wolfram_client:
        logger.error("WolframAlpha client is not initialized.")
        return "WolframAlpha client is not available to plot the expression."
    try:
        # Utilize WolframAlpha to get a plot image
        logger.debug(f"Attempting to plot expression: '{expression}'.")
        plot_query = f"plot {expression}"
        res = wolfram_client.query(plot_query)

        # Extract image URL from WolframAlpha's response
        plot_pod = None
        for pod in res.pods:
            if pod.title.lower() in ['plot', 'graph', 'graphic']:
                plot_pod = pod
                break

        if not plot_pod:
            logger.warning("No plot available from WolframAlpha for the given expression.")
            return "WolframAlpha could not generate a plot for the given expression."

        plot_subpod = plot_pod.subpods[0]
        plot_url = plot_subpod.img.src
        logger.debug(f"Retrieved plot URL from WolframAlpha: {plot_url}")

        # Download the plot image
        response = requests.get(plot_url)
        img = Image.open(BytesIO(response.content))

        # Create a matplotlib figure for interactive features
        fig = Figure(figsize=(6, 4), dpi=100)
        ax = fig.add_subplot(111)
        ax.imshow(img)
        ax.axis('off')  # Hide axes
        logger.debug("Plot downloaded and prepared for display.")
        return fig
    except StopIteration:
        logger.warning("No plot available from WolframAlpha for the given expression.")
        return "WolframAlpha could not generate a plot for the given expression."
    except Exception as e:
        logger.error(f"Error plotting expression '{expression}': {e}")
        return f"Error plotting expression: {e}"

# ------------------------- PDF Export Function -------------------------

def export_to_pdf(problem, solution, proof, plot_fig, save_path):
    """
    Export the solution, proof, and plot to a PDF file.

    Args:
        problem (str): The original problem.
        solution (str): The solution text.
        proof (str): The proof text.
        plot_fig (matplotlib.figure.Figure or str): The plot figure or error message.
        save_path (str): Path to save the PDF.
    """
    try:
        c = canvas.Canvas(save_path, pagesize=letter)
        width, height = letter

        # Title
        c.setFont("Helvetica-Bold", 16)
        c.drawString(50, height - 50, "Advanced Math Solver Report")

        # Problem Statement
        c.setFont("Helvetica-Bold", 12)
        c.drawString(50, height - 80, "Problem:")
        c.setFont("Helvetica", 12)
        text_object = c.beginText(50, height - 100)
        for line in problem.split('\n'):
            text_object.textLine(line)
        c.drawText(text_object)

        # Solution
        c.setFont("Helvetica-Bold", 12)
        c.drawString(50, height - 170, "Solution:")
        c.setFont("Helvetica", 12)
        text_object = c.beginText(50, height - 190)
        for line in solution.split('\n'):
            text_object.textLine(line)
        c.drawText(text_object)

        # Proof
        c.setFont("Helvetica-Bold", 12)
        c.drawString(50, height - 270, "Proof:")
        c.setFont("Helvetica", 12)
        text_object = c.beginText(50, height - 290)
        for line in proof.split('\n'):
            text_object.textLine(line)
        c.drawText(text_object)

        # Plot
        if isinstance(plot_fig, Figure):
            # Save plot to a temporary buffer
            buf = BytesIO()
            plot_fig.savefig(buf, format='PNG')
            buf.seek(0)
            img = ImageReader(buf)
            c.drawImage(img, 50, height - 600, width=500, height=300)
            buf.close()
        else:
            # If plot is an error message, add it as text
            c.setFont("Helvetica-Bold", 12)
            c.drawString(50, height - 600, "Plot:")
            c.setFont("Helvetica", 12)
            text_object = c.beginText(50, height - 620)
            for line in plot_fig.split('\n'):
                text_object.textLine(line)
            c.drawText(text_object)

        c.showPage()
        c.save()
        logger.info(f"Exported report to '{save_path}'.")
        messagebox.showinfo("Export Successful", f"Report exported to '{save_path}'.")
    except Exception as e:
        logger.error(f"Error exporting to PDF: {e}")
        messagebox.showerror("Export Error", f"Failed to export report: {e}")

# ------------------------- GPT Summarization Function -------------------------

def summarize_final_answer(corrected_response, proof):
    """
    Summarize the corrected response and proof into a compressed final answer.

    Args:
        corrected_response (str): The corrected chatbot response.
        proof (str): Comprehensive mathematical proof.

    Returns:
        str: Summarized final answer.
    """
    logger.debug("Summarizing final answer with advanced reinforcement Chain-of-Thought.")
    summary_prompt = f"""Based on the following detailed solution and proof, provide a concise summary that highlights the key points, final answer, and essential proof elements.

Detailed Solution:
{corrected_response}

Comprehensive Proof:
{proof}

Concise Final Answer:
"""
    summary = query_gpt(summary_prompt)
    return summary

# ------------------------- Chatbot Function with Advanced Features -------------------------

def chatbot(message):
    """
    Main function to handle the chatbot's response generation with advanced features.

    Args:
        message (str): The user's mathematical problem.

    Returns:
        tuple: Final response, confidence scores, and truncation status.
    """
    analytical_result, wolfram_confidence, mean_conf, std_conf = query_wolframalpha(message)

    gpt_result = query_gpt(message, suggestion=analytical_result)
    best_result, gpt_confidence, gpt_mean_conf, gpt_std_conf = advanced_depth_system(gpt_result)

    # Combine results from WolframAlpha and GPT
    combined_response = f"**Analytical Approach:**\n{analytical_result}\n\n**GPT Solution:**\n{best_result}"

    # Apply Advanced Self-Correction
    corrected_response = self_correct_response(combined_response)

    # Apply Advanced Scoping-Tuning Analysis
    scoping_analysis = scoping_tuning_analysis(message, corrected_response)

    # Generate Comprehensive Proof
    proof = advanced_proof_techniques(message)

    # Summarize the final answer using reinforcement CoT
    summary = summarize_final_answer(corrected_response, proof)

    # Final combined result with self-correction, scoping-tuning analysis, and proof
    final_result = f"{summary}\n\n**Scoping-Tuning Analysis:**\n{scoping_analysis}\n\n**Proof and Verification:**\n{proof}"

    # Apply Advanced Response Truncater
    max_length = config.get("MAX_RESPONSE_LENGTH", 5000)
    truncated_result, was_truncated = truncate_response(final_result, max_length)

    # Aggregate confidence scores
    confidence = max(wolfram_confidence, gpt_confidence)
    mean_confidence = (mean_conf + gpt_mean_conf) / 2
    std_confidence = (std_conf + gpt_std_conf) / 2

    # Append to history with thread safety
    with history_lock:
        history.append((message, truncated_result, confidence, mean_confidence, std_confidence))

    logger.info("Chatbot response generated successfully with advanced features.")
    return truncated_result, confidence, mean_confidence, std_confidence, was_truncated

# ------------------------- PDF Export Handler -------------------------

def handle_export():
    """
    Handle the export to PDF action.
    """
    if not history:
        messagebox.showinfo("No History", "There is no history to export.")
        return
    latest_entry = history[-1]
    problem, result, confidence, mean_conf, std_conf = latest_entry
    proof = advanced_proof_techniques(problem)
    response = result
    plot_fig = plot_expression(problem)
    
    # Ask user where to save the PDF
    file_path = filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF Files", "*.pdf")])
    if file_path:
        export_to_pdf(problem, response, proof, plot_fig, file_path)

# ------------------------- GUI Functions -------------------------

def on_submit():
    """
    Handle the submit button click event to process user input.
    """
    user_input = entry.get().strip()
    if not user_input:
        messagebox.showwarning("Input Error", "Please enter a math problem.")
        return
    submit_button.config(state="disabled")
    progress_bar.pack(fill=tk.X, padx=10, pady=(0,10))
    progress_bar.start()
    executor.submit(process_input, user_input)

def process_input(user_input):
    """
    Process the user input in a separate thread.

    Args:
        user_input (str): The mathematical problem entered by the user.
    """
    try:
        update_status("Processing...")
        response, confidence, mean_conf, std_conf, was_truncated = chatbot(user_input)
        step_by_step_solution = show_step_by_step_solution(user_input)
        fig = plot_expression(user_input)

        # Schedule GUI updates in the main thread
        root.after(0, update_gui_results, user_input, response, confidence, mean_conf, std_conf, step_by_step_solution, fig, was_truncated)
    except Exception as e:
        logger.error(f"Error processing input '{user_input}': {e}")
        root.after(0, lambda: messagebox.showerror("Processing Error", f"An error occurred: {e}"))
    finally:
        root.after(0, reset_gui)

def update_gui_results(problem, response, confidence, mean_conf, std_conf, step_solution, plot_fig, was_truncated):
    """
    Update the GUI with the results from the chatbot.
    """
    # Clear previous tabs
    for widget in tab_control.tabs():
        tab_control.forget(widget)

    # Create new tabs
    solution_tab = ttk.Frame(tab_control)
    step_tab = ttk.Frame(tab_control)
    proof_tab = ttk.Frame(tab_control)
    plot_tab = ttk.Frame(tab_control)

    tab_control.add(solution_tab, text='Solution')
    tab_control.add(step_tab, text='Detailed Steps')
    tab_control.add(proof_tab, text='Proof')
    tab_control.add(plot_tab, text='Plot')
    tab_control.pack(expand=1, fill="both")

    # Solution Tab
    solution_text = tk.Text(solution_tab, wrap=tk.WORD, state=tk.NORMAL)
    solution_text.insert(tk.END, f"{response}\n\n**Confidence:** {confidence}\n**Mean Confidence:** {mean_conf:.2f}\n**Std Confidence:** {std_conf:.2f}")
    if was_truncated:
        solution_text.insert(tk.END, "\n\n*Note: The response has been truncated for readability.*")
    solution_text.config(state=tk.DISABLED)
    solution_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

    # Detailed Steps Tab
    step_text = tk.Text(step_tab, wrap=tk.WORD, state=tk.NORMAL)
    step_text.insert(tk.END, f"{step_solution}")
    step_text.config(state=tk.DISABLED)
    step_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

    # Proof Tab
    proof = advanced_proof_techniques(problem)
    proof_text = tk.Text(proof_tab, wrap=tk.WORD, state=tk.NORMAL)
    proof_text.insert(tk.END, f"{proof}")
    proof_text.config(state=tk.DISABLED)
    proof_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

    # Plot Tab
    plot_display = plot_tab
    if isinstance(plot_fig, Figure):
        canvas = FigureCanvastkAgg(plot_fig, master=plot_display)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    else:
        plot_label = tk.Label(plot_display, text=plot_fig, wraplength=500, justify="left")
        plot_label.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

    # Update confidence label
    confidence_label.config(text=f"Confidence: {confidence}")

    logger.debug("GUI results updated.")

def reset_gui():
    """
    Reset the GUI elements after processing.
    """
    progress_bar.stop()
    progress_bar.pack_forget()
    submit_button.config(state="normal")
    update_status("Ready.")

def on_history():
    """
    Display the calculation history in a new window.
    """
    history_window = tk.Toplevel(root)
    history_window.title("Calculation History")

    history_frame = ttk.Frame(history_window, padding="10")
    history_frame.pack(fill=tk.BOTH, expand=True)

    title_label = ttk.Label(history_frame, text="Calculation History", font=("Helvetica", 14, "bold"))
    title_label.pack(pady=(0, 10))

    history_text = tk.Text(history_frame, height=20, width=80, wrap=tk.WORD)
    history_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    scroll_bar = ttk.Scrollbar(history_frame, orient=tk.VERTICAL, command=history_text.yview)
    scroll_bar.pack(side=tk.RIGHT, fill=tk.Y)
    history_text.config(yscrollcommand=scroll_bar.set)

    with history_lock:
        for i, (query, result, confidence, mean_conf, std_conf) in enumerate(history, 1):
            history_text.insert(tk.END, f"{i}. **Problem:** {query}\n**Result:**\n{result}\n**Confidence:** {confidence}, **Mean Confidence:** {mean_conf:.2f}, **Std Confidence:** {std_conf:.2f}\n\n")

    history_window.update_idletasks()
    history_window.minsize(history_text.winfo_width() + 50, history_text.winfo_height() + 100)

def on_save_history():
    """
    Save the calculation history to a file.
    """
    if not history:
        messagebox.showinfo("No History", "There is no history to save.")
        return
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt"), ("CSV Files", "*.csv")])
    if file_path:
        try:
            with history_lock:
                if file_path.endswith('.csv'):
                    with open(file_path, 'w', newline='') as f:
                        writer = csv.writer(f)
                        writer.writerow(["Problem", "Result", "Confidence", "Mean Confidence", "Std Confidence"])
                        for entry in history:
                            writer.writerow(entry)
                else:
                    with open(file_path, 'w') as f:
                        for i, (query, result, confidence, mean_conf, std_conf) in enumerate(history, 1):
                            f.write(f"{i}. Problem: {query}\nResult:\n{result}\nConfidence: {confidence}, Mean: {mean_conf:.2f}, Std: {std_conf:.2f}\n\n")
            messagebox.showinfo("Success", "History saved successfully.")
            logger.info(f"History saved to '{file_path}'.")
        except Exception as e:
            logger.error(f"Error saving history to '{file_path}': {e}")
            messagebox.showerror("Save Error", f"Failed to save history: {e}")

def on_load_config():
    """
    Open the configuration settings window.
    """
    config_window = tk.Toplevel(root)
    config_window.title("Configuration Settings")

    config_frame = ttk.Frame(config_window, padding="10")
    config_frame.pack(fill=tk.BOTH, expand=True)

    labels = [
        "OpenAI API Key:",
        "WolframAlpha App ID:",
        "GPT Model:",
        "Max Depth:",
        "Precision:",
        "GPT Max Tokens:",
        "Debug Mode (True/False):",
        "Max Response Length:"
    ]
    keys = [
        "OPENAI_API_KEY",
        "WOLFRAM_APP_ID",
        "GPT_MODEL",
        "MAX_DEPTH",
        "PRECISION",
        "GPT_MAX_TOKENS",
        "DEBUG_MODE",
        "MAX_RESPONSE_LENGTH"
    ]
    entries = []

    for idx, key in enumerate(keys):
        label = ttk.Label(config_frame, text=labels[idx])
        label.grid(row=idx, column=0, padx=5, pady=5, sticky=tk.E)
        entry = ttk.Entry(config_frame, width=40)
        entry.grid(row=idx, column=1, padx=5, pady=5)
        entry.insert(0, str(config.get(key, default_config.get(key, ''))))
        entries.append(entry)

    def save_settings():
        """
        Save the updated configuration settings.
        """
        new_config = {}
        for key, entry in zip(keys, entries):
            new_config[key] = entry.get().strip()
        
        # Validate and convert numerical values
        try:
            new_config["MAX_DEPTH"] = int(new_config["MAX_DEPTH"])
            new_config["PRECISION"] = int(new_config["PRECISION"])
            new_config["GPT_MAX_TOKENS"] = int(new_config["GPT_MAX_TOKENS"])
            new_config["MAX_RESPONSE_LENGTH"] = int(new_config["MAX_RESPONSE_LENGTH"])
            new_config["DEBUG_MODE"] = new_config["DEBUG_MODE"].lower() in ['true', '1', 'yes']
            
            # Secure API Keys
            if new_config["WOLFRAM_APP_ID"] == 'YOUR_WOLFRAM_APP_ID' or new_config["OPENAI_API_KEY"] == 'YOUR_OPENAI_API_KEY':
                messagebox.showerror("Invalid Input", "Please set your WolframAlpha App ID and OpenAI API Key.")
                return
        except ValueError:
            messagebox.showerror("Invalid Input", "Please enter valid numerical values for Max Depth, Precision, GPT Max Tokens, and Max Response Length, and a valid boolean for Debug Mode.")
            return
        
        # Update global config
        config.update(new_config)
        save_config(config)
        
        # Update logging level based on debug mode
        logger.setLevel(logging.DEBUG if config["DEBUG_MODE"] else logging.INFO)
        file_handler.setLevel(logging.DEBUG if config["DEBUG_MODE"] else logging.INFO)
        console_handler.setLevel(logging.DEBUG if config["DEBUG_MODE"] else logging.INFO)
        
        if config["DEBUG_MODE"]:
            logger.debug("Debug mode enabled.")
        else:
            logger.info("Debug mode disabled.")
        
        # Reinitialize WolframAlpha client and set OpenAI API key
        initialize_clients()
        openai.api_key = config.get("OPENAI_API_KEY", "YOUR_OPENAI_API_KEY")
        
        messagebox.showinfo("Success", "Configuration updated successfully.")
        config_window.destroy()
        logger.info("Configuration settings updated by user.")
    
    save_button = ttk.Button(config_frame, text="Save", command=save_settings)
    save_button.grid(row=len(keys), column=0, columnspan=2, pady=10)

def on_export():
    """
    Handle the export to PDF action.
    """
    handle_export()

def on_exit():
    """
    Handle the exit event, ensuring graceful shutdown.
    """
    if messagebox.askokcancel("Exit", "Do you really want to exit?"):
        executor.shutdown(wait=False)
        root.destroy()

def update_status(message):
    """
    Update the status bar message.
    """
    status_var.set(message)
    root.update_idletasks()

# ------------------------- Log Viewing Function -------------------------
def open_log_file():
    """
    Open the log file using the default system editor.
    """
    try:
        if os.name == 'nt':  # For Windows
            os.startfile(LOG_FILE)
        elif os.name == 'posix':  # For macOS and Linux
            opener = "open" if sys.platform == "darwin" else "xdg-open"
            subprocess.call([opener, LOG_FILE])
        logger.debug("Opened log file.")
    except Exception as e:
        logger.error(f"Failed to open log file: {e}")
        messagebox.showerror("Error", f"Could not open log file: {e}")

# ------------------------- Main Application -------------------------

# Initialize main window
root = tk.Tk()
root.title("Advanced Math Solver with Chain-of-Thought Specialization")
root.protocol("WM_DELETE_WINDOW", on_exit)

# Style Configuration
style = ttk.Style()
style.theme_use("clam")

# Menu Bar
menubar = tk.Menu(root)

# Settings Menu
settings_menu = tk.Menu(menubar, tearoff=0)
settings_menu.add_command(label="Configuration", command=on_load_config)
settings_menu.add_separator()
settings_menu.add_command(label="Exit", command=on_exit)
menubar.add_cascade(label="Settings", menu=settings_menu)

# History Menu
history_menu = tk.Menu(menubar, tearoff=0)
history_menu.add_command(label="View History", command=on_history)
history_menu.add_command(label="Save History", command=on_save_history)
menubar.add_cascade(label="History", menu=history_menu)

# Debug Menu
debug_menu = tk.Menu(menubar, tearoff=0)
debug_menu.add_command(label="View Logs", command=lambda: open_log_file())
menubar.add_cascade(label="Debug", menu=debug_menu)

# Export Menu
export_menu = tk.Menu(menubar, tearoff=0)
export_menu.add_command(label="Export Latest Solution as PDF", command=handle_export)
menubar.add_cascade(label="Export", menu=export_menu)

root.config(menu=menubar)

# Entry Frame
entry_frame = ttk.Frame(root, padding="10")
entry_frame.pack(fill=tk.X)

entry_label = ttk.Label(entry_frame, text="Enter Math Problem:")
entry_label.pack(side=tk.LEFT, padx=(0,5))

entry = ttk.Entry(entry_frame, width=50)
entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0,5))
entry.bind('<Return>', lambda event: on_submit())

submit_button = ttk.Button(entry_frame, text="Submit", command=on_submit)
submit_button.pack(side=tk.LEFT, padx=(5,0))

# Progress Bar
progress_bar = ttk.Progressbar(root, mode='indeterminate')

# Tab Control for Results
tab_control = ttk.Notebook(root)

# Confidence Frame
confidence_frame = ttk.Frame(root, padding="10")
confidence_frame.pack(fill=tk.X)

confidence_label = ttk.Label(confidence_frame, text="Confidence: N/A", font=("Helvetica", 12))
confidence_label.pack()

# Status Bar
status_var = tk.StringVar()
status_var.set("Ready")
status_bar = ttk.Label(root, textvariable=status_var, relief=tk.SUNKEN, anchor='w')
status_bar.pack(fill=tk.X, side=tk.BOTTOM)

# ------------------------- Run Application -------------------------

if __name__ == "__main__":
    root.mainloop()