"""
Telegram Bot webhook handler.

Setup (run once after deploy):
  curl "https://api.telegram.org/bot{TOKEN}/setWebhook?url=https://jarvis.goteku.com/api/v1/telegram/webhook"
"""
import re
from datetime import datetime
from fastapi import APIRouter, Request
from sqlalchemy import select
from app.database import AsyncSessionLocal
from app.models.surat import Surat
from app.models.document import Document, BorrowRequest, BorrowRequestItem
from app.models.user import User
from app.services.telegram import send_telegram
from app.services.notifier import notify_user_group, notify_user_by_id

router = APIRouter(prefix="/telegram", tags=["telegram"])


@router.post("/webhook")
async def telegram_webhook(request: Request):
    try:
        data = await request.json()
        message = data.get("message") or data.get("edited_message")
        if not message:
            return {"ok": True}

        chat_id    = str(message.get("chat", {}).get("id", ""))
        from_id    = str(message.get("from", {}).get("id", ""))
        text       = (message.get("text") or "").strip()
        first_name = message.get("from", {}).get("first_name", "")

        # ── /start ───────────────────────────────────────────────────────────
        if text.startswith("/start"):
            await send_telegram(chat_id, (
                f"Halo {first_name}! 👋\n\n"
                f"Ini adalah bot notifikasi *Jarvis*.\n\n"
                f"Chat ID kamu:\n`{chat_id}`"
            ))
            return {"ok": True}

        reply_to = message.get("reply_to_message")
        if not reply_to:
            return {"ok": True}

        reply_text    = reply_to.get("text", "")
        reply_caption = reply_to.get("caption", "")

        # ── Borrow Request: APPROVE / TOLAK ──────────────────────────────────
        match_req = re.search(r"#BORROW-REQ-(\d+)", reply_text)
        if match_req:
            req_id = int(match_req.group(1))
            cmd = text.strip().lower()
            async with AsyncSessionLocal() as db:
                req = await db.get(BorrowRequest, req_id)
                if not req:
                    await send_telegram(chat_id, f"❌ Permintaan #{req_id} tidak ditemukan.")
                    return {"ok": True}

                items_res = await db.execute(
                    select(BorrowRequestItem).where(BorrowRequestItem.borrow_request_id == req_id)
                )
                items = items_res.scalars().all()

                # Verify sender is custodian of these docs
                custodian_ids = set()
                for item in items:
                    doc = await db.get(Document, item.document_id)
                    if doc and doc.custodian_id:
                        custodian_ids.add(doc.custodian_id)

                sender_res = await db.execute(select(User).where(User.telegram_chat_id == from_id))
                sender = sender_res.scalar_one_or_none()
                if not sender or sender.id not in custodian_ids:
                    await send_telegram(chat_id, "❌ Hanya custodian dokumen yang bisa menyetujui permintaan ini.")
                    return {"ok": True}

                if cmd == "approve":
                    if req.status != "pending":
                        await send_telegram(chat_id, f"❌ Permintaan #{req_id} sudah dalam status '{req.status}'.")
                        return {"ok": True}
                    req.status = "active"
                    req.approved_by = sender.id
                    req.approved_at = datetime.utcnow()
                    for item in items:
                        item.status = "approved"
                        doc = await db.get(Document, item.document_id)
                        if doc:
                            doc.status = "borrowed"
                            doc.updated_at = datetime.utcnow()
                            if doc.location == "bank":
                                await send_telegram(chat_id, (
                                    f"✅ Permintaan #{req_id} disetujui.\n\n"
                                    f"Dokumen: *{doc.name}*\n"
                                    f"📍 Lokasi: Bank — silakan ambil terlebih dahulu.\n\n"
                                    f"Sudah diambil dari bank? Reply: `AMBIL` #BORROW-ITEM-{item.id}"
                                ))
                            else:
                                await send_telegram(chat_id, (
                                    f"✅ Permintaan #{req_id} disetujui.\n\n"
                                    f"Dokumen: *{doc.name}* siap diserahkan.\n\n"
                                    f"Sudah diserahkan ke peminjam? Reply: `SERAH` #BORROW-ITEM-{item.id}"
                                ))
                    await db.commit()
                    await notify_user_by_id(db, req.requester_id, "Permintaan pinjam disetujui", f"Permintaan #{req_id} disetujui.", "/documents/requests")
                    await db.commit()

                elif cmd.startswith("tolak"):
                    reason = text[5:].strip() or "Tidak ada alasan"
                    req.status = "rejected"
                    req.rejection_reason = reason
                    for item in items:
                        item.status = "rejected"
                    await db.commit()
                    await send_telegram(chat_id, f"❌ Permintaan #{req_id} ditolak.\nAlasan: {reason}")
                    await notify_user_by_id(db, req.requester_id, "Permintaan pinjam ditolak", f"Permintaan #{req_id} ditolak. Alasan: {reason}", "/documents/requests")
                    await db.commit()

                else:
                    await send_telegram(chat_id, "Perintah tidak dikenal.\nGunakan: `APPROVE` atau `TOLAK [alasan]`")
            return {"ok": True}

        # ── Borrow Item: AMBIL / SERAH / TERIMA ──────────────────────────────
        match_item = re.search(r"#BORROW-ITEM-(\d+)", reply_text)
        if match_item:
            item_id = int(match_item.group(1))
            cmd = text.strip().lower()
            async with AsyncSessionLocal() as db:
                item = await db.get(BorrowRequestItem, item_id)
                if not item:
                    await send_telegram(chat_id, f"❌ Item #{item_id} tidak ditemukan.")
                    return {"ok": True}
                doc = await db.get(Document, item.document_id)
                if not doc:
                    return {"ok": True}

                sender_res = await db.execute(select(User).where(User.telegram_chat_id == from_id))
                sender = sender_res.scalar_one_or_none()
                if not sender or doc.custodian_id != sender.id:
                    await send_telegram(chat_id, "❌ Hanya custodian dokumen yang bisa melakukan aksi ini.")
                    return {"ok": True}

                if cmd == "ambil" and item.status == "approved" and doc.location == "bank":
                    item.status = "retrieved"
                    item.retrieved_at = datetime.utcnow()
                    doc.location = "home"
                    doc.updated_at = datetime.utcnow()
                    await db.commit()
                    await send_telegram(chat_id, (
                        f"✅ *{doc.name}* sudah diambil dari bank.\n\n"
                        f"Sudah diserahkan ke peminjam? Reply: `SERAH` #BORROW-ITEM-{item.id}"
                    ))

                elif cmd == "serah" and item.status in ("approved", "retrieved"):
                    item.status = "with_borrower"
                    item.handed_over_at = datetime.utcnow()
                    doc.location = "with_borrower"
                    doc.updated_at = datetime.utcnow()
                    await db.commit()
                    req = await db.get(BorrowRequest, item.borrow_request_id)
                    if req:
                        await notify_user_by_id(db, req.requester_id, "Dokumen diserahkan", f"'{doc.name}' sudah diserahkan.", "/documents/requests")
                        await db.commit()
                    await send_telegram(chat_id, f"✅ *{doc.name}* diserahkan ke peminjam.")

                elif cmd == "terima" and item.status == "return_pending":
                    item.status = "returned"
                    item.returned_at = datetime.utcnow()
                    doc.location = "home"
                    doc.updated_at = datetime.utcnow()
                    await db.commit()
                    await send_telegram(chat_id, (
                        f"✅ *{doc.name}* diterima.\n\n"
                        f"Kembalikan ke bank? Reply: `BANK` atau `SIMPAN` #BORROW-DOC-{doc.id}"
                    ))
                    # Check if all items returned → complete request
                    all_items_res = await db.execute(
                        select(BorrowRequestItem).where(BorrowRequestItem.borrow_request_id == item.borrow_request_id)
                    )
                    all_items = all_items_res.scalars().all()
                    if all(i.status == "returned" for i in all_items):
                        req = await db.get(BorrowRequest, item.borrow_request_id)
                        if req:
                            req.status = "completed"
                            req.completed_at = datetime.utcnow()
                        for i in all_items:
                            d = await db.get(Document, i.document_id)
                            if d:
                                d.status = "available"
                                d.updated_at = datetime.utcnow()
                    await db.commit()

                else:
                    await send_telegram(chat_id, f"Perintah tidak sesuai status item saat ini ('{item.status}').")
            return {"ok": True}

        # ── Document return-to-bank: BANK / SIMPAN ───────────────────────────
        match_doc = re.search(r"#BORROW-DOC-(\d+)", reply_text)
        if match_doc:
            doc_id = int(match_doc.group(1))
            cmd = text.strip().lower()
            async with AsyncSessionLocal() as db:
                doc = await db.get(Document, doc_id)
                if not doc:
                    await send_telegram(chat_id, f"❌ Dokumen #{doc_id} tidak ditemukan.")
                    return {"ok": True}
                sender_res = await db.execute(select(User).where(User.telegram_chat_id == from_id))
                sender = sender_res.scalar_one_or_none()
                if not sender or doc.custodian_id != sender.id:
                    await send_telegram(chat_id, "❌ Hanya custodian yang bisa melakukan aksi ini.")
                    return {"ok": True}
                if cmd == "bank":
                    doc.location = "bank"
                    doc.updated_at = datetime.utcnow()
                    await db.commit()
                    await send_telegram(chat_id, f"✅ *{doc.name}* dicatat sudah dikembalikan ke bank.")
                elif cmd == "simpan":
                    await send_telegram(chat_id, f"✅ *{doc.name}* disimpan di rumah.")
                else:
                    await send_telegram(chat_id, "Reply: `BANK` atau `SIMPAN`")
            return {"ok": True}

        # ── Surat approve/reject (existing) ──────────────────────────────────
        caption = reply_caption
        match = re.search(r"Surat ID: #(\d+)", caption)
        if not match:
            return {"ok": True}

        surat_id = int(match.group(1))
        cmd = text.lower()

        async with AsyncSessionLocal() as db:
            surat = await db.get(Surat, surat_id)
            if not surat:
                await send_telegram(chat_id, f"❌ Surat #{surat_id} tidak ditemukan.")
                return {"ok": True}

            if cmd == "approve":
                surat.is_approved     = True
                surat.approved_at     = datetime.utcnow()
                surat.rejected_reason = None
                await db.commit()
                await send_telegram(chat_id, f"✅ Surat *{surat.no_surat}* telah disetujui.")
                await notify_user_group(db, f"Surat disetujui: {surat.no_surat}", surat.subject or "", f"/letters/{surat_id}")
                if surat.created_by:
                    await notify_user_by_id(db, surat.created_by, f"Surat disetujui: {surat.no_surat}", "Surat kamu telah disetujui.", f"/letters/{surat_id}")
                await db.commit()

            elif cmd.startswith("reject"):
                reason = text[6:].strip() or "Tidak ada alasan diberikan"
                surat.is_approved     = False
                surat.approved_at     = None
                surat.rejected_reason = reason
                await db.commit()
                await send_telegram(chat_id, f"❌ Surat *{surat.no_surat}* ditolak.\nAlasan: {reason}")
                await notify_user_group(db, f"Surat ditolak: {surat.no_surat}", f"Alasan: {reason}", f"/letters/{surat_id}")
                if surat.created_by:
                    await notify_user_by_id(db, surat.created_by, f"Surat ditolak: {surat.no_surat}", f"Alasan: {reason}", f"/letters/{surat_id}")
                await db.commit()

            else:
                await send_telegram(chat_id, (
                    "Perintah tidak dikenal.\n"
                    "Gunakan: `approve` atau `reject [alasan]`"
                ))

    except Exception as e:
        print(f"[telegram webhook] error: {e}")

    return {"ok": True}
