from __future__ import annotations

from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message

from app import runtime
from app.db import get_session
from app.keyboards import review_rating_kb
from app.models import Purchase, Review
from app.states import ReviewStates

router = Router()


@router.callback_query(F.data == "rev:cancel")
async def review_cancel(callback: CallbackQuery, state: FSMContext) -> None:
    await state.clear()
    try:
        await callback.message.edit_reply_markup(reply_markup=None)
    except Exception:
        pass
    await callback.answer("Cancelled")


@router.callback_query(F.data.startswith("rev:"))
async def review_start(callback: CallbackQuery) -> None:
    purchase_id = int(callback.data.split(":")[1])
    async with get_session() as session:
        purchase = await session.get(Purchase, purchase_id)
        if purchase is None or purchase.user_id != callback.from_user.id:
            await callback.answer("Purchase not found", show_alert=True)
            return
        if purchase.reviewed:
            await callback.answer("You already reviewed this purchase", show_alert=True)
            return
    await callback.message.answer(
        "⭐ <b>Rate the item</b> — how many stars?",
        reply_markup=review_rating_kb(purchase_id),
    )
    await callback.answer()


@router.callback_query(F.data.startswith("rate:"))
async def review_rate(callback: CallbackQuery, state: FSMContext) -> None:
    _, pid_raw, n_raw = callback.data.split(":")
    purchase_id, rating = int(pid_raw), int(n_raw)
    async with get_session() as session:
        purchase = await session.get(Purchase, purchase_id)
        if purchase is None or purchase.user_id != callback.from_user.id:
            await callback.answer("Purchase not found", show_alert=True)
            return
        if purchase.reviewed:
            await callback.answer("Already reviewed", show_alert=True)
            return
    await state.set_state(ReviewStates.text)
    await state.update_data(purchase_id=purchase_id, rating=rating)
    await callback.message.edit_text(
        f"⭐ Rating: {'★' * rating}{'☆' * (5 - rating)}\n\n"
        "Now write your review text (or send “-” to skip):"
    )
    await callback.answer()


@router.message(ReviewStates.text)
async def review_text(message: Message, state: FSMContext) -> None:
    data = await state.get_data()
    await state.clear()
    purchase_id = int(data.get("purchase_id", 0))
    rating = int(data.get("rating", 0))
    if purchase_id <= 0 or not 1 <= rating <= 5:
        await message.answer("Session expired, start again.")
        return
    text = (message.text or "").strip()
    if text == "-":
        text = ""

    async with get_session() as session:
        purchase = await session.get(Purchase, purchase_id)
        if purchase is None or purchase.user_id != message.from_user.id:
            await message.answer("Purchase not found.")
            return
        if purchase.reviewed:
            await message.answer("You already reviewed this purchase.")
            return
        purchase.reviewed = True
        item_name = purchase.item_name
        session.add(
            Review(
                purchase_id=purchase_id,
                user_id=message.from_user.id,
                item_id=purchase.item_id,
                item_name=item_name,
                rating=rating,
                text=text[:1000],
            )
        )
        await session.commit()
    await message.answer(
        f"✅ Thanks for your review! {'★' * rating}{'☆' * (5 - rating)}"
    )
    await _post_to_group(message, item_name, rating, text)


async def _post_to_group(message: Message, item_name: str, rating: int, text: str) -> None:
    """Publish the fresh review to the configured reviews group, if any."""
    group = runtime.get(runtime.REVIEWS_GROUP)
    if not group:
        return
    handle = f"@{message.from_user.username}" if message.from_user.username else "user"
    who = f"{handle} · id{message.from_user.id}"
    stars = "★" * rating + "☆" * (5 - rating)
    body = f"\n\n<i>{text}</i>" if text else ""
    try:
        await message.bot.send_message(
            group,
            f"⭐ <b>New review</b> — {item_name}\n{stars} · {who}{body}",
        )
    except Exception:
        pass
