from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import Optional, List
from ..config.database import get_db
from ..middleware.auth import get_current_user, authorize_roles
from ..models.user import User
from ..models.guest_preference import GuestPreference
from ..models.guest_note import GuestNote
from ..models.guest_tag import GuestTag
from ..models.guest_communication import GuestCommunication, CommunicationType, CommunicationDirection
from ..models.guest_segment import GuestSegment
from ..services.guest_profile_service import GuestProfileService
from ..utils.role_helpers import is_customer
import json

router = APIRouter(prefix='/guest-profiles', tags=['guest-profiles'])

# Guest Search and List
@router.get('/')
async def search_guests(
    search: Optional[str] = Query(None),
    is_vip: Optional[bool] = Query(None),
    segment_id: Optional[int] = Query(None),
    min_lifetime_value: Optional[float] = Query(None),
    min_satisfaction_score: Optional[float] = Query(None),
    tag_id: Optional[int] = Query(None),
    page: int = Query(1, ge=1),
    limit: int = Query(10, ge=1, le=100),
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Search and filter guests"""
    try:
        result = GuestProfileService.search_guests(
            db=db,
            search=search,
            is_vip=is_vip,
            segment_id=segment_id,
            min_lifetime_value=min_lifetime_value,
            min_satisfaction_score=min_satisfaction_score,
            tag_id=tag_id,
            page=page,
            limit=limit
        )
        
        guests_data = []
        for guest in result['guests']:
            guest_dict = {
                'id': guest.id,
                'full_name': guest.full_name,
                'email': guest.email,
                'phone': guest.phone,
                'is_vip': guest.is_vip,
                'lifetime_value': float(guest.lifetime_value) if guest.lifetime_value else 0,
                'satisfaction_score': float(guest.satisfaction_score) if guest.satisfaction_score else None,
                'total_visits': guest.total_visits,
                'last_visit_date': guest.last_visit_date.isoformat() if guest.last_visit_date else None,
                'tags': [{'id': tag.id, 'name': tag.name, 'color': tag.color} for tag in guest.guest_tags],
                'segments': [{'id': seg.id, 'name': seg.name} for seg in guest.guest_segments]
            }
            guests_data.append(guest_dict)
        
        return {
            'status': 'success',
            'data': {
                'guests': guests_data,
                'pagination': {
                    'total': result['total'],
                    'page': result['page'],
                    'limit': result['limit'],
                    'total_pages': result['total_pages']
                }
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Get Guest Profile Details
@router.get('/{user_id}')
async def get_guest_profile(
    user_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get comprehensive guest profile"""
    try:
        # First check if user exists at all
        user = db.query(User).filter(User.id == user_id).first()
        if not user:
            raise HTTPException(status_code=404, detail=f'User with ID {user_id} not found')
        
        # Check if user is a customer
        from ..utils.role_helpers import is_customer
        if not is_customer(user, db):
            raise HTTPException(status_code=404, detail=f'User with ID {user_id} is not a guest (customer)')
        
        # Get analytics
        analytics = GuestProfileService.get_guest_analytics(user_id, db)
        
        # Get preferences
        preferences = db.query(GuestPreference).filter(GuestPreference.user_id == user_id).first()
        
        # Get notes
        notes = db.query(GuestNote).filter(GuestNote.user_id == user_id).order_by(GuestNote.created_at.desc()).all()
        
        # Get communications
        communications = db.query(GuestCommunication).filter(
            GuestCommunication.user_id == user_id
        ).order_by(GuestCommunication.created_at.desc()).limit(20).all()
        
        # Get booking history
        bookings = GuestProfileService.get_booking_history(user_id, db, limit=10)
        
        # Safely access relationships
        try:
            tags = [{'id': tag.id, 'name': tag.name, 'color': tag.color} for tag in (user.guest_tags or [])]
        except Exception:
            tags = []
        
        try:
            segments = [{'id': seg.id, 'name': seg.name, 'description': seg.description} for seg in (user.guest_segments or [])]
        except Exception:
            segments = []
        
        profile_data = {
            'id': user.id,
            'full_name': user.full_name,
            'email': user.email,
            'phone': user.phone,
            'address': user.address,
            'avatar': user.avatar,
            'is_vip': getattr(user, 'is_vip', False),
            'lifetime_value': float(user.lifetime_value) if hasattr(user, 'lifetime_value') and user.lifetime_value else 0,
            'satisfaction_score': float(user.satisfaction_score) if hasattr(user, 'satisfaction_score') and user.satisfaction_score else None,
            'total_visits': getattr(user, 'total_visits', 0),
            'last_visit_date': user.last_visit_date.isoformat() if hasattr(user, 'last_visit_date') and user.last_visit_date else None,
            'created_at': user.created_at.isoformat() if user.created_at else None,
            'analytics': analytics,
            'preferences': {
                'preferred_room_location': preferences.preferred_room_location if preferences else None,
                'preferred_floor': preferences.preferred_floor if preferences else None,
                'preferred_amenities': preferences.preferred_amenities if preferences else None,
                'special_requests': preferences.special_requests if preferences else None,
                'preferred_contact_method': preferences.preferred_contact_method if preferences else None,
                'dietary_restrictions': preferences.dietary_restrictions if preferences else None,
            } if preferences else None,
            'tags': tags,
            'segments': segments,
            'notes': [{
                'id': note.id,
                'note': note.note,
                'is_important': note.is_important,
                'is_private': note.is_private,
                'created_by': note.creator.full_name if note.creator else None,
                'created_at': note.created_at.isoformat() if note.created_at else None
            } for note in notes],
            'communications': [{
                'id': comm.id,
                'communication_type': comm.communication_type.value,
                'direction': comm.direction.value,
                'subject': comm.subject,
                'content': comm.content,
                'staff_name': comm.staff.full_name if comm.staff else None,
                'created_at': comm.created_at.isoformat() if comm.created_at else None
            } for comm in communications],
            'recent_bookings': [{
                'id': booking.id,
                'booking_number': booking.booking_number,
                'check_in_date': booking.check_in_date.isoformat() if booking.check_in_date else None,
                'check_out_date': booking.check_out_date.isoformat() if booking.check_out_date else None,
                'status': booking.status.value if hasattr(booking.status, 'value') else str(booking.status),
                'total_price': float(booking.total_price) if booking.total_price else 0
            } for booking in bookings]
        }
        
        return {'status': 'success', 'data': {'profile': profile_data}}
    except HTTPException:
        raise
    except Exception as e:
        import traceback
        error_detail = f'Error fetching guest profile: {str(e)}\n{traceback.format_exc()}'
        raise HTTPException(status_code=500, detail=error_detail)

# Update Guest Preferences
@router.put('/{user_id}/preferences')
async def update_guest_preferences(
    user_id: int,
    preferences_data: dict,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Update guest preferences"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        preferences = db.query(GuestPreference).filter(GuestPreference.user_id == user_id).first()
        
        if not preferences:
            preferences = GuestPreference(user_id=user_id)
            db.add(preferences)
        
        if 'preferred_room_location' in preferences_data:
            preferences.preferred_room_location = preferences_data['preferred_room_location']
        if 'preferred_floor' in preferences_data:
            preferences.preferred_floor = preferences_data['preferred_floor']
        if 'preferred_room_type_id' in preferences_data:
            preferences.preferred_room_type_id = preferences_data['preferred_room_type_id']
        if 'preferred_amenities' in preferences_data:
            preferences.preferred_amenities = preferences_data['preferred_amenities']
        if 'special_requests' in preferences_data:
            preferences.special_requests = preferences_data['special_requests']
        if 'preferred_services' in preferences_data:
            preferences.preferred_services = preferences_data['preferred_services']
        if 'preferred_contact_method' in preferences_data:
            preferences.preferred_contact_method = preferences_data['preferred_contact_method']
        if 'preferred_language' in preferences_data:
            preferences.preferred_language = preferences_data['preferred_language']
        if 'dietary_restrictions' in preferences_data:
            preferences.dietary_restrictions = preferences_data['dietary_restrictions']
        if 'additional_preferences' in preferences_data:
            preferences.additional_preferences = preferences_data['additional_preferences']
        
        db.commit()
        db.refresh(preferences)
        
        return {'status': 'success', 'message': 'Preferences updated successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Create Guest Note
@router.post('/{user_id}/notes')
async def create_guest_note(
    user_id: int,
    note_data: dict,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Create a note for a guest"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        note = GuestNote(
            user_id=user_id,
            created_by=current_user.id,
            note=note_data.get('note'),
            is_important=note_data.get('is_important', False),
            is_private=note_data.get('is_private', False)
        )
        db.add(note)
        db.commit()
        db.refresh(note)
        
        return {'status': 'success', 'message': 'Note created successfully', 'data': {'note': {
            'id': note.id,
            'note': note.note,
            'is_important': note.is_important,
            'is_private': note.is_private,
            'created_at': note.created_at.isoformat() if note.created_at else None
        }}}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Delete Guest Note
@router.delete('/{user_id}/notes/{note_id}')
async def delete_guest_note(
    user_id: int,
    note_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Delete a guest note"""
    try:
        note = db.query(GuestNote).filter(GuestNote.id == note_id, GuestNote.user_id == user_id).first()
        if not note:
            raise HTTPException(status_code=404, detail='Note not found')
        
        db.delete(note)
        db.commit()
        
        return {'status': 'success', 'message': 'Note deleted successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Toggle VIP Status
@router.put('/{user_id}/vip-status')
async def toggle_vip_status(
    user_id: int,
    vip_data: dict,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Toggle VIP status for a guest"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        user.is_vip = vip_data.get('is_vip', False)
        db.commit()
        db.refresh(user)
        
        return {'status': 'success', 'message': 'VIP status updated successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Add Tag to Guest
@router.post('/{user_id}/tags')
async def add_tag_to_guest(
    user_id: int,
    tag_data: dict,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Add a tag to a guest"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        tag_id = tag_data.get('tag_id')
        tag = db.query(GuestTag).filter(GuestTag.id == tag_id).first()
        if not tag:
            raise HTTPException(status_code=404, detail='Tag not found')
        
        if tag not in user.guest_tags:
            user.guest_tags.append(tag)
            db.commit()
        
        return {'status': 'success', 'message': 'Tag added successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Remove Tag from Guest
@router.delete('/{user_id}/tags/{tag_id}')
async def remove_tag_from_guest(
    user_id: int,
    tag_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Remove a tag from a guest"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        tag = db.query(GuestTag).filter(GuestTag.id == tag_id).first()
        if not tag:
            raise HTTPException(status_code=404, detail='Tag not found')
        
        if tag in user.guest_tags:
            user.guest_tags.remove(tag)
            db.commit()
        
        return {'status': 'success', 'message': 'Tag removed successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Create Communication Record
@router.post('/{user_id}/communications')
async def create_communication(
    user_id: int,
    communication_data: dict,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Create a communication record"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        comm = GuestCommunication(
            user_id=user_id,
            staff_id=current_user.id,
            communication_type=CommunicationType(communication_data.get('communication_type')),
            direction=CommunicationDirection(communication_data.get('direction')),
            subject=communication_data.get('subject'),
            content=communication_data.get('content'),
            booking_id=communication_data.get('booking_id'),
            is_automated=communication_data.get('is_automated', False)
        )
        db.add(comm)
        db.commit()
        db.refresh(comm)
        
        return {'status': 'success', 'message': 'Communication recorded successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Get Guest Analytics
@router.get('/{user_id}/analytics')
async def get_guest_analytics(
    user_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get guest analytics"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        analytics = GuestProfileService.get_guest_analytics(user_id, db)
        
        return {'status': 'success', 'data': {'analytics': analytics}}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Update Guest Metrics
@router.post('/{user_id}/update-metrics')
async def update_guest_metrics(
    user_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Update guest metrics (lifetime value, satisfaction score, etc.)"""
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user or not is_customer(user, db):
            raise HTTPException(status_code=404, detail='Guest not found')
        
        metrics = GuestProfileService.update_guest_metrics(user_id, db)
        
        return {'status': 'success', 'message': 'Metrics updated successfully', 'data': {'metrics': metrics}}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Tag Management Routes
@router.get('/tags/all')
async def get_all_tags(
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get all available tags"""
    try:
        tags = db.query(GuestTag).all()
        tags_data = [{
            'id': tag.id,
            'name': tag.name,
            'color': tag.color,
            'description': tag.description
        } for tag in tags]
        
        return {'status': 'success', 'data': {'tags': tags_data}}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/tags')
async def create_tag(
    tag_data: dict,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Create a new tag"""
    try:
        tag = GuestTag(
            name=tag_data.get('name'),
            color=tag_data.get('color', '#3B82F6'),
            description=tag_data.get('description')
        )
        db.add(tag)
        db.commit()
        db.refresh(tag)
        
        return {'status': 'success', 'message': 'Tag created successfully', 'data': {'tag': {
            'id': tag.id,
            'name': tag.name,
            'color': tag.color,
            'description': tag.description
        }}}
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Segment Management Routes
@router.get('/segments/all')
async def get_all_segments(
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get all available segments"""
    try:
        segments = db.query(GuestSegment).filter(GuestSegment.is_active == True).all()
        segments_data = [{
            'id': seg.id,
            'name': seg.name,
            'description': seg.description,
            'criteria': seg.criteria
        } for seg in segments]
        
        return {'status': 'success', 'data': {'segments': segments_data}}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/{user_id}/segments')
async def assign_segment(
    user_id: int,
    segment_data: dict,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Assign a guest to a segment"""
    try:
        segment_id = segment_data.get('segment_id')
        success = GuestProfileService.assign_segment(user_id, segment_id, db)
        
        if not success:
            raise HTTPException(status_code=404, detail='Guest or segment not found')
        
        return {'status': 'success', 'message': 'Segment assigned successfully'}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/{user_id}/segments/{segment_id}')
async def remove_segment(
    user_id: int,
    segment_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Remove a guest from a segment"""
    try:
        success = GuestProfileService.remove_segment(user_id, segment_id, db)
        
        if not success:
            raise HTTPException(status_code=404, detail='Guest or segment not found')
        
        return {'status': 'success', 'message': 'Segment removed successfully'}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

