from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends, Query, HTTPException, File, UploadFile, Form
from services.chat_manager import manager
from services.global_manager import global_manager
import db
import auth_utils
import datetime
import schemas
import locales
from dependencies import get_current_user
import os
import uuid
import config
import json
from typing import Optional

router = APIRouter(tags=["chat"])

# In-memory storage for flood control: {user_id: timestamp}
last_message_times = {}

@router.get("/orders/{order_id}/messages")
async def get_order_messages(order_id: int, user: dict = Depends(get_current_user)):
    role = user.get("role")
    user_id = user.get("id")
    # Fetch user chat status
    user_info = db.execute_query("SELECT can_chat FROM users WHERE id = %s", (user_id,))
    can_chat = user_info[0]['can_chat'] if user_info else False

    order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
    if not order: raise HTTPException(status_code=404, detail="Order not found")
    if role != 'admin':
        if order[0]['user_id'] != user_id: raise HTTPException(status_code=403, detail="Not authorized")
        if not can_chat: raise HTTPException(status_code=403, detail="Chat access disabled for your account")
    query = """
        SELECT m.id, m.is_from_admin, m.message, m.created_at, u.first_name, u.email 
        FROM order_messages m
        LEFT JOIN users u ON m.user_id = u.id
        WHERE m.order_id = %s AND m.deleted = FALSE 
        ORDER BY m.created_at ASC
    """
    messages = db.execute_query(query, (order_id,))
    for msg in messages:
        if msg.get('created_at'): msg['created_at'] = msg['created_at'].isoformat()
        msg['is_from_admin'] = bool(msg['is_from_admin'])
        
    # Mark messages as read
    if role == 'admin':
        db.execute_commit("UPDATE order_messages SET is_read = TRUE WHERE order_id = %s AND is_from_admin = FALSE AND is_read = FALSE", (order_id,))
        await global_manager.notify_admins()
        await global_manager.notify_order_read(order_id)
    else:
        db.execute_commit("UPDATE order_messages SET is_read = TRUE WHERE order_id = %s AND is_from_admin = TRUE AND is_read = FALSE", (order_id,))
        await global_manager.notify_user(user_id)
        
    return messages

@router.post("/orders/{order_id}/messages")
async def post_order_message(
    order_id: int, 
    message: Optional[str] = Form(None),
    file: Optional[UploadFile] = File(None),
    user: dict = Depends(get_current_user), 
    lang: str = "en"
):
    role = user.get("role")
    user_id = user.get("id")
    
    # Flood control for non-admin users
    if role != 'admin':
        now = datetime.datetime.utcnow().timestamp()
        last_time = last_message_times.get(user_id, 0)
        if now - last_time < 10:
             raise HTTPException(status_code=429, detail=locales.translate_error("flood_control", lang))
        last_message_times[user_id] = now

    if not message and not file:
        raise HTTPException(status_code=400, detail="Empty message")

    if message:
        message = message.strip()

    is_admin = (role == 'admin')
    
    if not is_admin:
        user_info = db.execute_query("SELECT can_chat FROM users WHERE id = %s", (user_id,))
        if not user_info or not user_info[0]['can_chat']:
            raise HTTPException(status_code=403, detail="Chat access disabled")

    order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
    if not order: raise HTTPException(status_code=404, detail="Order not found")
    if not is_admin and order[0]['user_id'] != user_id: raise HTTPException(status_code=403, detail="Not authorized")

    final_message = ""
    db_file_path = None
    
    if file and file.filename:
        file_ext = os.path.splitext(file.filename)[1]
        unique_filename = f"{uuid.uuid4()}{file_ext}"
        file_path = os.path.join(config.CHAT_UPLOADS_DIR, unique_filename)
        db_file_path = f"uploads/chats/{unique_filename}"
        
        with open(file_path, "wb") as buffer:
            while chunk := file.file.read(8192):
                buffer.write(chunk)
                
    msg_obj = {}
    if db_file_path:
        msg_obj["image_url"] = db_file_path
    if message:
        msg_obj["text"] = message
        
    final_message = json.dumps(msg_obj)

    query = "INSERT INTO order_messages (order_id, user_id, is_from_admin, message) VALUES (%s, %s, %s, %s)"
    msg_id = db.execute_commit(query, (order_id, user_id, is_admin, final_message))
    now = datetime.datetime.utcnow().isoformat()
    
    user_info = db.execute_query("SELECT first_name, email FROM users WHERE id = %s", (user_id,))
    first_name = user_info[0]['first_name'] if user_info else None
    email = user_info[0]['email'] if user_info else None
    
    await manager.broadcast_to_order(order_id, {
        "id": msg_id, 
        "is_from_admin": is_admin, 
        "message": final_message, 
        "created_at": now,
        "first_name": first_name,
        "email": email
    })
    
    if is_admin:
        await global_manager.notify_user(order[0]['user_id'])
    else:
        from services import event_hooks
        await global_manager.notify_admins()
        await global_manager.notify_admins_new_message(order_id, message or "Image uploaded")
        event_hooks.on_message_received(order_id, user_id, message or "Image uploaded", db_file_path)
        
    return {
        "id": msg_id, 
        "status": "sent", 
        "message": final_message,
        "first_name": first_name,
        "email": email
    }

@router.delete("/orders/{order_id}/messages/{msg_id}")
async def delete_order_message(order_id: int, msg_id: int, user: dict = Depends(get_current_user)):
    user_id = user.get("id")
    role = user.get("role")
    is_admin = (role == 'admin')

    # Check order access
    order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
    if not order:
        raise HTTPException(status_code=404, detail="Order not found")
    if not is_admin and order[0]['user_id'] != user_id:
        raise HTTPException(status_code=403, detail="Not authorized")

    # Fetch the message
    msg = db.execute_query("SELECT * FROM order_messages WHERE id = %s AND order_id = %s", (msg_id, order_id))
    if not msg:
        raise HTTPException(status_code=404, detail="Message not found")

    # Only admin or the sender can delete the message
    if not is_admin and msg[0]['user_id'] != user_id:
        raise HTTPException(status_code=403, detail="Not authorized to delete this message")

    # Soft delete message from database
    db.execute_commit("UPDATE order_messages SET deleted = TRUE WHERE id = %s", (msg_id,))

    # Broadcast deletion
    await manager.broadcast_to_order(order_id, {
        "id": msg_id,
        "type": "message_deleted"
    })

    return {"message": "Deleted successfully"}
