import logging
import csv
import html
from datetime import datetime, timedelta
from io import StringIO

from services.transaction_service import (
    get_all_transactions,
    get_transaction_stats,
    get_transaction_stats_by_period,
    get_transactions_by_period,
    get_user_transaction_stats_for_admin,
    get_user_transactions_for_admin,
)

log = logging.getLogger("bot.admin_transaction_report")


STATUS_LABELS = {
    "approved": "Disetujui",
    "rejected": "Ditolak",
    "pending": "Tertunda",
}


def _format_rupiah(value):
    try:
        return f"Rp {int(value):,}".replace(",", ".")
    except (TypeError, ValueError):
        return "Rp 0"


def _status_emoji(status):
    return "✅" if status == "approved" else "❌" if status == "rejected" else "⏳"


def _stats_lines(stats):
    return (
        f"Order approved: <b>{stats['approved_count']}</b>\n"
        f"Revenue: <b>{_format_rupiah(stats['total_revenue'])}</b>\n"
        f"Rejected: <b>{stats['rejected_count']}</b>\n"
        f"Pending: <b>{stats['pending_count']}</b>\n"
        f"Total transaksi: <b>{stats['total_transactions']}</b>"
    )


def _format_transaction_rows(transactions, show_user=True):
    if not transactions:
        return "📭 Belum ada transaksi."

    lines = []
    for idx, tx in enumerate(transactions, 1):
        status = tx.get("status") or "-"
        status_text = STATUS_LABELS.get(status, status)
        promo_text = f"\n🎟️ Promo: <code>{html.escape(str(tx.get('promo_used')))}</code>" if tx.get("promo_used") else ""
        code_text = f"\n🆔 Kode: <code>{html.escape(str(tx.get('transaction_code')))}</code>" if tx.get("transaction_code") else ""
        user_text = f"\n👤 User ID: <code>{html.escape(str(tx.get('user_id') or '-'))}</code>" if show_user else ""
        lines.append(
            f"{idx}. {_status_emoji(status)} <b>{html.escape(str(tx.get('package_label') or '-'))}</b>"
            f"{user_text}\n"
            f"💰 {_format_rupiah(tx.get('harga_bayar'))}{promo_text}{code_text}\n"
            f"🏷️ {html.escape(str(status_text))}\n"
            f"📅 {html.escape(str(tx.get('created_at') or '-'))}"
        )

    return "\n\n".join(lines)


def get_report_period_bounds(period):
    now = datetime.now()
    today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
    if period == "today":
        return "Hari Ini", today_start, today_start + timedelta(days=1)

    month_start = today_start.replace(day=1)
    if month_start.month == 12:
        next_month = month_start.replace(year=month_start.year + 1, month=1)
    else:
        next_month = month_start.replace(month=month_start.month + 1)
    if period == "month":
        return now.strftime("Bulan Ini (%m/%Y)"), month_start, next_month

    return "Semua Transaksi", None, None


def format_owner_transaction_dashboard():
    today_label, today_start, today_end = get_report_period_bounds("today")
    month_label, month_start, month_end = get_report_period_bounds("month")
    today_stats = get_transaction_stats_by_period(today_start, today_end)
    month_stats = get_transaction_stats_by_period(month_start, month_end)

    return (
        "📊 <b>Laporan Transaksi</b>\n\n"
        f"<b>{today_label}</b>:\n"
        f"{_stats_lines(today_stats)}\n\n"
        f"<b>{month_label}</b>:\n"
        f"{_stats_lines(month_stats)}\n\n"
        "Pilih aksi laporan:"
    )


def format_period_transaction_report(period, limit=10):
    label, start_at, end_at = get_report_period_bounds(period)
    stats = get_transaction_stats_by_period(start_at, end_at)
    transactions = get_transactions_by_period(start_at, end_at, limit=limit)

    return (
        f"📊 <b>Laporan {html.escape(label)}</b>\n\n"
        f"{_stats_lines(stats)}\n\n"
        f"📦 <b>{len(transactions)} Transaksi Terbaru</b>\n\n"
        f"{_format_transaction_rows(transactions)}"
    )


def format_recent_transaction_report(limit=10):
    transactions = get_all_transactions(limit=limit)
    return (
        "📦 <b>Transaksi Terakhir</b>\n\n"
        f"{_format_transaction_rows(transactions)}"
    )


def format_user_transaction_report(search, limit=10):
    transactions = get_user_transactions_for_admin(search, limit=limit)
    if not transactions:
        return (
            "🔎 <b>Cari User</b>\n\n"
            f"Tidak ada transaksi untuk: <code>{html.escape(str(search).strip())}</code>"
        )

    first = transactions[0]
    username = f"@{first.get('username')}" if first.get("username") else "-"
    name = first.get("first_name") or "-"
    stats = get_user_transaction_stats_for_admin(search)

    return (
        "🔎 <b>Hasil Cari User</b>\n\n"
        f"Nama: <b>{html.escape(str(name))}</b>\n"
        f"Username: {html.escape(str(username))}\n"
        f"User ID: <code>{html.escape(str(first.get('user_id') or '-'))}</code>\n\n"
        f"{_stats_lines(stats)}\n\n"
        f"📦 <b>{len(transactions)} Transaksi Terbaru</b>\n\n"
        f"{_format_transaction_rows(transactions, show_user=False)}"
    )


def build_transaction_csv(limit=5000):
    transactions = get_all_transactions(limit=limit)
    output = StringIO()
    writer = csv.writer(output)
    writer.writerow([
        "id",
        "transaction_code",
        "user_id",
        "package_type",
        "package_label",
        "harga_bayar",
        "promo_used",
        "status",
        "created_at",
    ])
    for tx in transactions:
        writer.writerow([
            tx.get("id"),
            tx.get("transaction_code") or "",
            tx.get("user_id"),
            tx.get("package_type") or "",
            tx.get("package_label") or "",
            tx.get("harga_bayar") or 0,
            tx.get("promo_used") or "",
            tx.get("status") or "",
            tx.get("created_at") or "",
        ])
    return output.getvalue()


def format_transaction_report(limit=20, offset=0):
    """
    Format laporan transaksi untuk admin
    
    Args:
        limit: Jumlah transaksi yang ditampilkan
        offset: Offset untuk pagination
    
    Returns:
        Formatted text untuk ditampilkan
    """
    transactions = get_all_transactions(limit=limit, offset=offset)
    
    if not transactions:
        return "📊 Belum ada data transaksi."
    
    text = f"📊 <b>Laporan Transaksi</b> (Menampilkan {len(transactions)} data terakhir)\n\n"
    
    for tx in transactions:
        status_emoji = "✅" if tx['status'] == "approved" else "❌" if tx['status'] == "rejected" else "⏳"
        status_text = {
            "approved": "Disetujui",
            "rejected": "Ditolak",
            "pending": "Tertunda"
        }.get(tx['status'], tx['status'])
        
        promo_text = f" (Promo: {tx['promo_used']})" if tx['promo_used'] else ""
        
        text += (
            f"{status_emoji} <b>{tx['package_label']}</b>\n"
            f"👤 User ID: {tx['user_id']}\n"
            f"💰 Rp {tx['harga_bayar']:,}{promo_text}\n"
            f"🏷️ {status_text}\n"
            f"📅 {tx['created_at']}\n\n"
        )
    
    return text


def format_transaction_statistics():
    """
    Format statistik transaksi keseluruhan untuk admin dashboard
    
    Returns:
        Formatted text dengan statistik
    """
    stats = get_transaction_stats()
    
    if not stats or stats['total_transactions'] == 0:
        return (
            "📊 <b>Statistik Transaksi</b>\n\n"
            "Belum ada data transaksi."
        )
    
    total_revenue = stats['total_revenue'] if stats['total_revenue'] else 0
    avg_transaction = total_revenue / stats['total_transactions'] if stats['total_transactions'] > 0 else 0
    
    text = (
        "📊 <b>Statistik Transaksi Keseluruhan</b>\n\n"
        f"📦 Total Transaksi: <b>{stats['total_transactions']}</b>\n"
        f"👥 Total User Unik: <b>{stats['total_users']}</b>\n"
        f"✅ Disetujui: <b>{stats['approved_count']}</b>\n"
        f"❌ Ditolak: <b>{stats['rejected_count']}</b>\n"
        f"⏳ Tertunda: <b>{stats['pending_count']}</b>\n\n"
        f"💰 Total Revenue: <b>Rp {total_revenue:,}</b>\n"
        f"📊 Avg per Transaksi: <b>Rp {avg_transaction:,.0f}</b>\n"
        f"📈 Success Rate: <b>{(stats['approved_count'] / stats['total_transactions'] * 100):.1f}%</b>"
    )
    
    return text
