from pydantic import BaseModel, Field
from typing import List
from pymongo import MongoClient
from pymongo.errors import DuplicateKeyError
from bson import ObjectId

# ==========================================
# 1. DATA MODEL (Nhận dữ liệu từ React)
# ==========================================
class CategoryPayload(BaseModel):
    name: str = Field(..., min_length=1)
    slug: str = Field(..., min_length=1)
    subcategories: List[str] = []

# ==========================================
# 2. DATABASE MODEL (Lưu vào MongoDB)
# ==========================================
class CategoryDatabaseModel:
    def __init__(self, db_uri: str, db_name: str, collection_name: str):
        self.client = MongoClient(db_uri)
        self.db = self.client[db_name]
        self.collection = self.db[collection_name]

    def insert_category(self, category_data: dict) -> str:
        # BIẾN THUẬT: Ép cái 'slug' trở thành khóa chính '_id' của MongoDB
        category_data["_id"] = category_data["slug"]
        
        try:
            # Lưu vào database
            self.collection.insert_one(category_data)
            return category_data["_id"]
            
        except DuplicateKeyError:
            # Nếu MongoDB phát hiện slug (ví dụ 'apparel') đã tồn tại, nó sẽ văng lỗi này
            raise ValueError(f"Danh mục có đường dẫn '{category_data['slug']}' đã tồn tại!")
        except Exception as e:
            raise Exception(f"Lỗi Database: {str(e)}")
        
    def get_all_categories(self) -> List[dict]:
        """Lấy toàn bộ danh sách danh mục."""
        try:
            # MongoDB trả về _id dạng ObjectId, chúng ta cần biến nó 
            # thành string để Frontend JSON dễ đọc
            categories = list(self.collection.find())
            for cat in categories:
                if '_id' in cat:
                    cat['_id'] = str(cat['_id'])
            return categories
        except Exception as e:
            raise Exception(f"Lỗi lấy danh mục: {str(e)}")
    
    def update_category(self, category_id: str, data: dict):
        """Hàm tìm và cập nhật Category trong MongoDB (Bản an toàn)"""
        try:
            print(f"--- Bắt đầu cập nhật Category ID: {category_id} ---")
            print(f"Dữ liệu nhận được: {data}")
            
            # 1. Dùng .get() cho an toàn, tránh lỗi KeyError
            slug = data.get("slug")
            if slug:
                existing = self.collection.find_one({"slug": slug})
                # Kiểm tra trùng slug với ID khác
                if existing and str(existing.get("_id")) != category_id:
                    raise ValueError("Đường dẫn (Slug) này đã được sử dụng cho danh mục khác!")

            # 2. Xử lý ID (Vì trong DB của bạn ID có thể là "apparel" hoặc "69cb...")
            if ObjectId.is_valid(category_id):
                query = {"_id": ObjectId(category_id)}
            else:
                query = {"_id": category_id}
                
            print(f"Query tìm kiếm DB: {query}")
            
            # 3. Cập nhật vào DB
            result = self.collection.update_one(query, {"$set": data})
            print(f"Số bản ghi đã cập nhật: {result.modified_count}")
            
            return result.modified_count
            
        except ValueError as ve:
            print(f"Lỗi Logic (Value Error): {ve}")
            raise ve
        except Exception as e:
            print(f"Lỗi Exception Hệ thống: {str(e)}")
            raise Exception(f"Lỗi Database: {str(e)}")

    def delete_category(self, category_id: str):
        """Hàm tìm và xóa Category khỏi MongoDB"""
        try:
            query = {"_id": ObjectId(category_id)} if ObjectId.is_valid(category_id) else {"_id": category_id}
            result = self.collection.delete_one(query)
            return result.deleted_count
        except Exception as e:
            raise Exception(f"Lỗi Database: {str(e)}")