"""
Support Ticket System Module
Two separate ticket systems:
1. Internal Tickets (Tenant Admin): manages tickets from employees within org
2. Platform Tickets (Super Admin): tenant admins submit tickets to super admin support
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query, UploadFile, File, Form
from typing import Optional, List, Dict, Any
from datetime import datetime
from pydantic import BaseModel
import uuid
import base64
import logging

from auth import get_current_user, get_current_org, require_super_admin
from models import UserRole

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api", tags=["Support Tickets"])

db = None


def init_support_ticket_system(database):
    global db
    db = database


# ==================== Models ====================

class InternalTicketCreate(BaseModel):
    subject: str
    description: str
    priority: str = "medium"
    category: str = "general"


class TicketComment(BaseModel):
    message: str
    attachment_url: Optional[str] = None


class TicketAssign(BaseModel):
    assigned_to: str


class TicketStatusUpdate(BaseModel):
    status: str


class PlatformTicketCreate(BaseModel):
    subject: str
    description: str
    priority: str = "medium"
    category: str = "platform_support"


# ==================== Internal Tickets (Tenant Admin manages employee tickets) ====================

@router.post("/tickets/internal")
async def create_internal_ticket(
    data: InternalTicketCreate,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Any org user can create an internal support ticket"""
    user = await db.users.find_one({"id": current_user["sub"]})

    ticket = {
        "id": str(uuid.uuid4()),
        "type": "internal",
        "organization_id": org_id,
        "user_id": current_user["sub"],
        "user_email": current_user.get("email", user.get("email", "") if user else ""),
        "user_name": user.get("username", "") if user else "",
        "subject": data.subject,
        "description": data.description,
        "priority": data.priority,
        "category": data.category,
        "status": "open",
        "assigned_to": None,
        "assigned_to_name": None,
        "comments": [],
        "attachments": [],
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow(),
    }

    await db.internal_tickets.insert_one(ticket)
    ticket.pop("_id", None)
    return ticket


@router.get("/tickets/internal")
async def list_internal_tickets(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    ticket_status: Optional[str] = None,
    priority: Optional[str] = None,
    assigned_to: Optional[str] = None,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """List internal tickets. Admin sees all org tickets, others see their own."""
    query: Dict[str, Any] = {"organization_id": org_id, "type": "internal"}

    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        query["user_id"] = current_user["sub"]

    if ticket_status:
        query["status"] = ticket_status
    if priority:
        query["priority"] = priority
    if assigned_to:
        query["assigned_to"] = assigned_to

    total = await db.internal_tickets.count_documents(query)
    tickets = await db.internal_tickets.find(query).sort("created_at", -1).skip(skip).limit(limit).to_list(limit)

    for ticket in tickets:
        ticket.pop("_id", None)

    return {"tickets": tickets, "total": total, "skip": skip, "limit": limit}


@router.get("/tickets/internal/{ticket_id}")
async def get_internal_ticket(
    ticket_id: str,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Get internal ticket detail"""
    ticket = await db.internal_tickets.find_one({"id": ticket_id, "organization_id": org_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    if (current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]
            and ticket["user_id"] != current_user["sub"]
            and ticket.get("assigned_to") != current_user["sub"]):
        raise HTTPException(status_code=403, detail="Access denied")

    ticket.pop("_id", None)
    return ticket


@router.patch("/tickets/internal/{ticket_id}/status")
async def update_internal_ticket_status(
    ticket_id: str,
    data: TicketStatusUpdate,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Update internal ticket status (admin only)"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    valid_statuses = ["open", "in_progress", "resolved", "closed", "waiting_on_user"]
    if data.status not in valid_statuses:
        raise HTTPException(status_code=400, detail=f"Invalid status. Must be one of: {valid_statuses}")

    ticket = await db.internal_tickets.find_one({"id": ticket_id, "organization_id": org_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    updates = {"status": data.status, "updated_at": datetime.utcnow()}
    if data.status == "resolved":
        updates["resolved_at"] = datetime.utcnow()

    await db.internal_tickets.update_one({"id": ticket_id}, {"$set": updates})

    updated = await db.internal_tickets.find_one({"id": ticket_id})
    updated.pop("_id", None)
    return updated


@router.patch("/tickets/internal/{ticket_id}/assign")
async def assign_internal_ticket(
    ticket_id: str,
    data: TicketAssign,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Assign internal ticket to an employee (admin only)"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    ticket = await db.internal_tickets.find_one({"id": ticket_id, "organization_id": org_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    assignee = await db.users.find_one({"id": data.assigned_to, "organization_id": org_id})
    if not assignee:
        raise HTTPException(status_code=404, detail="Assignee not found in organization")

    await db.internal_tickets.update_one(
        {"id": ticket_id},
        {"$set": {
            "assigned_to": data.assigned_to,
            "assigned_to_name": assignee.get("username", assignee.get("email", "")),
            "status": "in_progress" if ticket["status"] == "open" else ticket["status"],
            "updated_at": datetime.utcnow(),
        }}
    )

    updated = await db.internal_tickets.find_one({"id": ticket_id})
    updated.pop("_id", None)
    return updated


@router.post("/tickets/internal/{ticket_id}/comment")
async def add_internal_ticket_comment(
    ticket_id: str,
    data: TicketComment,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Add comment to internal ticket"""
    ticket = await db.internal_tickets.find_one({"id": ticket_id, "organization_id": org_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    if (current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]
            and ticket["user_id"] != current_user["sub"]
            and ticket.get("assigned_to") != current_user["sub"]):
        raise HTTPException(status_code=403, detail="Access denied")

    user = await db.users.find_one({"id": current_user["sub"]})
    is_admin = current_user.get("role") in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]

    comment = {
        "id": str(uuid.uuid4()),
        "user_id": current_user["sub"],
        "user_name": user.get("username", "") if user else "",
        "user_email": current_user.get("email", ""),
        "message": data.message,
        "attachment_url": data.attachment_url,
        "is_admin": is_admin,
        "created_at": datetime.utcnow(),
    }

    await db.internal_tickets.update_one(
        {"id": ticket_id},
        {
            "$push": {"comments": comment},
            "$set": {"updated_at": datetime.utcnow()},
        }
    )

    updated = await db.internal_tickets.find_one({"id": ticket_id})
    updated.pop("_id", None)
    return updated


@router.post("/tickets/internal/{ticket_id}/upload")
async def upload_ticket_attachment(
    ticket_id: str,
    file: UploadFile = File(...),
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Upload image/attachment to a ticket"""
    ticket = await db.internal_tickets.find_one({"id": ticket_id, "organization_id": org_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    allowed_types = ["image/jpeg", "image/png", "image/gif", "image/webp", "application/pdf"]
    if file.content_type not in allowed_types:
        raise HTTPException(status_code=400, detail=f"File type not allowed. Allowed: {allowed_types}")

    max_size = 5 * 1024 * 1024  # 5MB
    content = await file.read()
    if len(content) > max_size:
        raise HTTPException(status_code=400, detail="File too large. Maximum 5MB")

    encoded = base64.b64encode(content).decode("utf-8")

    attachment = {
        "id": str(uuid.uuid4()),
        "filename": file.filename,
        "content_type": file.content_type,
        "size": len(content),
        "data": encoded,
        "uploaded_by": current_user["sub"],
        "uploaded_at": datetime.utcnow(),
    }

    await db.internal_tickets.update_one(
        {"id": ticket_id},
        {
            "$push": {"attachments": attachment},
            "$set": {"updated_at": datetime.utcnow()},
        }
    )

    attachment_info = {k: v for k, v in attachment.items() if k != "data"}
    return {"message": "File uploaded successfully", "attachment": attachment_info}


@router.get("/tickets/internal/{ticket_id}/attachments/{attachment_id}")
async def get_ticket_attachment(
    ticket_id: str,
    attachment_id: str,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Get attachment data"""
    ticket = await db.internal_tickets.find_one({"id": ticket_id, "organization_id": org_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    attachment = next(
        (a for a in ticket.get("attachments", []) if a["id"] == attachment_id),
        None
    )
    if not attachment:
        raise HTTPException(status_code=404, detail="Attachment not found")

    return attachment


# ==================== Platform Tickets (Tenant Admin -> Super Admin) ====================

@router.post("/tickets/platform")
async def create_platform_ticket(
    data: PlatformTicketCreate,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Tenant admin creates a ticket for super admin support"""
    if current_user.get("role") not in [UserRole.ADMIN.value]:
        raise HTTPException(status_code=403, detail="Only tenant admins can create platform support tickets")

    user = await db.users.find_one({"id": current_user["sub"]})
    org = await db.organizations.find_one({"id": org_id})

    ticket = {
        "id": str(uuid.uuid4()),
        "type": "platform",
        "organization_id": org_id,
        "organization_name": org.get("name", "") if org else "",
        "user_id": current_user["sub"],
        "user_email": current_user.get("email", user.get("email", "") if user else ""),
        "user_name": user.get("username", "") if user else "",
        "subject": data.subject,
        "description": data.description,
        "priority": data.priority,
        "category": data.category,
        "status": "open",
        "comments": [],
        "attachments": [],
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow(),
    }

    await db.platform_tickets.insert_one(ticket)
    ticket.pop("_id", None)
    return ticket


@router.get("/tickets/platform")
async def list_platform_tickets(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    ticket_status: Optional[str] = None,
    priority: Optional[str] = None,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """List platform tickets. Tenant admin sees their own, super admin sees all."""
    query: Dict[str, Any] = {"type": "platform"}

    if current_user.get("role") == UserRole.SUPER_ADMIN.value:
        pass  # super admin sees all
    elif current_user.get("role") == UserRole.ADMIN.value:
        query["organization_id"] = org_id
    else:
        raise HTTPException(status_code=403, detail="Access denied")

    if ticket_status:
        query["status"] = ticket_status
    if priority:
        query["priority"] = priority

    total = await db.platform_tickets.count_documents(query)
    tickets = await db.platform_tickets.find(query).sort("created_at", -1).skip(skip).limit(limit).to_list(limit)

    for ticket in tickets:
        ticket.pop("_id", None)

    return {"tickets": tickets, "total": total, "skip": skip, "limit": limit}


@router.get("/tickets/platform/{ticket_id}")
async def get_platform_ticket(
    ticket_id: str,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Get platform ticket detail"""
    ticket = await db.platform_tickets.find_one({"id": ticket_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    if (current_user.get("role") == UserRole.ADMIN.value
            and ticket["organization_id"] != org_id):
        raise HTTPException(status_code=403, detail="Access denied")
    elif current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Access denied")

    ticket.pop("_id", None)
    return ticket


@router.patch("/tickets/platform/{ticket_id}/status")
async def update_platform_ticket_status(
    ticket_id: str,
    data: TicketStatusUpdate,
    current_user: dict = Depends(require_super_admin),
):
    """Update platform ticket status (super admin only)"""
    valid_statuses = ["open", "in_progress", "resolved", "closed", "waiting_on_admin"]
    if data.status not in valid_statuses:
        raise HTTPException(status_code=400, detail=f"Invalid status. Must be one of: {valid_statuses}")

    ticket = await db.platform_tickets.find_one({"id": ticket_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    updates = {"status": data.status, "updated_at": datetime.utcnow()}
    if data.status == "resolved":
        updates["resolved_at"] = datetime.utcnow()

    await db.platform_tickets.update_one({"id": ticket_id}, {"$set": updates})

    updated = await db.platform_tickets.find_one({"id": ticket_id})
    updated.pop("_id", None)
    return updated


@router.post("/tickets/platform/{ticket_id}/comment")
async def add_platform_ticket_comment(
    ticket_id: str,
    data: TicketComment,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Add comment to platform ticket (tenant admin or super admin)"""
    ticket = await db.platform_tickets.find_one({"id": ticket_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    if current_user.get("role") == UserRole.ADMIN.value and ticket["organization_id"] != org_id:
        raise HTTPException(status_code=403, detail="Access denied")
    elif current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Access denied")

    user = await db.users.find_one({"id": current_user["sub"]})
    is_super_admin = current_user.get("role") == UserRole.SUPER_ADMIN.value

    comment = {
        "id": str(uuid.uuid4()),
        "user_id": current_user["sub"],
        "user_name": user.get("username", "") if user else "",
        "user_email": current_user.get("email", ""),
        "message": data.message,
        "attachment_url": data.attachment_url,
        "is_super_admin": is_super_admin,
        "created_at": datetime.utcnow(),
    }

    await db.platform_tickets.update_one(
        {"id": ticket_id},
        {
            "$push": {"comments": comment},
            "$set": {"updated_at": datetime.utcnow()},
        }
    )

    updated = await db.platform_tickets.find_one({"id": ticket_id})
    updated.pop("_id", None)
    return updated


@router.post("/tickets/platform/{ticket_id}/upload")
async def upload_platform_ticket_attachment(
    ticket_id: str,
    file: UploadFile = File(...),
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Upload image/attachment to a platform ticket"""
    ticket = await db.platform_tickets.find_one({"id": ticket_id})
    if not ticket:
        raise HTTPException(status_code=404, detail="Ticket not found")

    if current_user.get("role") == UserRole.ADMIN.value and ticket["organization_id"] != org_id:
        raise HTTPException(status_code=403, detail="Access denied")
    elif current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Access denied")

    allowed_types = ["image/jpeg", "image/png", "image/gif", "image/webp", "application/pdf"]
    if file.content_type not in allowed_types:
        raise HTTPException(status_code=400, detail=f"File type not allowed. Allowed: {allowed_types}")

    max_size = 5 * 1024 * 1024
    content = await file.read()
    if len(content) > max_size:
        raise HTTPException(status_code=400, detail="File too large. Maximum 5MB")

    encoded = base64.b64encode(content).decode("utf-8")

    attachment = {
        "id": str(uuid.uuid4()),
        "filename": file.filename,
        "content_type": file.content_type,
        "size": len(content),
        "data": encoded,
        "uploaded_by": current_user["sub"],
        "uploaded_at": datetime.utcnow(),
    }

    await db.platform_tickets.update_one(
        {"id": ticket_id},
        {
            "$push": {"attachments": attachment},
            "$set": {"updated_at": datetime.utcnow()},
        }
    )

    attachment_info = {k: v for k, v in attachment.items() if k != "data"}
    return {"message": "File uploaded successfully", "attachment": attachment_info}
