import re
import pytz
from datetime import datetime, timedelta
from pydantic import BaseModel
from typing import Optional
from bson import ObjectId
from MongoDBConnection import transactions_collection, users_collection

VN_TZ = pytz.timezone('Asia/Ho_Chi_Minh')


def format_to_vn_str(dt_obj):
    """Đảm bảo format Ngày/Tháng/Năm (DD/MM/YYYY)"""
    if dt_obj.tzinfo is None:
        dt_obj = pytz.utc.localize(dt_obj)
    return dt_obj.astimezone(VN_TZ).strftime("%d/%m/%Y %H:%M:%S")


# --- SCHEMAS ---
class TopUpRequest(BaseModel):
    paymentMethod: str
    referenceId: str
    amount: float
    receiptUrl: Optional[str] = None
    id_khach_hang: str
    ten_khach_hang: str


class TopUpUpdateRequest(BaseModel):
    ticketId: str
    type: str
    status: str
    processedBy: str
    rejectReason: Optional[str] = None


# --- MODEL LOGIC ---
class TopupModel:
    @staticmethod
    def _generate_transaction_id(prefix: str, vn_now: Optional[datetime] = None) -> str:
        vn_now = vn_now or datetime.now(VN_TZ)

        # Format: TUDP-20260414115349058-0001
        timestamp_part = vn_now.strftime("%Y%m%d%H%M%S") + f"{vn_now.microsecond // 1000:03d}"
        base_prefix = f"{prefix}-{timestamp_part}-"

        regex = re.compile(rf"^{re.escape(base_prefix)}(\d{{4}})$")

        latest_docs = transactions_collection.find(
            {"id": {"$regex": rf"^{re.escape(base_prefix)}\d{{4}}$"}},
            {"id": 1}
        )

        max_seq = 0
        for doc in latest_docs:
            tx_id = str(doc.get("id") or "")
            match = regex.match(tx_id)
            if match:
                max_seq = max(max_seq, int(match.group(1)))

        next_seq = max_seq + 1

        while True:
            generated = f"{base_prefix}{str(next_seq).zfill(4)}"
            existed = transactions_collection.find_one({"id": generated}, {"_id": 1})
            if not existed:
                return generated
            next_seq += 1

    @staticmethod
    def create_topup(request: TopUpRequest):
        now_vn = datetime.now(VN_TZ)
        tx_id = TopupModel._generate_transaction_id("TUDP", now_vn)

        new_doc = {
            "id": tx_id,
            "date": now_vn,
            "type": "Deposit",
            "amount": f"+${request.amount:,.2f}",
            "numericAmount": request.amount,
            "status": "Pending",
            "reasonKey": f"Nạp tiền qua {request.paymentMethod}",
            "referenceId": request.referenceId,
            "paymentMethod": request.paymentMethod,
            "receiptUrl": request.receiptUrl,
            "id_khach_hang": request.id_khach_hang,
            "ten_khach_hang": request.ten_khach_hang
        }
        transactions_collection.insert_one(new_doc)

        response_data = new_doc.copy()
        response_data["date"] = format_to_vn_str(now_vn)
        if "_id" in response_data:
            del response_data["_id"]
        return response_data

    @staticmethod
    def create_deduction_transaction(id_khach_hang: str, ten_khach_hang: str, amount: float, order_ids: list[str]):
        now_vn = datetime.now(VN_TZ)
        tx_id = TopupModel._generate_transaction_id("TUDD", now_vn)
        order_ref = ", ".join(order_ids)

        new_doc = {
            "id": tx_id,
            "date": now_vn,
            "type": "Deduction",
            "amount": f"-${amount:,.2f}",
            "numericAmount": amount,
            "status": "Completed",
            "reasonKey": f"Thanh toán đơn hàng {order_ref}",
            "referenceId": order_ref,
            "paymentMethod": "Balance",
            "receiptUrl": None,
            "id_khach_hang": id_khach_hang,
            "ten_khach_hang": ten_khach_hang
        }

        transactions_collection.insert_one(new_doc)

        response_data = new_doc.copy()
        response_data["date"] = format_to_vn_str(now_vn)
        if "_id" in response_data:
            del response_data["_id"]
        return response_data

    @staticmethod
    def get_topups(tx_type="all", page=1, pageSize=10, id_khach_hang=None, status=None, dateFrom=None, dateTo=None):
        query = {}
        if id_khach_hang:
            query["id_khach_hang"] = id_khach_hang

        if tx_type == "deposits":
            query["type"] = "Deposit"
        elif tx_type == "deductions":
            query["type"] = "Deduction"

        if status and status.lower() != "all":
            query["status"] = status.capitalize()

        if dateFrom or dateTo:
            date_query = {}
            if dateFrom:
                dt_from = VN_TZ.localize(datetime.strptime(dateFrom, "%Y-%m-%d"))
                date_query["$gte"] = dt_from
            if dateTo:
                dt_to = VN_TZ.localize(datetime.strptime(dateTo, "%Y-%m-%d") + timedelta(days=1, seconds=-1))
                date_query["$lte"] = dt_to
            if date_query:
                query["date"] = date_query

        cursor = (
            transactions_collection.find(query)
            .sort("date", -1)
            .skip((page - 1) * pageSize)
            .limit(pageSize)
        )
        results = list(cursor)
        total_count = transactions_collection.count_documents(query)

        formatted_data = []
        for doc in results:
            user_id_str = doc.get("id_khach_hang")
            doc["email"] = "Không rõ email"
            if user_id_str:
                try:
                    user_info = users_collection.find_one({"_id": ObjectId(user_id_str)})
                    if user_info:
                        doc["email"] = user_info.get("email", "Không rõ email")
                except Exception:
                    doc["email"] = "ID không hợp lệ"

            if isinstance(doc.get("date"), datetime):
                doc["date"] = format_to_vn_str(doc["date"])
            if "_id" in doc:
                del doc["_id"]
            formatted_data.append(doc)

        return formatted_data, total_count

    @staticmethod
    def update_ticket(req: TopUpUpdateRequest):
        ticket = transactions_collection.find_one({"id": req.ticketId})
        if not ticket:
            return False, "Không tìm thấy giao dịch", 404

        if req.status == "approved" and ticket.get("status") == "Pending":
            amount_to_add = ticket.get("numericAmount", 0)
            user_id_str = ticket.get("id_khach_hang")
            if user_id_str:
                try:
                    users_collection.update_one(
                        {"_id": ObjectId(user_id_str)},
                        {"$inc": {"balance": amount_to_add}}
                    )
                except Exception as e:
                    print(f"Lỗi khi cộng tiền: {e}")

        update_fields = {
            "status": req.status.capitalize() if req.status != "resolved" else "Resolved",
            "processedBy": req.processedBy
        }

        if req.status == "rejected" and req.rejectReason:
            update_fields["rejectReason"] = req.rejectReason

        transactions_collection.update_one({"id": req.ticketId}, {"$set": update_fields})
        return True, "Đã duyệt và cập nhật thành công", 200