"""
Worktable Service - API Views.
"""
import json
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError, PermissionDenied
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.core.tenant.middleware import get_current_tenant

from .models import (
    TableDefinition,
    TableColumn,
    TableRecord,
    SavedFilter,
    CustomView,
    RecordAuditLog,
    RecordStatus,
)
from .serializers import (
    TableDefinitionSerializer,
    TableDefinitionListSerializer,
    TableDefinitionCreateSerializer,
    TableStatsSerializer,
    TableColumnSerializer,
    TableColumnCreateSerializer,
    ColumnReorderSerializer,
    TableRecordSerializer,
    TableRecordListSerializer,
    TableRecordCreateSerializer,
    TableRecordUpdateSerializer,
    BulkCreateSerializer,
    BulkUpdateSerializer,
    BulkDeleteSerializer,
    BulkResultSerializer,
    SavedFilterSerializer,
    SavedFilterCreateSerializer,
    CustomViewSerializer,
    CustomViewCreateSerializer,
    RecordAuditLogSerializer,
    ExportSerializer,
    ImportSerializer,
)
from .services import (
    TableService,
    ColumnService,
    RecordService,
    FilterService,
    ViewService,
    ExportService,
    ImportService,
)


def get_tenant_from_request(request):
    """Get tenant from request or thread local."""
    tenant = getattr(request, 'tenant', None) or get_current_tenant()
    return tenant


def require_tenant(request):
    """Get tenant or raise ValidationError."""
    tenant = get_tenant_from_request(request)
    if tenant is None:
        raise ValidationError({'detail': 'Tenant not found'})
    return tenant


# ============================================================================
# Table ViewSet
# ============================================================================

class TableDefinitionViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing table definitions.
    
    list: List all tables
    create: Create a new table
    retrieve: Get table details with columns
    update: Update table
    partial_update: Partially update table
    destroy: Delete/deactivate table
    stats: Get table statistics
    """
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['name', 'description', 'slug']
    ordering_fields = ['name', 'order', 'created_at']
    ordering = ['order', 'name']
    lookup_field = 'slug'
    
    def get_queryset(self):
        tenant = get_tenant_from_request(self.request)
        if tenant is None:
            return TableDefinition.objects.none()
        
        queryset = TableDefinition.objects.filter(tenant=tenant)
        
        # Filter by active status
        if self.request.query_params.get('active') == 'true':
            queryset = queryset.filter(is_active=True)
        
        return queryset
    
    def get_serializer_class(self):
        if self.action == 'list':
            return TableDefinitionListSerializer
        if self.action == 'create':
            return TableDefinitionCreateSerializer
        return TableDefinitionSerializer
    
    def perform_create(self, serializer):
        tenant = require_tenant(self.request)
        serializer.save(tenant=tenant)
    
    def perform_destroy(self, instance):
        """Soft delete by default."""
        TableService.delete_table(instance, hard_delete=False)
    
    @action(detail=True, methods=['get'])
    def stats(self, request, slug=None):
        """Get table statistics."""
        table = self.get_object()
        stats = TableService.get_table_stats(table)
        serializer = TableStatsSerializer(stats)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def activate(self, request, slug=None):
        """Activate a table."""
        table = self.get_object()
        table.is_active = True
        table.save(update_fields=['is_active'])
        return Response({'status': 'activated'})
    
    @action(detail=True, methods=['post'])
    def deactivate(self, request, slug=None):
        """Deactivate a table."""
        table = self.get_object()
        table.is_active = False
        table.save(update_fields=['is_active'])
        return Response({'status': 'deactivated'})


# ============================================================================
# Column ViewSet
# ============================================================================

class TableColumnViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing table columns.
    
    Nested under tables: /tables/{table_slug}/columns/
    """
    serializer_class = TableColumnSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [OrderingFilter]
    ordering_fields = ['order', 'name', 'created_at']
    ordering = ['order']
    
    def get_table(self):
        """Get the parent table."""
        tenant = require_tenant(self.request)
        table_slug = self.kwargs.get('table_slug')
        return get_object_or_404(
            TableDefinition,
            tenant=tenant,
            slug=table_slug
        )
    
    def get_queryset(self):
        table = self.get_table()
        return table.columns.all()
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        if 'table_slug' in self.kwargs:
            context['table'] = self.get_table()
        return context
    
    def perform_create(self, serializer):
        table = self.get_table()
        # Get max order
        max_order = table.columns.count()
        serializer.save(table=table, order=max_order + 1)
    
    @action(detail=False, methods=['post'])
    def reorder(self, request, table_slug=None):
        """Reorder columns."""
        table = self.get_table()
        serializer = ColumnReorderSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        ColumnService.reorder_columns(table, serializer.validated_data['orders'])
        return Response({'status': 'reordered'})


# ============================================================================
# Record ViewSet
# ============================================================================

class TableRecordViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing table records.
    
    Nested under tables: /tables/{table_slug}/records/
    
    Supports:
    - Filtering: ?field=value or ?field[operator]=value
    - Searching: ?search=term
    - Sorting: ?sort=field:asc,field2:desc
    - Pagination: ?page=1&page_size=20
    """
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    ordering_fields = ['created_at', 'updated_at']
    ordering = ['-created_at']
    
    def get_table(self):
        """Get the parent table."""
        tenant = require_tenant(self.request)
        table_slug = self.kwargs.get('table_slug')
        return get_object_or_404(
            TableDefinition,
            tenant=tenant,
            slug=table_slug,
            is_active=True
        )
    
    def get_queryset(self):
        table = self.get_table()
        queryset = table.records.filter(is_deleted=False).select_related('owner')
        
        # Apply custom filters
        filters = self._parse_filters()
        if filters:
            queryset = FilterService.apply_filters(queryset, filters, table)
        
        # Apply search
        search = self.request.query_params.get('search')
        if search:
            queryset = FilterService.apply_search(queryset, search, table)
        
        # Apply sorting
        sort = self._parse_sort()
        if sort:
            queryset = FilterService.apply_sort(queryset, sort)
        
        # Filter by status
        status_param = self.request.query_params.get('status')
        if status_param:
            queryset = queryset.filter(status=status_param)
        
        # Include deleted
        if self.request.query_params.get('include_deleted') == 'true':
            queryset = table.records.select_related('owner')
        
        return queryset
    
    def _parse_filters(self):
        """Parse filter parameters from query string."""
        filters = {}
        for key, value in self.request.query_params.items():
            if key.startswith('filter[') and key.endswith(']'):
                # filter[field][operator]=value
                parts = key[7:-1].split('][')
                if len(parts) == 1:
                    filters[parts[0]] = value
                elif len(parts) == 2:
                    field, operator = parts
                    if field not in filters:
                        filters[field] = {}
                    filters[field][operator] = value
        return filters
    
    def _parse_sort(self):
        """Parse sort parameter."""
        sort_param = self.request.query_params.get('sort')
        if not sort_param:
            return None
        
        sort = []
        for item in sort_param.split(','):
            if ':' in item:
                field, order = item.split(':')
            else:
                field, order = item, 'asc'
            sort.append({'field': field, 'order': order})
        
        return sort
    
    def get_serializer_class(self):
        if self.action == 'list':
            return TableRecordListSerializer
        if self.action == 'create':
            return TableRecordCreateSerializer
        if self.action in ('update', 'partial_update'):
            return TableRecordUpdateSerializer
        return TableRecordSerializer
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        if 'table_slug' in self.kwargs:
            context['table'] = self.get_table()
        return context
    
    def perform_create(self, serializer):
        table = self.get_table()
        record = RecordService.create_record(
            table=table,
            data=serializer.validated_data['data'],
            owner=self.request.user,
            status=serializer.validated_data.get('status', RecordStatus.DRAFT),
            request=self.request,
        )
        serializer.instance = record
    
    def update(self, request, *args, **kwargs):
        """Override update to use proper response serializer."""
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        
        # Validate input
        serializer = self.get_serializer(data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        
        # Perform update
        updated_record = RecordService.update_record(
            record=instance,
            data=serializer.validated_data['data'],
            partial=True,
            request=request,
        )
        
        # Update status if provided
        if 'status' in serializer.validated_data:
            updated_record.status = serializer.validated_data['status']
            updated_record.save(update_fields=['status'])
        
        # Return with proper serializer
        response_serializer = TableRecordSerializer(updated_record)
        return Response(response_serializer.data)
    
    def perform_update(self, serializer):
        # Not used, update() handles everything
        pass
    
    def perform_destroy(self, instance):
        """Soft delete by default."""
        RecordService.delete_record(instance, hard_delete=False, request=self.request)
    
    @action(detail=True, methods=['post'])
    def restore(self, request, table_slug=None, pk=None):
        """Restore a soft-deleted record."""
        # Get including deleted
        table = self.get_table()
        record = get_object_or_404(TableRecord, table=table, pk=pk, is_deleted=True)
        RecordService.restore_record(record, request=request)
        serializer = TableRecordSerializer(record)
        return Response(serializer.data)
    
    @action(detail=False, methods=['post'])
    def bulk_create(self, request, table_slug=None):
        """Create multiple records at once."""
        table = self.get_table()
        serializer = BulkCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        created, errors = RecordService.bulk_create(
            table=table,
            data_list=serializer.validated_data['records'],
            owner=request.user,
            request=request,
        )
        
        result = BulkResultSerializer({
            'success_count': len(created),
            'error_count': len(errors),
            'errors': errors,
        })
        
        return Response(result.data, status=status.HTTP_201_CREATED)
    
    @action(detail=False, methods=['post'])
    def bulk_update(self, request, table_slug=None):
        """Update multiple records at once."""
        table = self.get_table()
        serializer = BulkUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        updated_count, errors = RecordService.bulk_update(
            table=table,
            updates=serializer.validated_data['updates'],
            user=request.user,
            request=request,
        )
        
        result = BulkResultSerializer({
            'success_count': updated_count,
            'error_count': len(errors),
            'errors': errors,
        })
        
        return Response(result.data)
    
    @action(detail=False, methods=['post'])
    def bulk_delete(self, request, table_slug=None):
        """Delete multiple records at once."""
        table = self.get_table()
        serializer = BulkDeleteSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        count = RecordService.bulk_delete(
            table=table,
            record_ids=serializer.validated_data['ids'],
            hard_delete=serializer.validated_data.get('hard_delete', False),
            user=request.user,
            request=request,
        )
        
        return Response({
            'deleted_count': count,
        })
    
    @action(detail=False, methods=['post'])
    def export(self, request, table_slug=None):
        """Export records."""
        table = self.get_table()
        serializer = ExportSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # Get filtered queryset
        queryset = self.get_queryset()
        records = list(queryset)
        
        format_type = serializer.validated_data.get('format', 'csv')
        columns = serializer.validated_data.get('columns')
        
        if format_type == 'csv':
            content = ExportService.export_csv(table, records, columns)
            response = HttpResponse(content, content_type='text/csv')
            response['Content-Disposition'] = f'attachment; filename="{table.slug}.csv"'
            return response
        else:
            data = ExportService.export_json(table, records, columns)
            return Response(data)
    
    @action(detail=False, methods=['post'])
    def import_data(self, request, table_slug=None):
        """Import records from file."""
        table = self.get_table()
        serializer = ImportSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        file = serializer.validated_data['file']
        content = file.read().decode('utf-8')
        column_mapping = serializer.validated_data.get('column_mapping')
        
        created, errors = ImportService.import_csv(
            table=table,
            csv_content=content,
            user=request.user,
            column_mapping=column_mapping,
        )
        
        result = BulkResultSerializer({
            'success_count': len(created),
            'error_count': len(errors),
            'errors': errors,
        })
        
        return Response(result.data, status=status.HTTP_201_CREATED)


# ============================================================================
# Filter ViewSet
# ============================================================================

class SavedFilterViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing saved filters.
    
    Nested under tables: /tables/{table_slug}/filters/
    """
    serializer_class = SavedFilterSerializer
    permission_classes = [IsAuthenticated]
    ordering = ['order', 'name']
    
    def get_table(self):
        """Get the parent table."""
        tenant = require_tenant(self.request)
        table_slug = self.kwargs.get('table_slug')
        return get_object_or_404(
            TableDefinition,
            tenant=tenant,
            slug=table_slug
        )
    
    def get_queryset(self):
        table = self.get_table()
        user = self.request.user
        # Return user's filters + shared filters
        return SavedFilter.objects.filter(
            table=table
        ).filter(
            models.Q(user=user) | models.Q(is_shared=True)
        ).distinct()
    
    def get_serializer_class(self):
        if self.action == 'create':
            return SavedFilterCreateSerializer
        return SavedFilterSerializer
    
    def perform_create(self, serializer):
        table = self.get_table()
        ViewService.save_filter(
            table=table,
            user=self.request.user,
            name=serializer.validated_data['name'],
            filter_config=serializer.validated_data['filters'],
            is_default=serializer.validated_data.get('is_default', False),
            is_shared=serializer.validated_data.get('is_shared', False),
        )
    
    def perform_destroy(self, instance):
        # Only allow deleting own filters
        if instance.user != self.request.user:
            raise PermissionDenied("Cannot delete another user's filter")
        instance.delete()


# ============================================================================
# View ViewSet
# ============================================================================

class CustomViewViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing custom views.
    
    Nested under tables: /tables/{table_slug}/views/
    """
    serializer_class = CustomViewSerializer
    permission_classes = [IsAuthenticated]
    ordering = ['order', 'name']
    
    def get_table(self):
        """Get the parent table."""
        tenant = require_tenant(self.request)
        table_slug = self.kwargs.get('table_slug')
        return get_object_or_404(
            TableDefinition,
            tenant=tenant,
            slug=table_slug
        )
    
    def get_queryset(self):
        table = self.get_table()
        user = self.request.user
        # Return user's views + shared views
        return CustomView.objects.filter(
            table=table
        ).filter(
            models.Q(user=user) | models.Q(is_shared=True)
        ).distinct()
    
    def get_serializer_class(self):
        if self.action == 'create':
            return CustomViewCreateSerializer
        return CustomViewSerializer
    
    def perform_create(self, serializer):
        table = self.get_table()
        ViewService.create_view(
            table=table,
            user=self.request.user,
            name=serializer.validated_data['name'],
            columns=serializer.validated_data.get('columns'),
            sort=serializer.validated_data.get('sort'),
            filters=serializer.validated_data.get('filters'),
            is_default=serializer.validated_data.get('is_default', False),
            is_shared=serializer.validated_data.get('is_shared', False),
        )
    
    def perform_destroy(self, instance):
        # Only allow deleting own views
        if instance.user != self.request.user:
            raise PermissionDenied("Cannot delete another user's view")
        instance.delete()


# ============================================================================
# Audit Log ViewSet
# ============================================================================

class RecordAuditLogViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Read-only ViewSet for audit logs.
    
    Nested under tables: /tables/{table_slug}/logs/
    Or under records: /tables/{table_slug}/records/{record_id}/logs/
    """
    serializer_class = RecordAuditLogSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_fields = ['action', 'user']
    ordering_fields = ['created_at']
    ordering = ['-created_at']
    
    def get_table(self):
        """Get the parent table."""
        tenant = require_tenant(self.request)
        table_slug = self.kwargs.get('table_slug')
        return get_object_or_404(
            TableDefinition,
            tenant=tenant,
            slug=table_slug
        )
    
    def get_queryset(self):
        table = self.get_table()
        queryset = RecordAuditLog.objects.filter(table=table).select_related('user')
        
        # Filter by record if specified
        record_id = self.kwargs.get('record_pk')
        if record_id:
            queryset = queryset.filter(record_id=record_id)
        
        return queryset


# Add missing import at module level
from django.db import models
