import re
import os
import base64
from datetime import datetime
import pytz
from pydantic import BaseModel
from typing import Optional
from bson import ObjectId
from MongoDBConnection import tickets_collection, users_collection

VN_TZ = pytz.timezone('Asia/Ho_Chi_Minh')
UPLOAD_DIR = os.path.join("uploads", "upload_img")
os.makedirs(UPLOAD_DIR, exist_ok=True)


# --- SCHEMAS ---
class TicketCreatePayload(BaseModel):
    orderId: str
    reason: str
    imageUrl: Optional[str] = None
    imageName: Optional[str] = None
    id_khach_hang: Optional[str] = None
    ten_khach_hang: Optional[str] = None


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


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

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

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

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

        max_seq = 0
        for doc in latest_docs:
            ticket_id = str(doc.get("id") or "")
            match = regex.match(ticket_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 = tickets_collection.find_one({"id": generated}, {"_id": 1})
            if not existed:
                return generated
            next_seq += 1

    @staticmethod
    def create_ticket(payload: TicketCreatePayload):
        now = datetime.now(VN_TZ)
        ticket_id = TicketModel._generate_ticket_id(now)
        saved_image_name = None

        if payload.imageUrl and payload.imageName:
            try:
                if "," in payload.imageUrl:
                    _, encoded = payload.imageUrl.split(",", 1)
                else:
                    encoded = payload.imageUrl

                file_ext = payload.imageName.split('.')[-1]
                unique_filename = f"{ticket_id}.{file_ext}"
                filepath = os.path.join(UPLOAD_DIR, unique_filename)

                with open(filepath, "wb") as f:
                    f.write(base64.b64decode(encoded))
                saved_image_name = unique_filename
            except Exception as e:
                print(f"Lỗi khi lưu ảnh: {e}")

        new_ticket = {
            "id": ticket_id,
            "orderId": payload.orderId,
            "reason": payload.reason,
            "imageName": saved_image_name,
            "id_khach_hang": payload.id_khach_hang,
            "ten_khach_hang": payload.ten_khach_hang,
            "status": "pending",
            "createdAt": now.isoformat()
        }

        tickets_collection.insert_one(new_ticket)
        return True, "Ticket created successfully"

    @staticmethod
    def get_tickets(base_url: str, status: str = None, dateFrom: str = None, dateTo: str = None, id_khach_hang: str = None):
        query = {}
        if id_khach_hang:
            query["id_khach_hang"] = id_khach_hang
        if status and status.lower() != "all":
            query["status"] = status.lower()
        if dateFrom or dateTo:
            date_query = {}
            if dateFrom:
                date_query["$gte"] = f"{dateFrom}T00:00:00"
            if dateTo:
                date_query["$lte"] = f"{dateTo}T23:59:59"
            if date_query:
                query["createdAt"] = date_query

        cursor = tickets_collection.find(query).sort("createdAt", -1)
        results = list(cursor)

        formatted_data = []
        for doc in results:
            if "_id" in doc:
                del doc["_id"]

            user_id_str = doc.get("id_khach_hang")
            doc["email"] = "N/A"
            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", "N/A")
                except Exception:
                    pass

            img_name = doc.get("imageName")
            doc["imageUrl"] = f"{base_url}/uploads/upload_img/{img_name}" if img_name else None

            if doc.get("createdAt"):
                dt = datetime.fromisoformat(doc["createdAt"])
                doc["createdAt"] = dt.strftime("%d/%m/%Y %H:%M:%S")

            formatted_data.append(doc)

        return formatted_data

    @staticmethod
    def update_ticket_status(req: TicketUpdateRequest):
        ticket = tickets_collection.find_one({"id": req.ticketId})
        if not ticket:
            return False, "Không tìm thấy phiếu khiếu nại này", 404

        update_fields = {
            "status": req.status.lower(),
            "processedBy": req.processedBy
        }

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

        tickets_collection.update_one({"id": req.ticketId}, {"$set": update_fields})
        return True, "Đã cập nhật trạng thái khiếu nại thành công", 200