import sys
import subprocess
import os

# Auto-install dependencies if missing
for package in ["flask", "requests", "openpyxl"]:
    try:
        __import__(package)
    except ImportError:
        print(f"Пакет '{package}' не найден. Устанавливаем...")
        try:
            subprocess.check_call([sys.executable, "-m", "pip", "install", package])
            print(f"Пакет '{package}' успешно установлен!")
        except Exception as e:
            print(f"Ошибка при автоматической установке '{package}': {e}")
            sys.exit(1)

import json
import uuid
import smtplib
import requests
from requests.auth import HTTPBasicAuth
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
import ipaddress

# YooKassa official IP address ranges for webhook callbacks
YOOKASSA_ALLOWED_NETWORKS = [
    ipaddress.ip_network("185.71.76.0/27"),
    ipaddress.ip_network("185.71.77.0/27"),
    ipaddress.ip_network("77.75.153.0/25"),
    ipaddress.ip_network("77.75.154.128/25"),
    ipaddress.ip_network("77.75.156.11/32"),
    ipaddress.ip_network("77.75.156.35/32"),
    ipaddress.ip_network("2a02:5180::/32"),
    ipaddress.ip_network("2a02:5180:0:1509::/64"),
    ipaddress.ip_network("2a02:5180:0:2655::/64"),
    ipaddress.ip_network("2a02:5180:0:1533::/64"),
    ipaddress.ip_network("2a02:5180:0:2669::/64"),
]

def is_yookassa_ip(ip_str: str) -> bool:
    """Check if the provided IP address belongs to YooKassa's official subnets."""
    try:
        ip = ipaddress.ip_address(ip_str)
        return any(ip in net for net in YOOKASSA_ALLOWED_NETWORKS)
    except ValueError:
        return False

import openpyxl
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, Alignment, PatternFill
from flask import Flask, request, jsonify, redirect, url_for, session, render_template_string

# Import local modules
import config
from database import DatabaseManager

# Get root directory
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))

# Initialize SQLite database
db_path = os.path.join(ROOT_DIR, "bot_database.db")
db = DatabaseManager(db_path=db_path)

# Initialize Flask
# static_folder points to the root directory to serve the whole site!
app = Flask(__name__, static_folder=ROOT_DIR, static_url_path='')
app.secret_key = os.getenv("FLASK_SECRET_KEY", "ikp_stable_admin_session_key_secret_2026")

# Path to the Excel spreadsheet in the form directory
FILE_NAME = os.path.join(ROOT_DIR, "form", "registration_for_training.xlsx")

def init_excel():
    """Create the Excel file with styled headers if it doesn't exist."""
    recreate = False
    if os.path.exists(FILE_NAME):
        try:
            wb = load_workbook(FILE_NAME)
            ws = wb.active
            # Recreate if it does not have the 'id_user' column as the first header
            if ws.cell(row=1, column=1).value != "id_user":
                recreate = True
        except Exception:
            recreate = True

    if recreate:
        try:
            os.remove(FILE_NAME)
            print("Обнаружена старая структура Excel файла. Пересоздаём с новыми колонками...")
        except Exception as e:
            print(f"Не удалось удалить старый Excel файл: {e}")

    if not os.path.exists(FILE_NAME):
        # Ensure form directory exists
        os.makedirs(os.path.dirname(FILE_NAME), exist_ok=True)
        
        wb = Workbook()
        ws = wb.active
        ws.title = "Заявки на обучение"
        
        headers = [
            "id_user",
            "Имя", 
            "Номер телефона", 
            "E-mail", 
            "Ссылка на профиль ВКонтакте", 
            "Согласие с офертой", 
            "Согласие с политикой", 
            "Согласие на рассылку", 
            "Услуга",
            "Сумма",
            "Статус оплаты",
            "ID платежа YooKassa",
            "Дата регистрации",
            "Дата оплаты"
        ]
        
        ws.append(headers)
        
        # Style header cells
        header_font = Font(name="Calibri", size=11, bold=True, color="FFFFFF")
        header_fill = PatternFill(start_color="1F4E78", end_color="1F4E78", fill_type="solid")
        header_align = Alignment(horizontal="center", vertical="center")
        
        for col_num, header in enumerate(headers, 1):
            cell = ws.cell(row=1, column=col_num)
            cell.font = header_font
            cell.fill = header_fill
            cell.alignment = header_align
            
        column_widths = [15, 20, 25, 25, 30, 15, 15, 15, 25, 15, 15, 30, 22, 22]
        for i, width in enumerate(column_widths, 1):
            ws.column_dimensions[openpyxl.utils.get_column_letter(i)].width = width
            
        wb.save(FILE_NAME)
        print(f"Создан новый файл Excel с поддержкой платежей: {FILE_NAME}")

def get_next_user_id(ws):
    """Generate the next unique user ID in the format id_001, id_002..."""
    max_row = ws.max_row
    if max_row <= 1:
        return "id_001"
    
    last_id_val = ws.cell(row=max_row, column=1).value
    if not last_id_val or not str(last_id_val).startswith("id_"):
        return f"id_{(max_row - 1):03d}"
    
    try:
        numeric_part = int(str(last_id_val).split("_")[1])
        next_num = numeric_part + 1
        return f"id_{next_num:03d}"
    except (IndexError, ValueError):
        return f"id_{max_row:03d}"

def add_registration_to_excel(reg_id, data):
    """Append a new form submission row into the Excel sheet."""
    init_excel()
    
    try:
        wb = load_workbook(FILE_NAME)
        ws = wb.active
    except Exception as e:
        print(f"Ошибка загрузки Excel файла, пересоздаём: {e}")
        init_excel()
        wb = load_workbook(FILE_NAME)
        ws = wb.active
        
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    row = [
        reg_id,
        data.get("name", "").strip(),
        data.get("phone", "").strip(),
        data.get("email", "").strip(),
        data.get("vk", "").strip(),
        "Да" if data.get("agreeOferta") else "Нет",
        "Да" if data.get("agreePolicy") else "Нет",
        "Да" if data.get("agreeNewsletter") else "Нет",
        data.get("serviceName", "Разовая тренировка").strip(),
        float(data.get("servicePrice", 870)),
        "Не оплачено",
        data.get("yookassaPaymentId", ""),
        current_time,
        ""
    ]
    
    ws.append(row)
    
    new_row_index = ws.max_row
    data_align_left = Alignment(horizontal="left", vertical="center")
    data_align_center = Alignment(horizontal="center", vertical="center")
    
    for col_idx in range(1, len(row) + 1):
        cell = ws.cell(row=new_row_index, column=col_idx)
        if col_idx in [2, 4, 5, 9]:
            cell.alignment = data_align_left
        else:
            cell.alignment = data_align_center
            
    wb.save(FILE_NAME)

def update_excel_payment_status(reg_id, status="Оплачено", paid_at=""):
    """Update payment status in the Excel file for a specific registration ID."""
    init_excel()
    if not os.path.exists(FILE_NAME):
        return
        
    try:
        wb = load_workbook(FILE_NAME)
        ws = wb.active
        
        found = False
        for r in range(2, ws.max_row + 1):
            if str(ws.cell(row=r, column=1).value) == str(reg_id):
                ws.cell(row=r, column=11).value = status  # Col 11: Статус оплаты
                ws.cell(row=r, column=14).value = paid_at  # Col 14: Дата оплаты
                found = True
                break
                
        if found:
            wb.save(FILE_NAME)
            print(f"Статус оплаты заказа {reg_id} успешно обновлен в Excel на '{status}'")
    except Exception as e:
        print(f"Ошибка при обновлении статуса оплаты в Excel: {e}")

# ====================================================
# YooKassa REST API Functions
# ====================================================
def create_yookassa_payment(reg_id, amount, description, return_url, customer_email=None, customer_phone=None, customer_name=None):
    shop_id = config.YOOKASSA_SHOP_ID
    secret_key = config.YOOKASSA_SECRET_KEY

    if not shop_id or not secret_key:
        print("[YOOKASSA] Создание платежа пропущено: логин/пароль ЮKassa не настроены в .env")
        return None

    url = "https://api.yookassa.ru/v3/payments"
    headers = {
        "Idempotence-Key": str(uuid.uuid4()),
        "Content-Type": "application/json"
    }
    payload = {
        "amount": {
            "value": f"{amount:.2f}",
            "currency": "RUB"
        },
        "capture": True,
        "confirmation": {
            "type": "redirect",
            "return_url": return_url
        },
        "description": description[:128],
        "metadata": {
            "registration_id": reg_id
        }
    }

    # Add 54-FZ compliant receipt if customer contact is available
    if customer_email or customer_phone:
        clean_phone = None
        if customer_phone:
            clean_phone = "".join(filter(str.isdigit, customer_phone))
            if clean_phone.startswith("8") and len(clean_phone) == 11:
                clean_phone = "7" + clean_phone[1:]
                
        customer = {}
        if customer_name:
            customer["full_name"] = customer_name[:256]
        if customer_email:
            customer["email"] = customer_email
        if clean_phone:
            customer["phone"] = clean_phone
            
        payload["receipt"] = {
            "customer": customer,
            "tax_system_code": config.TAX_SYSTEM_CODE,
            "items": [
                {
                    "description": description[:128],
                    "quantity": "1.00",
                    "amount": {
                        "value": f"{amount:.2f}",
                        "currency": "RUB"
                    },
                    "vat_code": 1,  # Без НДС
                    "payment_mode": "full_payment",
                    "payment_subject": "service"
                }
            ]
        }

    try:
        response = requests.post(url, json=payload, headers=headers, auth=HTTPBasicAuth(shop_id, secret_key), timeout=15)
        if response.status_code == 200:
            res_data = response.json()
            payment_id = res_data.get("id")
            confirmation_url = res_data.get("confirmation", {}).get("confirmation_url")
            return {"payment_id": payment_id, "confirmation_url": confirmation_url}
        else:
            print(f"[YOOKASSA] Ошибка API ({response.status_code}): {response.text}")
            return None
    except Exception as e:
        print(f"[YOOKASSA] Исключение при вызове API ЮKassa: {e}")
        return None

def check_yookassa_payment_status(payment_id):
    """Retrieve payment status directly from YooKassa API."""
    shop_id = config.YOOKASSA_SHOP_ID
    secret_key = config.YOOKASSA_SECRET_KEY

    if not shop_id or not secret_key or not payment_id:
        return None

    url = f"https://api.yookassa.ru/v3/payments/{payment_id}"
    try:
        response = requests.get(url, auth=HTTPBasicAuth(shop_id, secret_key), timeout=15)
        if response.status_code == 200:
            res_data = response.json()
            return res_data.get("status")  # succeeded, pending, canceled
        else:
            print(f"[YOOKASSA] Ошибка проверки платежа {payment_id}: {response.text}")
            return None
    except Exception as e:
        print(f"[YOOKASSA] Исключение при проверке платежа: {e}")
        return None

# ====================================================
# Notifications Logic
# ====================================================
try:
    import vk_api
    from vk_api.utils import get_random_id
except ImportError:
    vk_api = None

def send_vk_operator_notification(reg_id, data, paid=False):
    """Send VK chat alert to operators about registrations."""
    if not vk_api:
        return
    
    token = getattr(config, "VK_TOKEN", "")
    operator_id = getattr(config, "OPERATOR_PEER_ID", 0)
    
    if not token or token == "your_vk_community_token_here" or not operator_id:
        return

    try:
        vk_session = vk_api.VkApi(token=token)
        vk = vk_session.get_api()
        
        status_emoji = "✅ [ОПЛАЧЕНО]" if paid else "⏳ [ОЖИДАЕТ ОПЛАТЫ]"
        
        message = (
            f"🌐 **Новая активность на сайте ИКП!**\n\n"
            f"Статус: {status_emoji}\n"
        )
        
        vk.messages.send(
            peer_id=operator_id,
            message=message,
            random_id=get_random_id()
        )
    except Exception as e:
        print(f"[VK] Ошибка отправки уведомления: {e}")

def send_email_notification(reg_id, data, paid=False):
    """Send SMTP email notification."""
    smtp_server = config.SMTP_SERVER
    smtp_port = config.SMTP_PORT
    smtp_user = config.SMTP_USER
    smtp_password = config.SMTP_PASSWORD
    smtp_from = config.SMTP_FROM or smtp_user
    smtp_to_raw = config.SMTP_TO or smtp_user
    smtp_to = [email.strip() for email in smtp_to_raw.split(',')]

    print(f"[SMTP] Настройки: Server={smtp_server}, Port={smtp_port}, User={smtp_user}, To={smtp_to}")

    if not smtp_server or not smtp_user or not smtp_password:
        print("[SMTP] Пропущено: параметры SMTP не заполнены в .env")
        return False

    status_str = "УСПЕШНО ОПЛАЧЕН" if paid else "СОЗДАН (ОЖИДАЕТ ОПЛАТЫ)"
    subject = f"Новый заказ на сайте ИКП #{reg_id} - {status_str}"

    html_content = f"""
    <html>
    <body style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #333; line-height: 1.6; background-color: #f4f6f9; padding: 20px;">
        <div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 12px; background-color: #ffffff; box-shadow: 0 4px 6px rgba(0,0,0,0.05);">
            <div style="background: linear-gradient(90deg, #1a1a2e 0%, #161625 100%); color: #ffffff; padding: 20px; border-radius: 8px; text-align: center;">
                <h2 style="margin: 0; text-transform: uppercase; letter-spacing: 1px;">ИКП — Детали заказа</h2>
            </div>
            
            <p style="margin-top: 20px;">Здравствуйте!</p>
            <p>На сайте зарегистрирована заявка с новым статусом:</p>
            
            <table style="width: 100%; border-collapse: collapse; margin-top: 20px;">
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568; width: 40%;">ID заявки:</td>
                    <td style="padding: 10px; font-family: monospace;">{reg_id}</td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Статус заказа:</td>
                    <td style="padding: 10px;">
                        <span style="display: inline-block; padding: 4px 10px; font-size: 0.8rem; font-weight: bold; border-radius: 4px; color: { '#ffffff' if paid else '#744210' }; background-color: { '#48bb78' if paid else '#ecc94b' };">
                            {status_str}
                        </span>
                    </td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Выбранная услуга:</td>
                    <td style="padding: 10px; font-weight: bold;">{data.get('serviceName')}</td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Сумма платежа:</td>
                    <td style="padding: 10px; font-weight: bold; color: #7c3aed;">{data.get('servicePrice')} ₽</td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Имя клиента:</td>
                    <td style="padding: 10px;">{data.get('name')}</td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Номер телефона:</td>
                    <td style="padding: 10px; font-family: monospace;">{data.get('phone')}</td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">E-mail:</td>
                    <td style="padding: 10px;">{data.get('email')}</td>
                </tr>
                <tr style="border-bottom: 1px solid #edf2f7;">
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Профиль VK:</td>
                    <td style="padding: 10px;"><a href="{data.get('vk')}" style="color: #3182ce;">{data.get('vk')}</a></td>
                </tr>
                <tr>
                    <td style="padding: 10px; font-weight: bold; color: #4a5568;">Дата регистрации:</td>
                    <td style="padding: 10px; font-size: 0.9rem; color: #718096;">{datetime.now().strftime("%d.%m.%Y %H:%M:%S")}</td>
                </tr>
            </table>
            
            <div style="margin-top: 30px; border-top: 1px solid #e2e8f0; padding-top: 20px; text-align: center; font-size: 0.75rem; color: #a0aec0;">
                Это автоматическое системное уведомление от ИКП.
            </div>
        </div>
    </body>
    </html>
    """

    server = None
    try:
        msg = MIMEMultipart('alternative')
        msg['Subject'] = subject
        msg['From'] = smtp_from
        msg['To'] = ', '.join(smtp_to)  # заголовок — строка
        msg.attach(MIMEText(html_content, 'html', 'utf-8'))

        if smtp_port == 465:
            server = smtplib.SMTP_SSL(smtp_server, smtp_port)
        else:
            server = smtplib.SMTP(smtp_server, smtp_port)
            server.starttls()

        server.login(smtp_user, smtp_password)
        server.sendmail(smtp_from, smtp_to, msg.as_string())  # smtp_to — список
        print(f"[SMTP] Письмо о заказе {reg_id} отправлено на {smtp_to}")
        return True
    except Exception as e:
        print(f"[SMTP] Ошибка отправки письма: {e}")
        return False
    finally:
        if server:
            try:
                server.quit()
            except Exception:
                pass

# ====================================================
# Flask Web App Routes
# ====================================================

# Template filters
@app.template_filter('numberformat')
def numberformat_filter(value):
    try:
        return f"{int(value):,}".replace(",", " ")
    except (ValueError, TypeError):
        return value

# Serve static files logic
@app.route('/')
def root_index():
    return app.send_static_file('index.html')

@app.route('/form/')
@app.route('/form/index.html')
def form_index():
    return app.send_static_file('form/index.html')

@app.after_request
def add_cors_headers(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
    return response

@app.route('/api/services', methods=['GET'])
def get_api_services():
    try:
        services = db.get_services()
        return jsonify({"status": "success", "services": services})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

@app.route('/submit', methods=['POST', 'OPTIONS'])
def submit():
    if request.method == 'OPTIONS':
        return '', 204

    try:
        data = request.json
        if not data:
            return jsonify({"status": "error", "message": "Отсутствуют данные запроса"}), 400

        # Validate mandatory data
        name = data.get("name", "").strip()
        phone = data.get("phone", "").strip()
        email = data.get("email", "").strip()
        
        if not name or not phone or not email:
            return jsonify({"status": "error", "message": "Заполните обязательные поля: Имя, Телефон, E-mail"}), 400

        init_excel()
        
        # Load excel to generate sequential user ID
        try:
            wb = load_workbook(FILE_NAME)
            ws = wb.active
        except Exception:
            init_excel()
            wb = load_workbook(FILE_NAME)
            ws = wb.active
            
        reg_id = get_next_user_id(ws)
        
        # Secure price lookup based on serviceId from SQLite database
        service_id = str(data.get("serviceId", "web_1")).strip()
        db_services = db.get_services()
        service_info = db_services.get(service_id)
        
        if not service_info:
            return jsonify({"status": "error", "message": f"Выбранная услуга '{service_id}' не найдена в базе данных"}), 400
            
        service_name = service_info["name"]
        amount = service_info["price_numeric"]

        # 1. YooKassa checkout generation
        return_url = f"{request.host_url}?success=true&reg_id={reg_id}&service_id={service_id}"
        payment_info = create_yookassa_payment(
            reg_id=reg_id,
            amount=amount,
            description=f"Оплата: {service_name} (ИКП)",
            return_url=return_url,
            customer_email=email,
            customer_phone=phone,
            customer_name=name
        )

        payment_id = None
        payment_url = None
        if payment_info:
            payment_id = payment_info.get("payment_id")
            payment_url = payment_info.get("confirmation_url")
            
        # Update payload dict with secure details
        data_to_save = data.copy()
        data_to_save["yookassaPaymentId"] = payment_id or ""
        data_to_save["serviceName"] = service_name
        data_to_save["servicePrice"] = amount
        
        # 2. Save registration in SQLite database as pending
        db.add_web_registration(reg_id, {
            "name": name,
            "phone": phone,
            "email": email,
            "vk": data.get("vk", "").strip(),
            "agreeOferta": data.get("agreeOferta"),
            "agreePolicy": data.get("agreePolicy"),
            "agreeNewsletter": data.get("agreeNewsletter"),
            "serviceName": service_name,
            "servicePrice": amount,
            "paymentStatus": "pending",
            "yookassaPaymentId": payment_id
        })
        
        # 3. Save initial registration in Excel
        add_registration_to_excel(reg_id, data_to_save)

        # 4. Trigger operator alerts (unpaid yet)
        send_vk_operator_notification(reg_id, data_to_save, paid=False)
        send_email_notification(reg_id, data_to_save, paid=False)

        res = {"status": "success", "message": "Заявка зарегистрирована!"}
        if payment_url:
            res["payment_url"] = payment_url
            
        return jsonify(res)

    except PermissionError:
        return jsonify({
            "status": "error", 
            "message": "Файл таблицы Excel заблокирован. Пожалуйста, закройте Excel на сервере и попробуйте отправить форму заново."
        }), 500
    except Exception as e:
        import traceback
        traceback.print_exc()
        return jsonify({"status": "error", "message": str(e)}), 500

# ====================================================
# YooKassa Webhook Listener
# ====================================================
@app.route('/webhook/yookassa', methods=['POST'])
def yookassa_webhook():
    try:
        # Enforce YooKassa IP filtering if enabled
        if config.VERIFY_WEBHOOK_IP:
            # Handle proxy and Docker headers
            x_forwarded_for = request.headers.get("X-Forwarded-For")
            if x_forwarded_for:
                client_ip = x_forwarded_for.split(',')[0].strip()
            else:
                client_ip = request.remote_addr

            if not is_yookassa_ip(client_ip):
                print(f"[SECURITY WARNING] Заблокирован запрос к вебхуку от недоверенного IP: {client_ip}")
                return jsonify({"status": "error", "message": "Access Denied: Untrusted IP"}), 403

        event_data = request.json
        if not event_data:
            return 'Empty body', 400

        event_type = event_data.get("event")
        if event_type == "payment.succeeded":
            payment_obj = event_data.get("object", {})
            payment_id = payment_obj.get("id")
            metadata = payment_obj.get("metadata", {})
            reg_id = metadata.get("registration_id")

            if reg_id:
                # Retrieve existing record
                reg = db.get_web_registration(reg_id)
                if reg:
                    # Only process if status is not already paid
                    if reg.get("payment_status") != "paid":
                        paid_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                        
                        # 1. Update SQLite Status
                        db.update_web_payment_status(reg_id, "paid", payment_id, paid_at)
                        
                        # 2. Update Excel file Status
                        update_excel_payment_status(reg_id, "Оплачено", paid_at)
                        
                        # Rebuild data dict for notification helpers
                        notify_data = {
                            "name": reg.get("name"),
                            "phone": reg.get("phone"),
                            "email": reg.get("email"),
                            "vk": reg.get("vk_link"),
                            "agreeOferta": reg.get("agree_oferta"),
                            "agreePolicy": reg.get("agree_policy"),
                            "agreeNewsletter": reg.get("agree_newsletter"),
                            "serviceName": reg.get("service_name"),
                            "servicePrice": reg.get("amount")
                        }
                        
                        # 3. Send paid success notifications
                        send_vk_operator_notification(reg_id, notify_data, paid=True)
                        send_email_notification(reg_id, notify_data, paid=True)
                        
                        print(f"[WEBHOOK] Заявка {reg_id} успешно переведена в статус ОПЛАЧЕНО.")
                else:
                    print(f"[WEBHOOK] Заявка {reg_id} не найдена в базе данных.")
            else:
                print("[WEBHOOK] Отсутствует registration_id в метаданных платежа.")

        return 'OK', 200

    except Exception as e:
        print(f"[WEBHOOK] Исключение при обработке вебхука: {e}")
        return 'Internal Server Error', 500

# ====================================================
# Admin Cabinet Views (ЛК Администратора)
# ====================================================

# Шаблон страницы ошибки доступа
ACCESS_DENIED_TEMPLATE = """
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ИКП Админ | Ошибка авторизации</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Montserrat:wght@700;800&display=swap" rel="stylesheet">
    <style>body { font-family: 'Inter', sans-serif; background-color: #0a0a0f; }</style>
</head>
<body class="min-h-screen flex items-center justify-center bg-[radial-gradient(circle_at_center,_rgba(124,58,237,0.1)_0%,_rgba(10,10,15,1)_100%)]">
    <div class="w-full max-w-md p-8 bg-slate-900/60 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl text-center">
        <div class="text-5xl mb-4">🔒</div>
        <h2 class="font-display font-black text-2xl text-white uppercase mb-2" style="font-family:'Montserrat',sans-serif">Ошибка доступа</h2>
        <p class="text-slate-400 text-sm mb-6">{{ error }}</p>
        <a href="{{ login_url }}" class="inline-block w-full py-3 bg-purple-600 hover:bg-purple-500 text-white font-bold text-sm uppercase tracking-wider rounded-xl transition">
            Войти через Authentik
        </a>
    </div>
</body>
</html>
"""

DASHBOARD_TEMPLATE = """
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ИКП Админ | Реестр оплат</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@800;900&display=swap" rel="stylesheet">
    <style>
        body { font-family: 'Inter', sans-serif; background-color: #050508; color: #e2e8f0; }
        .font-display { font-family: 'Montserrat', sans-serif; }
        ::-webkit-scrollbar { width: 8px; height: 8px; }
        ::-webkit-scrollbar-track { background: #0c0c14; }
        ::-webkit-scrollbar-thumb { background: #1f1f2e; border-radius: 4px; }
        ::-webkit-scrollbar-thumb:hover { background: #2d2d44; }
    </style>
</head>
<body class="min-h-screen bg-[radial-gradient(ellipse_at_top,_rgba(26,15,46,0.8)_0%,_rgba(5,5,8,1)_80%)]">
    <header class="border-b border-white/5 bg-black/40 backdrop-blur-md sticky top-0 z-30">
        <div class="max-w-[1400px] mx-auto px-6 h-20 flex items-center justify-between">
            <div class="flex items-center gap-4">
                <span class="font-display font-black text-2xl tracking-wider text-white uppercase bg-gradient-to-r from-purple-500 to-blue-500 bg-clip-text text-transparent">ИКП</span>
                <span class="h-4 w-px bg-white/20"></span>
                <span class="text-xs font-mono text-slate-400 uppercase tracking-widest">Панель управления оплат</span>
            </div>
            <a href="{{ url_for('admin_logout') }}" class="px-4 py-2 bg-red-950/20 hover:bg-red-950/40 border border-red-900/30 hover:border-red-500/50 text-red-200 text-xs font-bold uppercase tracking-wider rounded-lg transition">
                Выйти
            </a>
        </div>
    </header>

    <main class="max-w-[1400px] mx-auto px-6 py-10 space-y-8">
        <!-- Tab navigation -->
        <div class="border border-white/5 bg-slate-900/40 rounded-2xl p-1.5 flex gap-2 max-w-xs">
            <button onclick="switchTab('orders')" id="tab-btn-orders" class="flex-1 py-2 rounded-xl text-xs font-bold uppercase tracking-wider bg-purple-600 text-white transition">Заявки</button>
            <button onclick="switchTab('services')" id="tab-btn-services" class="flex-1 py-2 rounded-xl text-xs font-bold uppercase tracking-wider bg-transparent text-slate-400 hover:text-slate-200 transition">Услуги</button>
        </div>

        <!-- SECTION: ORDERS -->
        <div id="section-orders" class="space-y-8">
            <!-- Stats cards -->
            <div class="grid grid-cols-1 md:grid-cols-4 gap-6">
                <div class="p-6 bg-slate-900/40 border border-white/5 rounded-2xl backdrop-blur-sm">
                    <p class="text-xs font-mono text-slate-400 uppercase tracking-wider mb-1">Всего заявок</p>
                    <p class="font-display font-black text-3xl text-white">{{ stats.total }}</p>
                </div>
                <div class="p-6 bg-slate-900/40 border border-white/5 rounded-2xl backdrop-blur-sm">
                    <p class="text-xs font-mono text-emerald-400 uppercase tracking-wider mb-1">Оплачено заказов</p>
                    <p class="font-display font-black text-3xl text-emerald-400">{{ stats.paid_count }}</p>
                </div>
                <div class="p-6 bg-slate-900/40 border border-white/5 rounded-2xl backdrop-blur-sm">
                    <p class="text-xs font-mono text-yellow-500 uppercase tracking-wider mb-1">Ожидает оплаты</p>
                    <p class="font-display font-black text-3xl text-yellow-500">{{ stats.pending_count }}</p>
                </div>
                <div class="p-6 bg-slate-900/40 border border-white/5 rounded-2xl backdrop-blur-sm">
                    <p class="text-xs font-mono text-blue-400 uppercase tracking-wider mb-1">Сумма сборов</p>
                    <p class="font-display font-black text-3xl text-blue-400">{{ stats.total_revenue | int | numberformat }} ₽</p>
                </div>
            </div>

            <!-- Filter and Search controls -->
            <div class="flex flex-col md:flex-row items-stretch md:items-center justify-between gap-4 p-4 bg-slate-900/20 border border-white/5 rounded-2xl">
                <div class="flex flex-wrap items-center gap-2">
                    <button onclick="filterStatus('all')" class="status-tab px-4 py-2 rounded-lg text-xs font-bold uppercase tracking-wider bg-purple-600 text-white transition" id="tab-all">Все</button>
                    <button onclick="filterStatus('paid')" class="status-tab px-4 py-2 rounded-lg text-xs font-bold uppercase tracking-wider bg-slate-800 text-slate-300 hover:bg-slate-700 transition" id="tab-paid">Оплачено</button>
                    <button onclick="filterStatus('pending')" class="status-tab px-4 py-2 rounded-lg text-xs font-bold uppercase tracking-wider bg-slate-800 text-slate-300 hover:bg-slate-700 transition" id="tab-pending">Ожидает оплаты</button>
                </div>
                
                <div class="relative flex-1 max-w-md">
                    <input type="text" id="search" oninput="searchTable()" placeholder="Поиск по имени, телефону или email..." 
                           class="w-full pl-10 pr-4 py-2 bg-black/40 border border-white/5 rounded-xl text-sm text-white placeholder-slate-500 focus:outline-none focus:border-purple-500 transition">
                    <span class="absolute left-3.5 top-2.5 text-slate-500">🔍</span>
                </div>
            </div>

            <!-- Orders Table -->
            <div class="bg-slate-900/20 border border-white/5 rounded-2xl overflow-hidden shadow-xl">
                <div class="overflow-x-auto">
                    <table class="w-full text-left border-collapse" id="orders-table">
                        <thead>
                            <tr class="border-b border-white/5 bg-white/[0.02] text-xs font-mono text-slate-400 uppercase tracking-wider">
                                <th class="p-4">ID</th>
                                <th class="p-4">Клиент</th>
                                <th class="p-4">Контакты</th>
                                <th class="p-4">Услуга</th>
                                <th class="p-4">Сумма</th>
                                <th class="p-4 text-center">Статус</th>
                                <th class="p-4">Регистрация</th>
                                <th class="p-4 text-center">Действие</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-white/[0.03]">
                            {% for reg in registrations %}
                            <tr class="order-row hover:bg-white/[0.01] transition-all text-sm" data-status="{{ reg.payment_status }}">
                                <td class="p-4 font-mono text-xs text-slate-400">{{ reg.id }}</td>
                                <td class="p-4 font-semibold text-white">
                                    {{ reg.name }}
                                </td>
                                <td class="p-4 space-y-1">
                                    <div class="flex items-center gap-2 text-xs">
                                        <span>📞</span> <span class="search-target font-mono">{{ reg.phone }}</span>
                                    </div>
                                    <div class="flex items-center gap-2 text-xs">
                                        <span>✉️</span> <span class="search-target font-mono text-slate-400">{{ reg.email }}</span>
                                    </div>
                                    {% if reg.vk_link %}
                                    <div class="flex items-center gap-2 text-xs">
                                        <span>🌐</span> <a href="{{ reg.vk_link }}" target="_blank" class="text-blue-400 hover:underline font-mono text-[11px] truncate max-w-[150px]">{{ reg.vk_link }}</a>
                                    </div>
                                    {% endif %}
                                </td>
                                <td class="p-4">
                                    <span class="px-2.5 py-1 bg-white/5 rounded text-xs text-glow-blue border border-white/5 font-semibold text-white">{{ reg.service_name }}</span>
                                </td>
                                <td class="p-4 font-mono font-bold text-white">{{ reg.amount | int }} ₽</td>
                                <td class="p-4 text-center">
                                    {% if reg.payment_status == 'paid' %}
                                    <span class="inline-flex items-center gap-1.5 px-2.5 py-1 bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-xs font-bold uppercase tracking-wider rounded-full">
                                        <span class="w-1.5 h-1.5 bg-emerald-400 rounded-full"></span> Оплачено
                                    </span>
                                    {% else %}
                                    <span class="inline-flex items-center gap-1.5 px-2.5 py-1 bg-yellow-500/10 border border-yellow-500/20 text-yellow-500 text-xs font-bold uppercase tracking-wider rounded-full">
                                        <span class="w-1.5 h-1.5 bg-yellow-500 rounded-full animate-pulse"></span> Ожидает
                                    </span>
                                    {% endif %}
                                </td>
                                <td class="p-4 text-xs text-slate-400 space-y-0.5">
                                    <div>Рег: {{ reg.created_at }}</div>
                                    {% if reg.paid_at %}
                                    <div class="text-emerald-400 font-mono text-[10px]">Опл: {{ reg.paid_at }}</div>
                                    {% endif %}
                                </td>
                                <td class="p-4 text-center">
                                    {% if reg.payment_status != 'paid' and reg.yookassa_payment_id %}
                                    <button onclick="checkStatus('{{ reg.id }}', this)" 
                                            class="px-3 py-1.5 bg-purple-950/30 hover:bg-purple-900/50 border border-purple-900/40 hover:border-purple-500/50 text-purple-300 text-xs font-bold uppercase tracking-wider rounded-lg transition flex items-center gap-1 mx-auto">
                                        <span>🔄</span> Проверить
                                    </button>
                                    {% else %}
                                    <span class="text-xs text-slate-500 font-mono">-</span>
                                    {% endif %}
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <!-- SECTION: SERVICES -->
        <div id="section-services" class="hidden space-y-8">
            <!-- Services Header and Add Button -->
            <div class="flex justify-between items-center bg-slate-900/40 border border-white/5 rounded-2xl p-6">
                <div>
                    <h2 class="font-display font-black text-2xl text-white uppercase tracking-wider">Каталог услуг</h2>
                    <p class="text-xs font-mono text-purple-400 uppercase tracking-widest">Управление тарифами и ценами</p>
                </div>
                <button onclick="openAddModal()" class="px-5 py-3 bg-purple-600 hover:bg-purple-500 text-white font-display font-black text-xs uppercase tracking-wider rounded-xl shadow-lg shadow-purple-600/20 hover:shadow-purple-600/40 transform hover:-translate-y-0.5 transition duration-200 flex items-center gap-2">
                    <span>➕</span> Добавить услугу
                </button>
            </div>

            <!-- Services Table -->
            <div class="bg-slate-900/20 border border-white/5 rounded-2xl overflow-hidden shadow-xl">
                <div class="overflow-x-auto">
                    <table class="w-full text-left border-collapse" id="services-table">
                        <thead>
                            <tr class="border-b border-white/5 bg-white/[0.02] text-xs font-mono text-slate-400 uppercase tracking-wider">
                                <th class="p-4">ID услуги</th>
                                <th class="p-4">Название</th>
                                <th class="p-4">Отображаемая цена</th>
                                <th class="p-4">Числовая цена (для YooKassa)</th>
                                <th class="p-4">Описание / Игры</th>
                                <th class="p-4 text-center">Статус</th>
                                <th class="p-4 text-center">Действия</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-white/[0.03]">
                            {% for svc in services %}
                            <tr class="hover:bg-white/[0.01] transition-all text-sm">
                                <td class="p-4 font-mono text-xs text-purple-400 font-semibold">{{ svc.id }}</td>
                                <td class="p-4 font-semibold text-white">{{ svc.name }}</td>
                                <td class="p-4 font-mono text-slate-300">{{ svc.price }}</td>
                                <td class="p-4 font-mono font-bold text-white">{{ svc.price_numeric | int }} ₽</td>
                                <td class="p-4 text-slate-400 max-w-xs truncate">{{ svc.description }}</td>
                                <td class="p-4 text-center">
                                    {% if svc.is_active == 1 %}
                                    <span class="inline-flex items-center gap-1.5 px-2.5 py-1 bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-xs font-bold uppercase tracking-wider rounded-full">
                                        <span class="w-1.5 h-1.5 bg-emerald-400 rounded-full"></span> Активна
                                    </span>
                                    {% else %}
                                    <span class="inline-flex items-center gap-1.5 px-2.5 py-1 bg-slate-500/10 border border-slate-500/20 text-slate-400 text-xs font-bold uppercase tracking-wider rounded-full">
                                        <span class="w-1.5 h-1.5 bg-slate-400 rounded-full"></span> Отключена
                                    </span>
                                    {% endif %}
                                </td>
                                <td class="p-4 text-center">
                                    <button onclick="openEditModal('{{ svc.id }}', '{{ svc.name | replace("'", "\\'") }}', '{{ svc.price | replace("'", "\\'") }}', '{{ svc.price_numeric }}', '{{ svc.description | replace("'", "\\'") | replace("\n", " ") }}', {{ svc.is_active }})" 
                                            class="inline-flex items-center gap-1 px-3 py-1.5 bg-blue-950/30 hover:bg-blue-900/50 border border-blue-900/40 hover:border-blue-500/50 text-blue-300 text-xs font-bold uppercase tracking-wider rounded-lg transition">
                                        ✏️ Ред.
                                    </button>
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </main>

    <!-- Modal Add Service -->
    <div id="modal-add-service" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center hidden">
        <div class="w-full max-w-lg p-8 bg-slate-900 border border-white/10 rounded-2xl shadow-2xl relative">
            <button onclick="closeAddModal()" class="absolute top-4 right-4 text-slate-400 hover:text-white text-xl">✕</button>
            <h3 class="font-display font-black text-2xl text-white uppercase tracking-wider mb-6">Добавить новую услугу</h3>
            
            <form id="form-add-service" class="space-y-4" onsubmit="submitAddService(event)">
                <div>
                    <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">ID услуги (уникальный, латиница)</label>
                    <input type="text" id="add-svc-id" required placeholder="например: web_6" 
                           class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                </div>
                <div>
                    <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Название услуги</label>
                    <input type="text" id="add-svc-name" required placeholder="например: Индивидуальное занятие" 
                           class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                </div>
                <div class="grid grid-cols-2 gap-4">
                    <div>
                        <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Отображаемая цена</label>
                        <input type="text" id="add-svc-price" required placeholder="например: 1 500 ₽" 
                               class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Числовая цена (для YooKassa)</label>
                        <input type="number" id="add-svc-price-num" required step="0.01" placeholder="1500" 
                               class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                    </div>
                </div>
                <div>
                    <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Описание / Игры</label>
                    <textarea id="add-svc-desc" rows="3" placeholder="Описание услуги..." 
                              class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition"></textarea>
                </div>
                <button type="submit" class="w-full py-3 bg-purple-600 hover:bg-purple-500 text-white font-display font-black text-sm uppercase tracking-wider rounded-xl shadow-lg transition">
                    Добавить услугу
                </button>
            </form>
        </div>
    </div>

    <!-- Modal Edit Service -->
    <div id="modal-edit-service" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center hidden">
        <div class="w-full max-w-lg p-8 bg-slate-900 border border-white/10 rounded-2xl shadow-2xl relative">
            <button onclick="closeEditModal()" class="absolute top-4 right-4 text-slate-400 hover:text-white text-xl">✕</button>
            <h3 class="font-display font-black text-2xl text-white uppercase tracking-wider mb-6">Редактировать услугу</h3>
            
            <form id="form-edit-service" class="space-y-4" onsubmit="submitEditService(event)">
                <input type="hidden" id="edit-svc-id">
                <div>
                    <label class="block text-xs font-bold text-slate-400 uppercase tracking-wider mb-1">ID услуги (нельзя изменить)</label>
                    <input type="text" id="edit-svc-id-display" readonly 
                           class="w-full px-4 py-2 bg-black/30 border border-white/5 rounded-xl text-slate-500 focus:outline-none cursor-not-allowed">
                </div>
                <div>
                    <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Название услуги</label>
                    <input type="text" id="edit-svc-name" required 
                           class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                </div>
                <div class="grid grid-cols-2 gap-4">
                    <div>
                        <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Отображаемая цена</label>
                        <input type="text" id="edit-svc-price" required 
                               class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Числовая цена (для YooKassa)</label>
                        <input type="number" id="edit-svc-price-num" required step="0.01" 
                               class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition">
                    </div>
                </div>
                <div>
                    <label class="block text-xs font-bold text-blue-400 uppercase tracking-wider mb-1">Описание / Игры</label>
                    <textarea id="edit-svc-desc" rows="3" 
                              class="w-full px-4 py-2 bg-black/50 border border-white/10 rounded-xl text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 transition"></textarea>
                </div>
                <div class="flex items-center gap-2">
                    <input type="checkbox" id="edit-svc-active" class="w-4 h-4 rounded text-purple-600 focus:ring-purple-500 bg-black/50 border-white/10">
                    <label for="edit-svc-active" class="text-sm font-bold text-slate-300 uppercase tracking-wider cursor-pointer">Активна (доступна для выбора и оплаты)</label>
                </div>
                <button type="submit" class="w-full py-3 bg-purple-600 hover:bg-purple-500 text-white font-display font-black text-sm uppercase tracking-wider rounded-xl shadow-lg transition">
                    Сохранить изменения
                </button>
            </form>
        </div>
    </div>

    <script id="services-data" type="application/json">
        {{ services | tojson }}
    </script>

    <script>
        let currentFilter = 'all';

        const servicesData = JSON.parse(document.getElementById('services-data').textContent);

        function switchTab(tab) {
            if (tab === 'orders') {
                document.getElementById('section-orders').classList.remove('hidden');
                document.getElementById('section-services').classList.add('hidden');
                
                document.getElementById('tab-btn-orders').className = "flex-1 py-2 rounded-xl text-xs font-bold uppercase tracking-wider bg-purple-600 text-white transition";
                document.getElementById('tab-btn-services').className = "flex-1 py-2 rounded-xl text-xs font-bold uppercase tracking-wider bg-transparent text-slate-400 hover:text-slate-200 transition";
            } else {
                document.getElementById('section-orders').classList.add('hidden');
                document.getElementById('section-services').classList.remove('hidden');
                
                document.getElementById('tab-btn-services').className = "flex-1 py-2 rounded-xl text-xs font-bold uppercase tracking-wider bg-purple-600 text-white transition";
                document.getElementById('tab-btn-orders').className = "flex-1 py-2 rounded-xl text-xs font-bold uppercase tracking-wider bg-transparent text-slate-400 hover:text-slate-200 transition";
            }
        }

        // Modals management
        function openAddModal() {
            document.getElementById('modal-add-service').classList.remove('hidden');
        }
        function closeAddModal() {
            document.getElementById('modal-add-service').classList.add('hidden');
            document.getElementById('form-add-service').reset();
        }

        function openEditModal(id) {
            const svc = servicesData.find(s => s.id === id);
            if (!svc) return;

            document.getElementById('edit-svc-id').value = svc.id;
            document.getElementById('edit-svc-id-display').value = svc.id;
            document.getElementById('edit-svc-name').value = svc.name;
            document.getElementById('edit-svc-price').value = svc.price;
            document.getElementById('edit-svc-price-num').value = svc.price_numeric;
            document.getElementById('edit-svc-desc').value = svc.description;
            document.getElementById('edit-svc-active').checked = (svc.is_active === 1);
            
            document.getElementById('modal-edit-service').classList.remove('hidden');
        }
        function closeEditModal() {
            document.getElementById('modal-edit-service').classList.add('hidden');
            document.getElementById('form-edit-service').reset();
        }

        function submitAddService(e) {
            e.preventDefault();
            const id = document.getElementById('add-svc-id').value.trim();
            const name = document.getElementById('add-svc-name').value.trim();
            const price = document.getElementById('add-svc-price').value.trim();
            const price_numeric = parseFloat(document.getElementById('add-svc-price-num').value);
            const description = document.getElementById('add-svc-desc').value.trim();

            fetch('/admin/services/add', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ id, name, price, price_numeric, description })
            })
            .then(res => res.json())
            .then(data => {
                if (data.status === 'success') {
                    alert('Услуга успешно добавлена!');
                    window.location.reload();
                } else {
                    alert('Ошибка: ' + data.message);
                }
            })
            .catch(err => {
                console.error(err);
                alert('Не удалось связаться с сервером');
            });
        }

        function submitEditService(e) {
            e.preventDefault();
            const id = document.getElementById('edit-svc-id').value;
            const name = document.getElementById('edit-svc-name').value.trim();
            const price = document.getElementById('edit-svc-price').value.trim();
            const price_numeric = parseFloat(document.getElementById('edit-svc-price-num').value);
            const description = document.getElementById('edit-svc-desc').value.trim();
            const is_active = document.getElementById('edit-svc-active').checked ? 1 : 0;

            fetch(`/admin/services/edit/${id}`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ name, price, price_numeric, description, is_active })
            })
            .then(res => res.json())
            .then(data => {
                if (data.status === 'success') {
                    alert('Услуга успешно обновлена!');
                    window.location.reload();
                } else {
                    alert('Ошибка: ' + data.message);
                }
            })
            .catch(err => {
                console.error(err);
                alert('Не удалось связаться с сервером');
            });
        }

        function filterStatus(status) {
            currentFilter = status;
            
            // Toggle active styles on tabs
            document.querySelectorAll('.status-tab').forEach(tab => {
                tab.classList.remove('bg-purple-600', 'text-white');
                tab.classList.add('bg-slate-800', 'text-slate-300');
            });
            
            const activeTab = document.getElementById('tab-' + status);
            activeTab.classList.remove('bg-slate-800', 'text-slate-300');
            activeTab.classList.add('bg-purple-600', 'text-white');
            
            applyFilterAndSearch();
        }

        function searchTable() {
            applyFilterAndSearch();
        }

        function applyFilterAndSearch() {
            const query = document.getElementById('search').value.toLowerCase();
            const rows = document.querySelectorAll('.order-row');
            
            rows.forEach(row => {
                const status = row.getAttribute('data-status');
                
                // Get name and other fields text content
                const name = row.querySelector('.font-semibold').innerText.toLowerCase();
                const searchTargets = row.querySelectorAll('.search-target');
                let targetText = name;
                searchTargets.forEach(t => targetText += ' ' + t.innerText.toLowerCase());
                
                const matchesFilter = (currentFilter === 'all') || (status === currentFilter);
                const matchesSearch = targetText.includes(query);
                
                if (matchesFilter && matchesSearch) {
                    row.style.display = '';
                } else {
                    row.style.display = 'none';
                }
            });
        }

        function checkStatus(regId, button) {
            const originalText = button.innerHTML;
            button.disabled = true;
            button.innerHTML = '<span>🔄</span> Проверка...';
            
            fetch(`/admin/check-payment/${regId}`, {
                method: 'POST'
            })
            .then(res => res.json())
            .then(data => {
                if (data.status === 'success') {
                    alert(`Новый статус: ${data.payment_status == 'paid' ? 'ОПЛАЧЕНО!' : 'Ожидает оплаты'}`);
                    if (data.payment_status === 'paid') {
                        window.location.reload();
                    }
                } else {
                    alert('Ошибка: ' + data.message);
                }
            })
            .catch(err => {
                console.error(err);
                alert('Сбой соединения с сервером');
            })
            .finally(() => {
                button.disabled = false;
                button.innerHTML = originalText;
            });
        }
    </script>
</body>
</html>
"""

@app.route('/admin', methods=['GET'])
def admin_dashboard():
    if not session.get('logged_in'):
        # Генерируем state для защиты от CSRF
        state = str(uuid.uuid4())
        session['oauth_state'] = state

        base = config.AUTHENTIK_BASE_URL.rstrip('/')
        params = {
            'client_id': config.AUTHENTIK_CLIENT_ID,
            'redirect_uri': config.AUTHENTIK_REDIRECT_URI,
            'response_type': 'code',
            'scope': 'openid email profile',
            'state': state,
        }
        auth_url = f"{base}/application/o/authorize/?" + "&".join(f"{k}={v}" for k, v in params.items())
        return redirect(auth_url)

    # Загрузить данные
    registrations = db.get_all_web_registrations()
    services = db.get_all_services_list()
    stats = {
        "total": len(registrations),
        "paid_count": sum(1 for r in registrations if r["payment_status"] == "paid"),
        "pending_count": sum(1 for r in registrations if r["payment_status"] != "paid"),
        "total_revenue": sum(r["amount"] for r in registrations if r["payment_status"] == "paid")
    }
    return render_template_string(DASHBOARD_TEMPLATE, registrations=registrations, stats=stats, services=services)


@app.route('/admin/callback', methods=['GET'])
def admin_callback():
    """OIDC callback от Authentik."""
    error = request.args.get('error')
    if error:
        print(f"[OIDC] Ошибка авторизации: {error} — {request.args.get('error_description', '')}")
        base = config.AUTHENTIK_BASE_URL.rstrip('/')
        login_url = f"{base}/application/o/authorize/?client_id={config.AUTHENTIK_CLIENT_ID}&redirect_uri={config.AUTHENTIK_REDIRECT_URI}&response_type=code&scope=openid+email+profile"
        return render_template_string(ACCESS_DENIED_TEMPLATE,
                                      error=f"Ошибка от Authentik: {error}",
                                      login_url=login_url), 403

    # Проверка state против CSRF
    state = request.args.get('state')
    if not state or state != session.get('oauth_state'):
        print("[OIDC] Неверный state — возможная CSRF-атака")
        return "403 Invalid state", 403
    session.pop('oauth_state', None)

    code = request.args.get('code')
    if not code:
        return "403 No code returned", 403

    # Обмен кода на токен
    base = config.AUTHENTIK_BASE_URL.rstrip('/')
    token_url = f"{base}/application/o/token/"
    try:
        token_resp = requests.post(token_url, data={
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': config.AUTHENTIK_REDIRECT_URI,
            'client_id': config.AUTHENTIK_CLIENT_ID,
            'client_secret': config.AUTHENTIK_CLIENT_SECRET,
        }, timeout=15)
        token_data = token_resp.json()
    except Exception as e:
        print(f"[OIDC] Ошибка получения токена: {e}")
        return "500 Token exchange failed", 500

    if 'error' in token_data:
        print(f"[OIDC] Ошибка токена: {token_data}")
        return f"403 {token_data.get('error_description', token_data['error'])}", 403

    access_token = token_data.get('access_token')

    # Получаем данные пользователя
    try:
        userinfo_resp = requests.get(f"{base}/application/o/userinfo/",
                                     headers={'Authorization': f'Bearer {access_token}'},
                                     timeout=10)
        userinfo = userinfo_resp.json()
    except Exception as e:
        print(f"[OIDC] Ошибка получения userinfo: {e}")
        return "500 Userinfo request failed", 500

    print(f"[OIDC] Успешный вход: {userinfo.get('email') or userinfo.get('preferred_username', '?')}")
    session['logged_in'] = True
    session['user_email'] = userinfo.get('email', '')
    session['user_name'] = userinfo.get('name') or userinfo.get('preferred_username', '')
    return redirect(url_for('admin_dashboard'))


@app.route('/admin/login', methods=['POST', 'GET'])
def admin_login():
    """Legacy-маршрут — перенаправляет на OIDC."""
    return redirect(url_for('admin_dashboard'))


@app.route('/admin/logout', methods=['GET'])
def admin_logout():
    session.clear()
    # Выход также из Authentik
    base = config.AUTHENTIK_BASE_URL.rstrip('/')
    if base:
        return redirect(f"{base}/application/o/ikp-admin/end-session/")
    return redirect(url_for('admin_dashboard'))

@app.route('/admin/check-payment/<reg_id>', methods=['POST'])
def admin_check_payment(reg_id):
    if not session.get('logged_in'):
        return jsonify({"status": "error", "message": "Не авторизован"}), 403

    try:
        reg = db.get_web_registration(reg_id)
        if not reg:
            return jsonify({"status": "error", "message": "Заявка не найдена"}), 404

        payment_id = reg.get("yookassa_payment_id")
        if not payment_id:
            return jsonify({"status": "error", "message": "У этой заявки нет ID платежа ЮKassa"}), 400

        yoo_status = check_yookassa_payment_status(payment_id)
        if not yoo_status:
            return jsonify({"status": "error", "message": "Не удалось связаться с ЮKassa API"}), 500

        # Update if paid
        if yoo_status == "succeeded" and reg.get("payment_status") != "paid":
            paid_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            db.update_web_payment_status(reg_id, "paid", payment_id, paid_at)
            update_excel_payment_status(reg_id, "Оплачено", paid_at)

            # Send paid notifications
            notify_data = {
                "name": reg.get("name"),
                "phone": reg.get("phone"),
                "email": reg.get("email"),
                "vk": reg.get("vk_link"),
                "agreeOferta": reg.get("agree_oferta"),
                "agreePolicy": reg.get("agree_policy"),
                "agreeNewsletter": reg.get("agree_newsletter"),
                "serviceName": reg.get("service_name"),
                "servicePrice": reg.get("amount")
            }
            send_vk_operator_notification(reg_id, notify_data, paid=True)
            send_email_notification(reg_id, notify_data, paid=True)
            
            return jsonify({"status": "success", "payment_status": "paid"})
            
        return jsonify({"status": "success", "payment_status": reg.get("payment_status")})

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

def run_server(port=8000):
    init_excel()
    print(f"\n=======================================================")
    print(f"Flask-сервер ИКП запущен на http://localhost:{port}/")
    print(f"Главная страница: http://localhost:{port}/")
    print(f"Форма регистрации: http://localhost:{port}/form/index.html")
    print(f"Панель администратора: http://localhost:{port}/admin")
    print(f"Данные пишутся в SQLite и Excel: {FILE_NAME}")
    print(f"Нажмите Ctrl+C для остановки сервера.")
    print(f"=======================================================\n")
    app.run(host='0.0.0.0', port=port, debug=True)

if __name__ == '__main__':
    run_server()
