from collections import OrderedDict
from datetime import date
from flask import Blueprint, current_app, flash, redirect, request, send_from_directory, jsonify
from flask import render_template, session, abort

from DocumentManager.DocumentsManager import DocumentManager
from config import UPLOAD_FILES
from models.doc_manager import DocConfig
from models.ai_model import AITaskModelConfig, Balance, ModelTokenUsage, OpenAIModel, PromptFile, PromptType, SystemPrompt, ModelType
from models.chats import ChatMessage
from models.user import User
from services import auth_service
from extensions import db
from services.chat_service import client

from flask_babel import _



admin_bp = Blueprint("admin_panel", __name__)



@admin_bp.route('/admin/dashboard', endpoint='admin_panel')
@auth_service.admin_login_required()
def admin_panel():

    total_users = get_total_users()
    return render_template("admin.html",)



@admin_bp.route('/admin/dashboard', endpoint='ai_credit')
@auth_service.admin_login_required()
def ai_credit():


    return render_template("admin.html")


@auth_service.admin_login_required()
def get_total_users():
    try:
        total_users = User.query.count()
    except:
        total_users =  0
    return total_users



@admin_bp.route('/admin/dashboardmain', endpoint='dashboardmain')
@auth_service.admin_login_required()
def dashboardmain():


    total_users = User.query.order_by(User.created_at.desc()).count()

    total_prompts = ChatMessage.query.count()

    # مجموع توکن مصرف‌شده
    total_tokens = (
        db.session.query(
            db.func.sum(
                ModelTokenUsage.input_tokens +
                ModelTokenUsage.output_tokens
            )
        ).scalar()
        or 0
    )


    balance = Balance.query.get(1)  # get the only row
    if balance:
        used_usd = balance.initial_charge_usd - balance.remaining_balance_usd
        remaining_usd = balance.remaining_balance_usd
        print(f"Used USD: {used_usd}")
    else:
        used_usd = 0
        remaining_usd = 0
        print("No balance row found")



    usage_chart = (
        db.session.query(
            db.func.date(ModelTokenUsage.created_at).label("date"),
            OpenAIModel.name.label("model"),
            db.func.sum(
                ModelTokenUsage.input_tokens +
                ModelTokenUsage.output_tokens
            ).label("total_tokens")
        )
        .join(OpenAIModel, OpenAIModel.id == ModelTokenUsage.model_id)
        .filter(ModelTokenUsage.created_at >= db.func.current_date() - 30)
        .group_by(
            db.func.date(ModelTokenUsage.created_at),
            OpenAIModel.name
        )
        .order_by(
            db.func.date(ModelTokenUsage.created_at),
            OpenAIModel.name
        )
        .all()
    )

    chart_data = {}
    for date, model, tokens in usage_chart:
        date_str = date.strftime("%Y-%m-%d")
        chart_data.setdefault(date_str, {})
        chart_data[date_str][model] = int(tokens or 0)
                                          
    chart_labels = [str(row[0]) for row in usage_chart]
    chart_values = [row[1] for row in usage_chart]

    users = User.query.order_by(User.created_at.desc()).limit(20).all()

    return render_template(
        "admin/dashboard.html",
        total_users=total_users,
        total_prompts=total_prompts,
        total_tokens=total_tokens,
        used_usd=round(used_usd, 6),
        remaining_usd=round(remaining_usd, 6),
        chart_labels=chart_labels,
        chart_values=chart_values,
        chart_data = chart_data,
        users=users
    )



from datetime import date, timedelta
import random

def fake_usage_chart(days=7):
    today = date.today()
    data = []

    for i in range(days):
        d = today - timedelta(days=days - i)
        tokens = random.randint(5000, 20000)
        data.append((d, tokens))

    return data


def calculate_cost(model, input_tokens, output_tokens):
    input_cost = (input_tokens / 1000000) * model.input_cost_per_1m
    output_cost = (output_tokens / 1000000) * model.output_cost_per_1m
    return round(input_cost + output_cost, 6)



@admin_bp.route("/admin/prompts/<prompt_type>", methods=["GET", "POST"], endpoint='edit_prompt')
@auth_service.admin_login_required()
def edit_prompt(prompt_type):
    prompt_enum = PromptType(prompt_type)

    prompt = SystemPrompt.query.filter_by(type=prompt_enum).first_or_404()

    files = PromptFile.query.filter_by(
        user_id=session.get("user_id"),
        prompt_type=prompt_enum
    ).order_by(PromptFile.uploaded_at.desc()).all()



    if request.method == "POST":
        prompt.content = request.form["content"]
        prompt.updated_by = session.get("user_id")
        db.session.commit()
        flash(_("پرامپت ذخیره شد"))

    
    

    return render_template(
        "admin/edit_prompt.html",
        prompt=prompt,
        prompt_type = prompt_type,
        files = files
    )


@admin_bp.route("/admin/prompts/default-content", methods=["GET", "POST"], endpoint='get_default_prompt_content')
@auth_service.admin_login_required()
def get_default_prompt_content():
    prompt_type = request.args.get('type')
    
    if not prompt_type:
        return jsonify({'success': False, 'error': 'نوع پرامپت مشخص نشده'})
    
    try:
        from services.prompt import SYSTEM_PROMPT, STRUCTURED_ANS_PROMPT, TEXT_TO_SPEECH, CONVERSATIONAL_TTS_PROMPT, REFERENCES
        
        defaults = {
            'text': SYSTEM_PROMPT,
            'text2voice': TEXT_TO_SPEECH,
            'conversation': CONVERSATIONAL_TTS_PROMPT,
            'references': REFERENCES
        }
        
        content = defaults.get(prompt_type)
        
        if content is None:
            return jsonify({'success': False, 'error': 'نوع پرامپت نامعتبر است'})
        
        return jsonify({
            'success': True,
            'content': content
        })
        
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)})



import os
from werkzeug.utils import secure_filename


ALLOWED_EXTENSIONS = {"pdf", "doc", "docx", "txt"}

def allowed_file(filename):
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS


@admin_bp.route("/admin/upload/<prompt_type>", methods=["POST"], endpoint='upload_prompt_file')
@auth_service.admin_login_required()
def upload_prompt_file(prompt_type):
    if prompt_type not in ["text", "text2voice", "conversation"]:
        abort(400)
    
    prompt_enum = PromptType(prompt_type)

    file = request.files.get("file")
    if not file or file.filename == "":
        flash(_("فایلی انتخاب نشده"), "error")
        return redirect(request.referrer)

    if not allowed_file(file.filename):
        flash(_("فرمت فایل مجاز نیست"), "error")
        return redirect(request.referrer)

    filename = file.filename


    user_folder = os.path.join(
        UPLOAD_FILES,
        "prompts",
    )
    os.makedirs(user_folder, exist_ok=True)

    file_path = os.path.join(user_folder, filename)
    file.save(file_path)

    record = PromptFile(
        user_id=session.get("user_id"),
        prompt_type=prompt_enum,
        filename=filename,
        filepath=file_path
    )

    db.session.add(record)
    db.session.commit()

    doc_manager:DocumentManager = current_app.doc_manager
    doc_manager.run_safe_scan_directory()

    flash(_("فایل با موفقیت آپلود شد"), "success")
    return redirect(request.referrer)


@admin_bp.route("/api/doc-refresh", methods=["GET"], endpoint='documents_refresh')
@auth_service.admin_login_required()
def documents_refresh():
    user = auth_service.current_user()
    if user.is_admin():
        doc_manager:DocumentManager = current_app.doc_manager
        doc_manager.run_safe_scan_directory()
        return jsonify({"messages": "بروز رسانی موفق"})
    return jsonify({"messages": "دسترسی غیر مجاز"})


@admin_bp.route("/admin/delete/<int:file_id>", methods=["POST"], endpoint='delete_prompt_file')
@auth_service.admin_login_required()
def delete_prompt_file(file_id):
    file = PromptFile.query.get_or_404(file_id)

    if file.user_id != session.get("user_id"):
        abort(403)

    if os.path.exists(file.filepath):
        os.remove(file.filepath)

    db.session.delete(file)
    db.session.commit()

            
    doc_manager:DocumentManager = current_app.doc_manager
    doc_manager.run_safe_scan_directory()

    flash(_("فایل حذف شد"), "success")
    return redirect(request.referrer)



from flask import send_file
import os

@admin_bp.route(
    "/admin_panel/prompts/files/<int:file_id>/download",
    methods=["GET"],
    endpoint="download_prompt_file"
)
def download_prompt_file(file_id):


    file = PromptFile.query.get_or_404(file_id)


    full_path = file.filepath

    if not os.path.exists(full_path):
        print("FILE NOT FOUND:", full_path)
        abort(404)

    return send_file(
        full_path,
        as_attachment=True,
        download_name=file.filename
    )






@admin_bp.route("/admin_panel/set_balance", methods=["GET", "POST"], endpoint='set_balance')
@auth_service.admin_login_required()
def set_balance():
    balance = Balance.query.get(1)
    
    from models.ai_model import ModelTokenUsage
    from sqlalchemy import func
    
    token_count = ModelTokenUsage.query.count()
    total_cost = db.session.query(func.sum(ModelTokenUsage.total_cost)).scalar() or 0
    
    if request.method == "POST":

        remaining = float(request.form["remaining_balance"])

        Balance.query.filter_by(id=1).update({
     
            Balance.remaining_balance_usd: remaining
        })
        db.session.commit()
        flash(_("موجودی با موفقیت به‌روزرسانی شد"), "success")
        return redirect(url_for("admin_panel.set_balance"))

    return render_template('admin/set_balance.html', 
                         balance=balance,
                         token_count=token_count,
                         total_cost=total_cost,
                        )



from flask import request, redirect, url_for, flash

@admin_bp.route("/admin_panel/set_doc_config", methods=["GET", "POST"], endpoint='set_doc_config')
@auth_service.admin_login_required()
def set_doc_config():
    doc_config = DocConfig.query.get(1)
    if request.method == "POST":
        cache_lifetime = float(request.form["cache_lifetime"])
        chunk_size = float(request.form["chunk_size"])
        chunk_overlap = float(request.form["chunk_overlap"])
        batch_size = float(request.form["batch_size"])
        top_k = float(request.form["top_k"])

        config = DocConfig.query.get(1)

        if config:
            config.cache_lifetime = cache_lifetime
            config.chunk_size = chunk_size
            config.chunk_overlap = chunk_overlap
            config.batch_size = batch_size
            config.top_k = top_k
        else:
            config = DocConfig(
                id=1,
                cache_lifetime=cache_lifetime,
                chunk_size=chunk_size,
                chunk_overlap=chunk_overlap,
                batch_size=batch_size,
                top_k=top_k
            )
            db.session.add(config)

        db.session.commit()

        
        doc_manager:DocumentManager = current_app.doc_manager
        doc_manager.update_config(
            cache_lifetime=cache_lifetime,
            chunk_size=chunk_size,
            chunk_overlap=chunk_overlap,
            batch_size=batch_size,
            top_k=top_k
        )
        
        flash(_("تنظیمات فایل های داکیومنت با موفقیت به‌روزرسانی شد"), "success")
        return redirect(url_for("admin_panel.set_doc_config"))

    return render_template("admin/set_doc_config.html", doc_config=doc_config)



from flask import request, render_template
from sqlalchemy import func,case , desc
from datetime import datetime, timedelta
from models.chats import ChatMessage
from models.user import User

@admin_bp.route('/admin/dashboard/users', endpoint='dashboard_users')
@auth_service.admin_login_required()
def dashboard_users():
    start_date_str = request.args.get("start_date")
    end_date_str = request.args.get("end_date")

    try:
        end_date = datetime.strptime(end_date_str, "%Y-%m-%d") + timedelta(days=1) if end_date_str else datetime.utcnow() + timedelta(days=1)
        ret_end_date = datetime.strptime(end_date_str, "%Y-%m-%d")  if end_date_str else datetime.utcnow()
    except ValueError:
        end_date = datetime.utcnow() + timedelta(days=1)
        ret_end_date = datetime.utcnow()

    try:
        start_date = datetime.strptime(start_date_str, "%Y-%m-%d") if start_date_str else end_date - timedelta(days=30)
    except ValueError:
        start_date = end_date - timedelta(days=30)

    lang_query = db.session.query(
        func.date(ChatMessage.created_at).label("date"),
        ChatMessage.language,
        func.count(ChatMessage.id).label("count"),
        func.string_agg(
            case((User.phone != None, User.phone), else_="") + ' / ' +
            case((User.email != None, User.email), else_=""),
            ', '
        ).label("contacts")
    ).join(User, User.id == ChatMessage.user_id)\
    .filter(ChatMessage.created_at >= start_date)\
    .filter(ChatMessage.created_at < end_date)\
    .group_by(func.date(ChatMessage.created_at), ChatMessage.language)\
    .order_by(func.date(ChatMessage.created_at))



    lang_results = lang_query.all()

    lang_chart_data = {}
    lang_contacts = {}
    for date, lang, count, contacts in lang_results:
        date_str = date.strftime("%Y-%m-%d")
        lang_chart_data.setdefault(date_str, {})
        lang_chart_data[date_str][lang] = count
        lang_contacts.setdefault(date_str, {})
        lang_contacts[date_str][lang] = contacts or ""

    msg_query = db.session.query(
        func.date(ChatMessage.created_at).label("date"),
        func.count(ChatMessage.id).label("total_messages")
    ).filter(ChatMessage.created_at >= start_date)\
     .filter(ChatMessage.created_at < end_date)\
     .group_by(func.date(ChatMessage.created_at))\
     .order_by(func.date(ChatMessage.created_at))

    msg_results = msg_query.all()
    msg_chart_data = {date.strftime("%Y-%m-%d"): total for date, total in msg_results}

    languages = sorted({lang for date_data in lang_chart_data.values() for lang in date_data.keys()})
    colors = [
        '#065f46','#2563eb','#d97706','#db2777','#16a34a','#e11d48','#0ea5e9','#f97316',
        '#7c3aed','#14b8a6','#f43f5e','#22c55e','#eab308','#8b5cf6','#06b6d4','#f87171'
    ]
    lang_colors = OrderedDict()
    for i, lang in enumerate(languages):
        lang_colors[lang] = colors[i % len(colors)]

    avg_daily_messages = round(sum(msg_chart_data.values()) / max(1, len(msg_chart_data)))

    daily_users = (
        db.session.query(
            func.date(ChatMessage.created_at).label("day"),
            func.count(func.distinct(func.coalesce(User.phone, User.email))).label("unique_users")
        )
        .join(User, User.id == ChatMessage.user_id)
        .filter(ChatMessage.created_at >= start_date)
        .filter(ChatMessage.created_at < end_date)
        .group_by(func.date(ChatMessage.created_at))
        .order_by(func.date(ChatMessage.created_at))
        .all()
    )

    if daily_users:
        avg_daily_users = round(sum(day.unique_users for day in daily_users) / len(daily_users))
    else:
        avg_daily_users = 0

    lang_max_query = (
        db.session.query(
            ChatMessage.language,
            func.count(ChatMessage.id).label("total_messages")
        )
        .filter(ChatMessage.created_at >= start_date)
        .filter(ChatMessage.created_at < end_date)
        .filter(ChatMessage.language != 'un')
        .group_by(ChatMessage.language)
        .order_by(desc("total_messages"))
        .limit(1)
    )

    most_used_language = lang_max_query.first()
    if most_used_language:
        most_used_language_name = most_used_language.language
        most_used_language_count = most_used_language.total_messages
    else:
        most_used_language_name = "—"
        most_used_language_count = 0

    user_dominant_lang_query = (
        db.session.query(
            func.date(ChatMessage.created_at).label("day"),
            ChatMessage.user_id,
            ChatMessage.language,
            func.count(ChatMessage.id).label("msg_count")
        )
        .join(User, User.id == ChatMessage.user_id)
        .filter(ChatMessage.created_at >= start_date)
        .filter(ChatMessage.created_at < end_date)
        .filter(ChatMessage.language != 'un')
        .group_by(func.date(ChatMessage.created_at), ChatMessage.user_id, ChatMessage.language)
        .subquery()
    )

    from sqlalchemy import func as sa_func

    dominant_lang_per_day = (
        db.session.query(
            user_dominant_lang_query.c.day,
            user_dominant_lang_query.c.language,
            sa_func.count(user_dominant_lang_query.c.user_id).label("user_count")
        )
        .group_by(user_dominant_lang_query.c.day, user_dominant_lang_query.c.language)
        .order_by(user_dominant_lang_query.c.day)
        .all()
    )

    dominant_lang_chart_data = {}
    for day, language, user_count in dominant_lang_per_day:
        day_str = day.strftime("%Y-%m-%d")
        if day_str not in dominant_lang_chart_data:
            dominant_lang_chart_data[day_str] = {}
        dominant_lang_chart_data[day_str][language] = user_count

    return render_template(
        "admin/users.html",
        start_date=start_date.strftime("%Y-%m-%d"),
        end_date=ret_end_date.strftime("%Y-%m-%d"),
        lang_chart_data=lang_chart_data,
        lang_contacts=lang_contacts,
        msg_chart_data=msg_chart_data,
        languages=languages,
        selected_language=request.args.get("language", ""),
        lang_colors=lang_colors,
        avg_daily_users=avg_daily_users,
        avg_daily_messages=avg_daily_messages,
        most_used_language_name = most_used_language_name,
        most_used_language_count = most_used_language_count,
        dominant_lang_chart_data=dominant_lang_chart_data,
    )




@admin_bp.route("/admin_panel/models_settings", methods=["GET", "POST"], endpoint='models_settings')
@auth_service.admin_login_required()
def models_settings():
    models = OpenAIModel.query.all()
    
    current_config = AITaskModelConfig.get_current_config()
    
    text_model_id = None
    tts_model_id = None
    stt_model_id = None
    
    if current_config:
        text_model_id = current_config.text_model_id
        tts_model_id = current_config.text_to_voice_model_id
        stt_model_id = current_config.voice_to_text_model_id
    
    if request.method == "POST":
        pass

    model_types_dict = [{"value": mt.name, "label": mt.label} for mt in ModelType]
    
    return render_template(
        "admin/models.html", 
        models=models,
        text_model=text_model_id,
        tts_model=tts_model_id,
        stt_model=stt_model_id,
        current_config=current_config,
        model_types = model_types_dict,
    )


@admin_bp.route("/admin_panel/add_model", methods=["POST"])
@auth_service.admin_login_required()
def add_model():
    model_name = request.form.get('model_name')
    model_type = request.form.get('model_type')
    input_cost = request.form.get('input_cost')
    output_cost = request.form.get('output_cost')
    cache_cost = request.form.get('cache_cost', 0.0)
    
    if not model_name or not input_cost or not output_cost:
        flash(_('لطفاً تمام فیلدهای اجباری را پر کنید'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    try:
        input_cost = float(input_cost)
        output_cost = float(output_cost)
        cache_cost = float(cache_cost)
    except ValueError:
        flash(_('مقادیر هزینه باید عدد باشند'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    if input_cost < 0 or output_cost < 0 or cache_cost < 0:
        flash(_('هزینه‌ها نمی‌توانند منفی باشند'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    existing_model = OpenAIModel.query.filter_by(name=model_name).first()
    if existing_model:
        flash(_('مدلی با این نام قبلاً ثبت شده است'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    new_model = OpenAIModel(
        name=model_name,
        model_type=model_type,
        input_cost_per_1m=input_cost,
        output_cost_per_1m=output_cost,
        cache_cost_per_1m=cache_cost
    )
    
    try:
        db.session.add(new_model)
        db.session.commit()
        flash(_('مدل %(name)s با موفقیت اضافه شد', name=model_name), 'success')
    except Exception as e:
        db.session.rollback()
        current_app.logger.exception(e)
        flash(_('خطا در افزودن مدل'), 'error')
    
    return redirect(url_for('admin_panel.models_settings'))



@admin_bp.route("/admin_panel/edit_model", methods=["POST"])
@auth_service.admin_login_required()
def edit_model():
    model_id = request.form.get('model_id')
    model_name = request.form.get('model_name')
    model_type = request.form.get('model_type')
    input_cost = request.form.get('input_cost')
    output_cost = request.form.get('output_cost')
    cache_cost = request.form.get('cache_cost')
    
    if not model_id or not model_name or not input_cost or not output_cost:
        flash(_('اطلاعات ناقص است'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    try:
        model_id = int(model_id)
        input_cost = float(input_cost)
        output_cost = float(output_cost)
        cache_cost = float(cache_cost) if cache_cost else 0.0
    except ValueError:
        flash(_('مقادیر وارد شده نامعتبر است'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    if input_cost < 0 or output_cost < 0 or cache_cost < 0:
        flash(_('هزینه‌ها نمی‌توانند منفی باشند'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    model = OpenAIModel.query.get(model_id)
    if not model:
        flash(_('مدل مورد نظر یافت نشد'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    existing_model = OpenAIModel.query.filter(
        OpenAIModel.name == model_name,
        OpenAIModel.id != model_id
    ).first()
    
    if existing_model:
        flash(_('مدلی با این نام قبلاً ثبت شده است'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    model.name = model_name
    model.model_type = model_type
    model.input_cost_per_1m = input_cost
    model.output_cost_per_1m = output_cost
    model.cache_cost_per_1m = cache_cost
    
    try:
        db.session.commit()
        flash(_('مدل %(name)s با موفقیت به‌روزرسانی شد', name=model_name), 'success')
    except Exception as e:
        db.session.rollback()
        current_app.logger.exception(e)
        flash(_('خطا در به روزرسانی model'), 'error')
    
    return redirect(url_for('admin_panel.models_settings'))

@admin_bp.route("/admin_panel/delete_model", methods=["POST"])
@auth_service.admin_login_required()
def delete_model():

    model_id = request.form.get("model_id")

    if not model_id:
        flash(_("شناسه مدل نامعتبر است"), "error")
        return redirect(url_for("admin_panel.models_settings"))

    model = OpenAIModel.query.get(model_id)

    if not model:
        flash(_("مدل یافت نشد"), "error")
        return redirect(url_for("admin_panel.models_settings"))

    try:
        db.session.delete(model)
        db.session.commit()
        flash(_("مدل %(name)s با موفقیت حذف شد", name=model.name), "success")

    except Exception as e:
        db.session.rollback()
        current_app.logger.exception(e)
        flash(_('خطا در حذف مدل'), 'error')
        

    return redirect(url_for("admin_panel.models_settings"))

@admin_bp.route("/admin_panel/toggle_model/<int:model_id>", methods=["POST"])
@auth_service.admin_login_required()
def toggle_model(model_id):
    model = OpenAIModel.query.get(model_id)
    if not model:
        flash(_('مدل مورد نظر وجود ندارد'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    model.is_active = not model.is_active
    
    try:
        db.session.commit()
        status = _("فعال") if model.is_active else _("غیرفعال")
        flash(_('وضعیت مدل به %(status)s تغییر یافت', status=status), 'success')

    except Exception as e:
        db.session.rollback()
        current_app.logger.exception(e)
        flash(_('خطا در تغییر وضعیت'), 'error')
    
    return redirect(url_for('admin_panel.models_settings'))


@admin_bp.route("/admin_panel/get_model/<int:model_id>")
@auth_service.admin_login_required()
def get_model(model_id):
    model = OpenAIModel.query.get_or_404(model_id)
    return jsonify({
        'id': model.id,
        'name': model.name,
        'input_cost_per_1m': model.input_cost_per_1m,
        'output_cost_per_1m': model.output_cost_per_1m,
        'is_active': model.is_active
    })

@admin_bp.route("/admin_panel/assign_models", methods=["POST"],endpoint='assign_models')
@auth_service.admin_login_required()
def assign_models():
    current_config = AITaskModelConfig.get_current_config()
    
    if not current_config:
        current_config = AITaskModelConfig(is_active=True)
        db.session.add(current_config)
    
    text_model_id = request.form.get('text_model')
    tts_model_id = request.form.get('tts_model')
    stt_model_id = request.form.get('stt_model')
    
    if not all([text_model_id, tts_model_id, stt_model_id]):
        flash(_('لطفاً همه مدل‌ها را انتخاب کنید'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    try:
        text_model_id = int(text_model_id)
        tts_model_id = int(tts_model_id)
        stt_model_id = int(stt_model_id)
    except ValueError:
        flash(_('شناسه مدل نامعتبر است'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    text_model = OpenAIModel.query.get(text_model_id)
    tts_model = OpenAIModel.query.get(tts_model_id)
    stt_model = OpenAIModel.query.get(stt_model_id)
    
    if not all([text_model, tts_model, stt_model]):
        flash(_('یکی از مدل‌های انتخاب شده وجود ندارد'), 'error')
        return redirect(url_for('admin_panel.models_settings'))
    
    current_config.text_model_id = text_model_id
    current_config.text_to_voice_model_id = tts_model_id
    current_config.voice_to_text_model_id = stt_model_id
    
    try:
        db.session.commit()
        flash(_('تخصیص مدل‌ها با موفقیت ذخیره شد'), 'success')
    except Exception as e:
        db.session.rollback()
        current_app.logger.exception(e)
        flash(_('خطا در ذخیره تخصیص‌ها'), 'error')
    
    return redirect(url_for('admin_panel.models_settings'))



@admin_bp.route("/admin_panel/assign_single_model", methods=["POST"])
@auth_service.admin_login_required()
def assign_single_model():
    pass










@admin_bp.route("/admin_panel/clear-token-history", methods=["POST"])
@auth_service.admin_login_required()
def clear_token_history():
    try:
        data = request.get_json()
        
        if not data or not data.get('confirm'):
            return jsonify({'success': False, 'error': 'تایید انجام نشد'})
        
        from models.ai_model import ModelTokenUsage
        
        count = ModelTokenUsage.query.delete()
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': f'{count} رکورد با موفقیت حذف شد',
            'deleted_count': count
        })
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.exception(e)
        return jsonify({
            'success': False,
            'error': 'خطای داخلی رخ داد'
        })
    





@admin_bp.route('/admin_panel/messages-comparison', endpoint='dashboard_messages_comparison')
@auth_service.admin_login_required()
def dashboard_messages_comparison():
    start_date1_str = request.args.get("start_date1")
    end_date1_str = request.args.get("end_date1")
    
    start_date2_str = request.args.get("start_date2")
    end_date2_str = request.args.get("end_date2")
    
    try:
        end_date1 = datetime.strptime(end_date1_str, "%Y-%m-%d") + timedelta(days=1) if end_date1_str else datetime.utcnow() + timedelta(days=1)
        ret_end_date1 = datetime.strptime(end_date1_str, "%Y-%m-%d") if end_date1_str else datetime.utcnow()
    except ValueError:
        end_date1 = datetime.utcnow() + timedelta(days=1)
        ret_end_date1 = datetime.utcnow()
    
    try:
        start_date1 = datetime.strptime(start_date1_str, "%Y-%m-%d") if start_date1_str else end_date1 - timedelta(days=30)
    except ValueError:
        start_date1 = end_date1 - timedelta(days=30)
    
    try:
        end_date2 = start_date1
        ret_end_date2 = start_date1 - timedelta(days=1)
    except:
        end_date2 = datetime.utcnow() + timedelta(days=1)
        ret_end_date2 = datetime.utcnow()
    
    try:
        start_date2 = datetime.strptime(start_date2_str, "%Y-%m-%d") if start_date2_str else end_date2 - timedelta(days=30)
    except ValueError:
        start_date2 = end_date2 - timedelta(days=30)
    
    compare_mode = request.args.get("compare", "0") == "1"
    
    msg_query_period1 = db.session.query(
        func.date(ChatMessage.created_at).label("date"),
        func.count(ChatMessage.id).label("total_messages")
    ).filter(ChatMessage.created_at >= start_date1)\
     .filter(ChatMessage.created_at < end_date1)\
     .group_by(func.date(ChatMessage.created_at))\
     .order_by(func.date(ChatMessage.created_at))
    
    msg_results_period1 = msg_query_period1.all()
    period1_chart_data = {date.strftime("%Y-%m-%d"): total for date, total in msg_results_period1}
    
    total_messages_period1 = sum(period1_chart_data.values())
    
    msg_query_period2 = db.session.query(
        func.date(ChatMessage.created_at).label("date"),
        func.count(ChatMessage.id).label("total_messages")
    ).filter(ChatMessage.created_at >= start_date2)\
     .filter(ChatMessage.created_at < end_date2)\
     .group_by(func.date(ChatMessage.created_at))\
     .order_by(func.date(ChatMessage.created_at))
    
    msg_results_period2 = msg_query_period2.all()
    period2_chart_data = {date.strftime("%Y-%m-%d"): total for date, total in msg_results_period2}
    
    total_messages_period2 = sum(period2_chart_data.values())
    
    if total_messages_period1 > 0:
        percentage_change = ((total_messages_period2 - total_messages_period1) / total_messages_period1) * 100
    else:
        percentage_change = 0
    
    compare_chart_data = {
        "period1": period1_chart_data,
        "period2": period2_chart_data
    }
    
    all_dates = sorted(set(period1_chart_data.keys()) | set(period2_chart_data.keys()))
    
    comparison_data = []
    for date in all_dates:
        p1_count = period1_chart_data.get(date, 0)
        p2_count = period2_chart_data.get(date, 0)
        diff = p2_count - p1_count
        comparison_data.append((date, p1_count, p2_count, diff))
    
    lang_query_p1 = db.session.query(
        func.date(ChatMessage.created_at).label("date"),
        ChatMessage.language,
        func.count(ChatMessage.id).label("count")
    ).join(User, User.id == ChatMessage.user_id)\
    .filter(ChatMessage.created_at >= start_date1)\
    .filter(ChatMessage.created_at < end_date1)\
    .filter(ChatMessage.language != 'un')\
    .group_by(func.date(ChatMessage.created_at), ChatMessage.language)\
    .order_by(func.date(ChatMessage.created_at))
    
    lang_results_p1 = lang_query_p1.all()
    lang_chart_data_p1 = {}
    for date, lang, count in lang_results_p1:
        date_str = date.strftime("%Y-%m-%d")
        lang_chart_data_p1.setdefault(date_str, {})
        lang_chart_data_p1[date_str][lang] = count
    
    lang_query_p2 = db.session.query(
        func.date(ChatMessage.created_at).label("date"),
        ChatMessage.language,
        func.count(ChatMessage.id).label("count")
    ).join(User, User.id == ChatMessage.user_id)\
    .filter(ChatMessage.created_at >= start_date2)\
    .filter(ChatMessage.created_at < end_date2)\
    .filter(ChatMessage.language != 'un')\
    .group_by(func.date(ChatMessage.created_at), ChatMessage.language)\
    .order_by(func.date(ChatMessage.created_at))
    
    lang_results_p2 = lang_query_p2.all()
    lang_chart_data_p2 = {}
    for date, lang, count in lang_results_p2:
        date_str = date.strftime("%Y-%m-%d")
        lang_chart_data_p2.setdefault(date_str, {})
        lang_chart_data_p2[date_str][lang] = count
    
    most_used_p1 = db.session.query(
        ChatMessage.language,
        func.count(ChatMessage.id).label("total")
    ).filter(ChatMessage.created_at >= start_date1)\
     .filter(ChatMessage.created_at < end_date1)\
     .filter(ChatMessage.language != 'un')\
     .group_by(ChatMessage.language)\
     .order_by(desc("total"))\
     .first()
    
    most_used_lang_p1 = most_used_p1.language if most_used_p1 else "—"
    most_used_count_p1 = most_used_p1.total if most_used_p1 else 0
    
    most_used_p2 = db.session.query(
        ChatMessage.language,
        func.count(ChatMessage.id).label("total")
    ).filter(ChatMessage.created_at >= start_date2)\
     .filter(ChatMessage.created_at < end_date2)\
     .filter(ChatMessage.language != 'un')\
     .group_by(ChatMessage.language)\
     .order_by(desc("total"))\
     .first()
    
    most_used_lang_p2 = most_used_p2.language if most_used_p2 else "—"
    most_used_count_p2 = most_used_p2.total if most_used_p2 else 0
    
    avg_daily_p1 = round(total_messages_period1 / max(1, len(period1_chart_data)))
    avg_daily_p2 = round(total_messages_period2 / max(1, len(period2_chart_data)))
    print('nu')
    
    return render_template(
        "admin/messages_comparison.html",
        start_date1=start_date1.strftime("%Y-%m-%d"),
        end_date1=ret_end_date1.strftime("%Y-%m-%d"),
        start_date2=start_date2.strftime("%Y-%m-%d"),
        end_date2=ret_end_date2.strftime("%Y-%m-%d"),
        compare_mode=compare_mode,
        total_messages_period1=total_messages_period1,
        total_messages_period2=total_messages_period2,
        percentage_change=round(percentage_change, 1),
        compare_chart_data=compare_chart_data,
        comparison_data=comparison_data,
        lang_chart_data_p1=lang_chart_data_p1,
        lang_chart_data_p2=lang_chart_data_p2,
        most_used_lang_p1=most_used_lang_p1,
        most_used_count_p1=most_used_count_p1,
        most_used_lang_p2=most_used_lang_p2,
        most_used_count_p2=most_used_count_p2,
        avg_daily_p1=avg_daily_p1,
        avg_daily_p2=avg_daily_p2,
    )
