"""Admin panel handlers."""

from aiogram import Router, F
from aiogram.types import CallbackQuery, Message, FSInputFile
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from datetime import datetime
import tempfile
from utils.helpers import gregorian_to_persian, persian_to_gregorian
import os
import aiosqlite

from config import settings
from states.prediction import PredictionAdminState
from states.admin import AdminState
from keyboards.admin import (
    get_admin_main_menu,
    get_matches_management_keyboard,
    get_record_result_keyboard,
    get_broadcast_type_keyboard,
    get_admin_back_keyboard,
)
from database import (
    get_all_matches,
    get_top_users,
    create_match,
    update_match_result,
    delete_match,
    get_all_users,
    get_user_count,
    get_user_count_by_role,
    get_prediction_count_for_user,
    get_referral_count_for_user,
    search_user,
    get_match,
    get_predictions_for_match,
    DB_PATH,
    update_user_score,
)
from services.scoring import calculate_prediction_score, calculate_result_prediction_score
import aiosqlite


router = Router()


def is_admin(user_id: int) -> bool:
    """Check if user is admin."""
    return user_id in settings.get_admin_ids()


@router.message(Command("admin"), F.from_user.func(lambda u: is_admin(u.id)))
async def admin_command(message: Message, state: FSMContext):
    """Handle /admin command to open admin panel."""
    await state.clear()
    await message.answer(
        "⚙️ پنل مدیریت",
        reply_markup=get_admin_main_menu()
    )


@router.callback_query(F.data == "admin_panel", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_panel(callback: CallbackQuery, state: FSMContext):
    """Show admin panel main menu."""
    await state.clear()
    await callback.message.edit_text(
        "⚙️ پنل مدیریت",
        reply_markup=get_admin_main_menu()
    )
    await callback.answer()


@router.callback_query(F.data == "admin_add_match", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_add_match(callback: CallbackQuery, state: FSMContext):
    """Start adding a new match - ask for team1."""
    await state.set_state(PredictionAdminState.waiting_for_team1)
    await callback.message.edit_text(
        "🏆 نام تیم اول را وارد کنید:",
        reply_markup=get_admin_back_keyboard()
    )
    await callback.answer()


@router.message(PredictionAdminState.waiting_for_team1, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_team1(message: Message, state: FSMContext):
    """Process team1 name."""
    if not message.text:
        return

    await state.update_data(team1=message.text.strip())
    await state.set_state(PredictionAdminState.waiting_for_team2)
    await message.answer("🏆 نام تیم دوم را وارد کنید:")


@router.message(PredictionAdminState.waiting_for_team2, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_team2(message: Message, state: FSMContext):
    """Process team2 name."""
    if not message.text:
        return

    await state.update_data(team2=message.text.strip())
    await state.set_state(PredictionAdminState.waiting_for_team1_flag)
    await message.answer("🏳️ پرچم تیم اول (مثلاً 🇮🇷) را وارد کنید:")


@router.message(PredictionAdminState.waiting_for_team1_flag, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_team1_flag(message: Message, state: FSMContext):
    """Process team1 flag."""
    if not message.text:
        return

    await state.update_data(team1_flag=message.text.strip())
    await state.set_state(PredictionAdminState.waiting_for_team2_flag)
    await message.answer("🏳️ پرچم تیم دوم (مثلاً 🇳🇿) را وارد کنید:")


@router.message(PredictionAdminState.waiting_for_team2_flag, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_team2_flag(message: Message, state: FSMContext):
    """Process team2 flag."""
    if not message.text:
        return

    await state.update_data(team2_flag=message.text.strip())
    await state.set_state(PredictionAdminState.waiting_for_match_time)

    now_gregorian = datetime.now().strftime('%Y-%m-%d %H:%M')

    await message.answer(
        f"📅 زمان مسابقه را به فرمت شمسی یا میلادی وارد کنید:\n\n"
        f"شمسی (مثال): 1404-03-24 20:50\n"
        f"میلادی (مثال): {now_gregorian}"
    )


@router.message(PredictionAdminState.waiting_for_match_time, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_match_time(message: Message, state: FSMContext):
    """Process match time and create the match."""
    if not message.text:
        return

    input_text = message.text.strip()
    match_time = None

    try:
        match_time = datetime.strptime(input_text, "%Y-%m-%d %H:%M")
    except ValueError:
        try:
            match_time = persian_to_gregorian(input_text)
        except ValueError:
            await message.answer(
                "❌ فرمت تاریخ نامعتبر است.\n"
                "لطفاً از فرمت‌های زیر استفاده کنید:\n"
                "• شمسی: 1404/03/24 20:50\n"
                "• میلادی: 2025-06-14 20:50"
            )
            return

    data = await state.get_data()
    await create_match(
        team1=data["team1"],
        team2=data["team2"],
        team1_flag=data["team1_flag"],
        team2_flag=data["team2_flag"],
        match_time=match_time
    )
    await state.clear()
    await message.answer("✅ مسابقه با موفقیت ذخیره شد.")


@router.callback_query(F.data == "admin_manage_matches", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_manage_matches(callback: CallbackQuery):
    """Show matches management page."""
    matches = await get_all_matches()
    await callback.message.edit_text(
        "⚽ مدیریت مسابقات",
        reply_markup=get_matches_management_keyboard(matches)
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_delete_match_"), F.from_user.func(lambda u: is_admin(u.id)))
async def admin_delete_match(callback: CallbackQuery, state: FSMContext):
    """Delete a match."""
    match_id = int(callback.data.split("_")[-1])
    await delete_match(match_id)
    await callback.answer("✅ مسابقه حذف شد.", show_alert=True)

    matches = await get_all_matches()
    await callback.message.edit_text(
        "⚽ مدیریت مسابقات",
        reply_markup=get_matches_management_keyboard(matches)
    )


@router.callback_query(F.data == "admin_record_result", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_record_result(callback: CallbackQuery):
    """Start recording match result."""
    matches = await get_all_matches()
    upcoming_matches = [m for m in matches if m.get("status") == "upcoming"]

    if not upcoming_matches:
        await callback.answer("❌ مسابقه‌ای برای ثبت نتیجه وجود ندارد.", show_alert=True)
        return

    await callback.message.edit_text(
        "🏁 ثبت نتیجه مسابقه",
        reply_markup=get_record_result_keyboard(upcoming_matches)
    )
    await callback.answer()


@router.callback_query(F.data.startswith("record_result_"), F.from_user.func(lambda u: is_admin(u.id)))
async def admin_select_match_for_result(callback: CallbackQuery, state: FSMContext):
    """Select match for result recording."""
    match_id = int(callback.data.split("_")[-1])
    await state.set_state(PredictionAdminState.waiting_for_result_team1)
    await state.update_data(match_id=match_id)

    match = await get_match(match_id)
    await callback.message.edit_text(
        f"🏁 ثبت نتیجه مسابقه\n{match['team1_flag']} {match['team1']} vs {match['team2_flag']} {match['team2']}",
        reply_markup=get_admin_back_keyboard()
    )
    await callback.message.answer(f"گل {match['team1']} را وارد کنید:")


@router.message(PredictionAdminState.waiting_for_result_team1, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_result_team1(message: Message, state: FSMContext):
    """Process team1 result score."""
    try:
        score = int(message.text)
        if score < 0:
            raise ValueError()
    except (ValueError, TypeError):
        await message.answer("❌ لطفاً عددی معتبر وارد کنید.")
        return

    await state.update_data(team1_score=score)
    await state.set_state(PredictionAdminState.waiting_for_result_team2)

    data = await state.get_data()
    match = await get_match(data["match_id"])
    await message.answer(f"گل {match['team2']} را وارد کنید:")


@router.message(PredictionAdminState.waiting_for_result_team2, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_result_team2(message: Message, state: FSMContext):
    """Process team2 result score and save."""
    try:
        score = int(message.text)
        if score < 0:
            raise ValueError()
    except (ValueError, TypeError):
        await message.answer("❌ لطفاً عددی معتبر وارد کنید.")
        return

    data = await state.get_data()
    match_id = data["match_id"]
    team1_score = data["team1_score"]
    team2_score = score

    await update_match_result(match_id, team1_score, team2_score)

    predictions = await get_predictions_for_match(match_id)

    for pred in predictions:
        if pred.get("predict_result"):
            earned = await calculate_result_prediction_score(
                pred["user_id"],
                match_id,
                team1_score,
                team2_score
            )
            await update_user_score(pred["user_id"], earned)
        else:
            await calculate_prediction_score(
                pred["user_id"],
                match_id,
                team1_score,
                team2_score
            )

    await state.clear()
    await message.answer("✅ نتیجه مسابقه ثبت شد و امتیازات محاسبه شدند.")


@router.callback_query(F.data == "admin_users", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_users(callback: CallbackQuery):
    """Show user statistics."""
    total_users = await get_user_count()
    students = await get_user_count_by_role("دانشجو")
    dentists = await get_user_count_by_role("دندانپزشک")

    async with aiosqlite.connect(DB_PATH) as db:
        pred_cursor = await db.execute("SELECT COUNT(*) FROM predictions")
        pred_count = (await pred_cursor.fetchone())[0]

        ref_cursor = await db.execute("SELECT COUNT(*) FROM referrals")
        ref_count = (await ref_cursor.fetchone())[0]

    stats_text = f"""
👥 آمار کاربران

👤 تعداد کل کاربران: {total_users}
👨‍⚕️ تعداد دندانپزشکان: {dentists}
👨‍🎓 تعداد دانشجویان: {students}
⚽ تعداد پیش بینی ها: {pred_count}
🎁 تعداد دعوت های موفق: {ref_count}
"""

    await callback.message.edit_text(stats_text, reply_markup=get_admin_back_keyboard())
    await callback.answer()


@router.callback_query(F.data == "admin_stats", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_stats(callback: CallbackQuery, state: FSMContext):
    """Show detailed statistics."""
    top_users = await get_top_users(limit=50) 

    top_text = "🏆 رنکینگ رده بندی:\n"
    rank = 1
    for user in top_users:
        top_text += f"{rank}. {user['full_name']} - {user['score']} امتیاز\n"
        rank += 1

    async with aiosqlite.connect(DB_PATH) as db:
        cursor = await db.execute("SELECT COUNT(*) FROM matches WHERE status = 'finished'")
        finished_count = (await cursor.fetchone())[0]

        cursor = await db.execute("SELECT COUNT(*) FROM matches WHERE status = 'upcoming'")
        upcoming_count = (await cursor.fetchone())[0]

    stats_text = f"""
📊 آمار

{top_text}
"""

    await callback.message.edit_text(stats_text, reply_markup=get_admin_back_keyboard())
    await callback.answer()


@router.callback_query(F.data == "admin_broadcast", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_broadcast(callback: CallbackQuery, state: FSMContext):
    """Start broadcast process."""
    await state.set_state(PredictionAdminState.waiting_for_broadcast_content)
    await state.update_data(broadcast_type=None)

    await callback.message.edit_text(
        "📢 ارسال پیام همگانی\n\nنوع پیام را انتخاب کنید:",
        reply_markup=get_broadcast_type_keyboard()
    )
    await callback.answer()


@router.callback_query(F.data.startswith("broadcast_"), F.from_user.func(lambda u: is_admin(u.id)))
async def admin_select_broadcast_type(callback: CallbackQuery, state: FSMContext):
    """Select broadcast type and prompt for content."""
    broadcast_type = callback.data.split("_")[-1]
    await state.update_data(broadcast_type=broadcast_type)

    if broadcast_type == "text":
        await state.set_state(PredictionAdminState.waiting_for_broadcast_content)
        await callback.message.edit_text(
            "📝 متن پیام همگانی را وارد کنید:",
            reply_markup=get_admin_back_keyboard()
        )
    elif broadcast_type in ["photo", "video", "file"]:
        await state.set_state(PredictionAdminState.waiting_for_broadcast_content)
        type_name = {"photo": "عکس", "video": "ویدیو", "file": "فایل"}[broadcast_type]
        await callback.message.edit_text(
            f"{type_name} را ارسال کنید:",
            reply_markup=get_admin_back_keyboard()
        )


@router.message(PredictionAdminState.waiting_for_broadcast_content, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_broadcast(message: Message, state: FSMContext):
    """Process and send broadcast message."""
    data = await state.get_data()
    broadcast_type = data.get("broadcast_type")

    users = await get_all_users()
    success_count = 0
    fail_count = 0

    for user in users:
        try:
            if broadcast_type == "text":
                await message.bot.send_message(user["telegram_id"], message.text)
            elif broadcast_type == "photo":
                await message.bot.send_photo(
                    user["telegram_id"],
                    photo=message.photo[-1].file_id,
                    caption=message.caption or ""
                )
            elif broadcast_type == "video":
                await message.bot.send_video(
                    user["telegram_id"],
                    video=message.video.file_id,
                    caption=message.caption or ""
                )
            elif broadcast_type == "file":
                await message.bot.send_document(
                    user["telegram_id"],
                    document=message.document.file_id,
                    caption=message.caption or ""
                )
            success_count += 1
        except Exception:
            fail_count += 1

    await state.clear()
    await message.answer(
        f"✅ ارسال پیام همگانی تکمیل شد.\n\n"
        f"موفق: {success_count}\n"
        f"ناموفق: {fail_count}"
    )


@router.callback_query(F.data == "admin_export_excel", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_export_excel(callback: CallbackQuery, state: FSMContext):
    """Export users to Excel file."""
    from datetime import datetime as dt

    users = await get_all_users()

    csv_lines = ["نام و نام خانوادگی,شماره تماس,نوع کاربر,امتیاز,تعداد پیش بینی,تعداد دعوت,تاریخ ثبت نام"]

    for user in users:
        prediction_count = await get_prediction_count_for_user(user["id"])
        referral_count = await get_referral_count_for_user(user["id"])
        registered_at = user.get("registered_at", "")

        csv_lines.append(
            f"{user['full_name']},{user['phone']},{user['role']},"
            f"{user['score']},{prediction_count},{referral_count},{registered_at}"
        )

    csv_content = "\n".join(csv_lines)

    with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False, encoding="utf-8-sig") as f:
        f.write(csv_content)
        temp_path = f.name

    try:
        await callback.message.answer_document(
            FSInputFile(temp_path, filename=f"users_export_{dt.now().strftime('%Y%m%d_%H%M%S')}.csv")
        )
    finally:
        os.unlink(temp_path)

    await callback.answer()


@router.callback_query(F.data == "admin_search_user", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_search_user_prompt(callback: CallbackQuery, state: FSMContext):
    """Prompt for user search."""
    await state.set_state(AdminState.searching_user)
    await callback.message.edit_text(
        "🔎 جستجوی کاربر\n\nشناسه تلگرام، شماره تماس یا نام کاربر را وارد کنید:",
        reply_markup=get_admin_back_keyboard()
    )
    await callback.answer()


@router.message(AdminState.searching_user, F.from_user.func(lambda u: is_admin(u.id)))
async def admin_process_user_search(message: Message, state: FSMContext):
    """Process user search query."""
    if not message.text:
        return

    user = await search_user(message.text.strip())

    if not user:
        await message.answer("❌ کاربری یافت نشد.", reply_markup=get_admin_back_keyboard())
        return

    prediction_count = await get_prediction_count_for_user(user["id"])
    referral_count = await get_referral_count_for_user(user["id"])

    user_info = f"""
🔎 اطلاعات کاربر

🆔 شناسه تلگرام: {user['telegram_id']}
👤 نام: {user['full_name']}
📱 شماره تماس: {user['phone']}
🔰 نقش: {user['role']}
💎 امتیاز: {user['score']}
⚽ تعداد پیش بینی: {prediction_count}
👥 تعداد دعوت: {referral_count}
📅 تاریخ ثبت نام: {user.get('registered_at', '')}
"""

    await message.answer(user_info, reply_markup=get_admin_back_keyboard())


@router.callback_query(F.data == "admin_back", F.from_user.func(lambda u: is_admin(u.id)))
async def admin_go_back(callback: CallbackQuery, state: FSMContext):
    """Go back to admin main menu."""
    await state.clear()
    await callback.message.edit_text(
        "⚙️ پنل مدیریت",
        reply_markup=get_admin_main_menu()
    )
    await callback.answer()