"""
Organization Views - API views for organizational units management.
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.db.models import Q
from django.shortcuts import get_object_or_404

from .models import OrganizationalUnit, UserOrganizationalUnit, OrganizationalUnitType, Company, BusinessPartner
from .serializers import (
    OrganizationalUnitSerializer,
    OrganizationalUnitCreateSerializer,
    OrganizationalUnitTreeSerializer,
    UserOrganizationalUnitSerializer,
    OrganizationalUnitAssignmentSerializer,
    OrganizationalUnitBulkAssignmentSerializer,
    CompanySerializer,
    CompanyCreateSerializer,
    BusinessPartnerSerializer,
    BusinessPartnerCreateSerializer,
)
from apps.core.permission.services import PermissionService


class OrganizationalUnitViewSet(viewsets.ModelViewSet):
    """
    API endpoint for managing organizational units.
    
    list: Get all organizational units (flat list)
    retrieve: Get a specific organizational unit
    create: Create a new organizational unit
    update: Update an organizational unit
    partial_update: Partially update an organizational unit
    destroy: Delete an organizational unit
    
    Custom actions:
    - tree: Get organizational units as a tree structure
    - types: Get available organizational unit types
    - children: Get children of a specific unit
    - ancestors: Get ancestors of a specific unit
    - members: Get/manage members of a unit
    """
    
    serializer_class = OrganizationalUnitSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """
        Get queryset filtered by user's permissions.
        """
        user = self.request.user
        queryset = OrganizationalUnit.objects.all()
        
        # Apply data scope filtering
        if not user.is_superuser:
            accessible_units = PermissionService.get_user_org_units(user)
            if accessible_units:
                # Include units and all their ancestors
                all_ids = set(accessible_units)
                for unit in OrganizationalUnit.objects.filter(id__in=accessible_units):
                    if unit.path:
                        all_ids.update(int(x) for x in unit.path.split('/') if x.isdigit())
                queryset = queryset.filter(id__in=all_ids)
        
        # Filter by query params
        unit_type = self.request.query_params.get('type')
        if unit_type:
            queryset = queryset.filter(unit_type=unit_type)
        
        is_active = self.request.query_params.get('is_active')
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        parent_id = self.request.query_params.get('parent_id')
        if parent_id:
            if parent_id == 'null':
                queryset = queryset.filter(parent__isnull=True)
            else:
                queryset = queryset.filter(parent_id=parent_id)
        
        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) | Q(code__icontains=search)
            )
        
        return queryset.select_related('parent').order_by('level', 'name')
    
    def get_serializer_class(self):
        """Get appropriate serializer based on action."""
        if self.action in ['create', 'update', 'partial_update']:
            return OrganizationalUnitCreateSerializer
        if self.action == 'tree':
            return OrganizationalUnitTreeSerializer
        return OrganizationalUnitSerializer
    
    def perform_create(self, serializer):
        """Create organizational unit."""
        serializer.save()
    
    def perform_destroy(self, instance):
        """
        Delete organizational unit.
        Can either soft delete (deactivate) or cascade delete children.
        """
        cascade = self.request.query_params.get('cascade', 'false').lower() == 'true'
        
        if cascade:
            # Delete all descendants
            descendants = instance.get_descendants()
            for desc in descendants:
                desc.delete()
            instance.delete()
        else:
            # Soft delete (deactivate)
            instance.is_active = False
            instance.save()
    
    @action(detail=False, methods=['get'])
    def tree(self, request):
        """
        Get organizational units as a tree structure.
        Returns only root units with nested children.
        """
        # Get root units (no parent)
        roots = self.get_queryset().filter(
            parent__isnull=True,
            is_active=True
        ).order_by('name')
        
        serializer = OrganizationalUnitTreeSerializer(roots, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def types(self, request):
        """Get available organizational unit types."""
        types = [
            {
                'value': choice[0],
                'label': choice[1],
            }
            for choice in OrganizationalUnitType.choices
        ]
        return Response(types)
    
    @action(detail=True, methods=['get'])
    def children(self, request, pk=None):
        """Get direct children of an organizational unit."""
        unit = self.get_object()
        children = unit.children.filter(is_active=True).order_by('name')
        serializer = OrganizationalUnitSerializer(children, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get'])
    def descendants(self, request, pk=None):
        """Get all descendants (children, grandchildren, etc.) of a unit."""
        unit = self.get_object()
        descendants = unit.get_descendants()
        serializer = OrganizationalUnitSerializer(descendants, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get'])
    def ancestors(self, request, pk=None):
        """Get all ancestors (parent, grandparent, etc.) of a unit."""
        unit = self.get_object()
        ancestors = unit.get_ancestors()
        serializer = OrganizationalUnitSerializer(ancestors, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get', 'post', 'delete'])
    def members(self, request, pk=None):
        """
        Get/manage members of an organizational unit.
        
        GET: List all members
        POST: Add member(s) to unit
        DELETE: Remove member(s) from unit
        """
        unit = self.get_object()
        
        if request.method == 'GET':
            members = UserOrganizationalUnit.objects.filter(
                organizational_unit=unit
            ).select_related('user').order_by('-is_primary', 'user__first_name')
            serializer = UserOrganizationalUnitSerializer(members, many=True)
            return Response(serializer.data)
        
        elif request.method == 'POST':
            # Add members
            if isinstance(request.data, list):
                # Bulk add
                results = []
                for item in request.data:
                    item['organizational_unit_id'] = unit.id
                    serializer = OrganizationalUnitAssignmentSerializer(data=item)
                    if serializer.is_valid():
                        membership, created = UserOrganizationalUnit.objects.update_or_create(
                            user_id=serializer.validated_data['user_id'],
                            organizational_unit=unit,
                            defaults={
                                'is_primary': serializer.validated_data.get('is_primary', False),
                                'is_manager': serializer.validated_data.get('is_manager', False),
                                'start_date': serializer.validated_data.get('start_date'),
                                'end_date': serializer.validated_data.get('end_date'),
                            }
                        )
                        results.append({
                            'user_id': str(serializer.validated_data['user_id']),
                            'created': created
                        })
                return Response(results, status=status.HTTP_201_CREATED)
            else:
                # Single add
                serializer = OrganizationalUnitAssignmentSerializer(data={
                    **request.data,
                    'organizational_unit_id': unit.id
                })
                serializer.is_valid(raise_exception=True)
                
                membership, created = UserOrganizationalUnit.objects.update_or_create(
                    user_id=serializer.validated_data['user_id'],
                    organizational_unit=unit,
                    defaults={
                        'is_primary': serializer.validated_data.get('is_primary', False),
                        'is_manager': serializer.validated_data.get('is_manager', False),
                        'start_date': serializer.validated_data.get('start_date'),
                        'end_date': serializer.validated_data.get('end_date'),
                    }
                )
                return Response(
                    UserOrganizationalUnitSerializer(membership).data,
                    status=status.HTTP_201_CREATED if created else status.HTTP_200_OK
                )
        
        elif request.method == 'DELETE':
            # Remove members
            user_ids = request.data.get('user_ids', [])
            if not user_ids:
                user_id = request.data.get('user_id')
                if user_id:
                    user_ids = [user_id]
            
            if not user_ids:
                return Response(
                    {'error': 'user_id or user_ids required'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            deleted_count, _ = UserOrganizationalUnit.objects.filter(
                organizational_unit=unit,
                user_id__in=user_ids
            ).delete()
            
            return Response({'deleted_count': deleted_count})


class UserOrganizationalUnitViewSet(viewsets.ModelViewSet):
    """
    API endpoint for managing user organizational unit assignments.
    """
    
    serializer_class = UserOrganizationalUnitSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """Get user organizational unit assignments."""
        queryset = UserOrganizationalUnit.objects.select_related(
            'user', 'organizational_unit'
        )
        
        # Filter by user
        user_id = self.request.query_params.get('user_id')
        if user_id:
            queryset = queryset.filter(user_id=user_id)
        
        # Filter by org unit
        org_unit_id = self.request.query_params.get('org_unit_id')
        if org_unit_id:
            queryset = queryset.filter(organizational_unit_id=org_unit_id)
        
        # Filter by primary
        is_primary = self.request.query_params.get('is_primary')
        if is_primary is not None:
            queryset = queryset.filter(is_primary=is_primary.lower() == 'true')
        
        return queryset.order_by('-is_primary', 'organizational_unit__name')
    
    @action(detail=False, methods=['get'])
    def my_units(self, request):
        """Get current user's organizational unit memberships."""
        memberships = UserOrganizationalUnit.objects.filter(
            user=request.user
        ).select_related('organizational_unit').order_by('-is_primary', 'organizational_unit__name')
        
        serializer = UserOrganizationalUnitSerializer(memberships, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['post'])
    def set_primary(self, request):
        """Set a specific unit as user's primary unit."""
        user_id = request.data.get('user_id', request.user.id)
        org_unit_id = request.data.get('org_unit_id')
        
        if not org_unit_id:
            return Response(
                {'error': 'org_unit_id required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Reset all to non-primary
        UserOrganizationalUnit.objects.filter(
            user_id=user_id
        ).update(is_primary=False)
        
        # Set new primary
        updated = UserOrganizationalUnit.objects.filter(
            user_id=user_id,
            organizational_unit_id=org_unit_id
        ).update(is_primary=True)
        
        if not updated:
            return Response(
                {'error': 'User is not a member of this organizational unit'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        return Response({'success': True})


# ─── Company ──────────────────────────────────────────────────────────────


class CompanyViewSet(viewsets.ModelViewSet):
    """CRUD شرکت‌ها."""

    serializer_class = CompanySerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        qs = Company.objects.select_related(
            "org_unit", "parent_company", "base_currency"
        )
        is_active = self.request.query_params.get("is_active")
        if is_active is not None:
            qs = qs.filter(is_active=is_active.lower() == "true")
        search = self.request.query_params.get("search")
        if search:
            qs = qs.filter(
                Q(name__icontains=search)
                | Q(name_en__icontains=search)
                | Q(code__icontains=search)
            )
        return qs.order_by("name")

    def get_serializer_class(self):
        if self.action in ("create", "update", "partial_update"):
            return CompanyCreateSerializer
        return CompanySerializer


# ─── Business Partner ─────────────────────────────────────────────────────


class BusinessPartnerViewSet(viewsets.ModelViewSet):
    """CRUD شرکای تجاری."""

    serializer_class = BusinessPartnerSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        qs = BusinessPartner.objects.select_related("company", "currency")
        is_active = self.request.query_params.get("is_active")
        if is_active is not None:
            qs = qs.filter(is_active=is_active.lower() == "true")
        partner_type = self.request.query_params.get("type")
        if partner_type:
            qs = qs.filter(partner_type=partner_type.upper())
        search = self.request.query_params.get("search")
        if search:
            qs = qs.filter(
                Q(name__icontains=search)
                | Q(name_en__icontains=search)
                | Q(code__icontains=search)
            )
        return qs.order_by("name")

    def get_serializer_class(self):
        if self.action in ("create", "update", "partial_update"):
            return BusinessPartnerCreateSerializer
        return BusinessPartnerSerializer

    @action(detail=False, methods=["get"])
    def customers(self, request):
        """فقط مشتریان."""
        qs = self.get_queryset().filter(
            partner_type__in=["CUSTOMER", "BOTH"]
        )
        return Response(
            BusinessPartnerSerializer(qs, many=True).data
        )

    @action(detail=False, methods=["get"])
    def vendors(self, request):
        """فقط تأمین‌کنندگان."""
        qs = self.get_queryset().filter(
            partner_type__in=["VENDOR", "BOTH"]
        )
        return Response(
            BusinessPartnerSerializer(qs, many=True).data
        )
