"""
Worktable GraphQL Queries.

Defines GraphQL query resolvers for tables, records, etc.
"""
import strawberry
from strawberry.types import Info
from typing import Optional, List
from uuid import UUID
from django.db.models import Q

from apps.core.tenant.middleware import get_current_tenant
from apps.services.worktable.models import (
    TableDefinition,
    TableColumn,
    TableRecord,
    SavedFilter,
    CustomView,
    RecordAuditLog,
)
from apps.services.worktable.services import FilterService

from .types import (
    TableDefinitionType,
    TableColumnType,
    TableRecordType,
    SavedFilterType,
    CustomViewType,
    AuditLogType,
    TableRecordConnection,
    TableDefinitionConnection,
    PageInfo,
    RecordFilterInput,
    SortInput,
)


def get_current_user(info: Info):
    """Get current authenticated user from request context."""
    request = info.context.get("request")
    if request and request.user and request.user.is_authenticated:
        return request.user
    return None


def get_tenant_from_context(info: Info):
    """Get tenant from request context."""
    request = info.context.get("request")
    if request:
        return getattr(request, 'tenant', None) or get_current_tenant()
    return get_current_tenant()


@strawberry.type
class WorktableQuery:
    """Worktable GraphQL queries."""
    
    @strawberry.field
    def tables(
        self,
        info: Info,
        active_only: bool = True,
        search: Optional[str] = None,
    ) -> List[TableDefinitionType]:
        """
        Get all tables for the current tenant.
        
        Args:
            active_only: If True, only return active tables
            search: Optional search term for name/description
        """
        tenant = get_tenant_from_context(info)
        if not tenant:
            return []
        
        queryset = TableDefinition.objects.filter(tenant=tenant)
        
        if active_only:
            queryset = queryset.filter(is_active=True)
        
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) | Q(description__icontains=search)
            )
        
        return [TableDefinitionType.from_model(t) for t in queryset]
    
    @strawberry.field
    def table(
        self,
        info: Info,
        slug: str,
    ) -> Optional[TableDefinitionType]:
        """
        Get a specific table by slug.
        
        Args:
            slug: Table slug
        """
        tenant = get_tenant_from_context(info)
        if not tenant:
            return None
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=slug)
            return TableDefinitionType.from_model(table)
        except TableDefinition.DoesNotExist:
            return None
    
    @strawberry.field
    def table_columns(
        self,
        info: Info,
        table_slug: str,
    ) -> List[TableColumnType]:
        """
        Get all columns for a table.
        
        Args:
            table_slug: Table slug
        """
        tenant = get_tenant_from_context(info)
        if not tenant:
            return []
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=table_slug)
            return [TableColumnType.from_model(c) for c in table.columns.all()]
        except TableDefinition.DoesNotExist:
            return []
    
    @strawberry.field
    def records(
        self,
        info: Info,
        table_slug: str,
        filters: Optional[RecordFilterInput] = None,
        sort: Optional[List[SortInput]] = None,
        page: int = 1,
        page_size: int = 20,
    ) -> TableRecordConnection:
        """
        Get paginated records for a table.
        
        Args:
            table_slug: Table slug
            filters: Optional filter conditions
            sort: Optional sorting rules
            page: Page number (1-indexed)
            page_size: Records per page
        """
        tenant = get_tenant_from_context(info)
        if not tenant:
            return TableRecordConnection(
                page_info=PageInfo(
                    has_next_page=False,
                    has_previous_page=False,
                    total_count=0,
                    page=page,
                    page_size=page_size,
                    total_pages=0,
                ),
                nodes=[],
            )
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=table_slug)
        except TableDefinition.DoesNotExist:
            return TableRecordConnection(
                page_info=PageInfo(
                    has_next_page=False,
                    has_previous_page=False,
                    total_count=0,
                    page=page,
                    page_size=page_size,
                    total_pages=0,
                ),
                nodes=[],
            )
        
        queryset = TableRecord.objects.filter(
            tenant=tenant,
            table=table,
            is_deleted=False,
        )
        
        # Apply filters
        if filters:
            if filters.status:
                queryset = queryset.filter(status=filters.status.value)
            
            if filters.owner_id:
                queryset = queryset.filter(owner_id=filters.owner_id)
            
            if filters.search:
                # Search in JSONField data
                queryset = queryset.filter(data__icontains=filters.search)
            
            if filters.conditions:
                for condition in filters.conditions:
                    q = FilterService.build_condition(
                        f"data__{condition.field}",
                        condition.operator,
                        condition.value,
                    )
                    if q:
                        queryset = queryset.filter(q)
        
        # Apply sorting
        if sort:
            ordering = []
            for s in sort:
                prefix = "-" if s.order == "desc" else ""
                ordering.append(f"{prefix}data__{s.field}")
            if ordering:
                queryset = queryset.order_by(*ordering)
        else:
            queryset = queryset.order_by('-created_at')
        
        # Pagination
        total_count = queryset.count()
        total_pages = (total_count + page_size - 1) // page_size
        offset = (page - 1) * page_size
        records = queryset[offset:offset + page_size]
        
        return TableRecordConnection(
            page_info=PageInfo(
                has_next_page=page < total_pages,
                has_previous_page=page > 1,
                total_count=total_count,
                page=page,
                page_size=page_size,
                total_pages=total_pages,
            ),
            nodes=[TableRecordType.from_model(r) for r in records],
        )
    
    @strawberry.field
    def record(
        self,
        info: Info,
        table_slug: str,
        record_id: UUID,
    ) -> Optional[TableRecordType]:
        """
        Get a specific record.
        
        Args:
            table_slug: Table slug
            record_id: Record UUID
        """
        tenant = get_tenant_from_context(info)
        if not tenant:
            return None
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=table_slug)
            record = TableRecord.objects.get(
                id=record_id,
                table=table,
                is_deleted=False,
            )
            return TableRecordType.from_model(record)
        except (TableDefinition.DoesNotExist, TableRecord.DoesNotExist):
            return None
    
    @strawberry.field
    def saved_filters(
        self,
        info: Info,
        table_slug: str,
    ) -> List[SavedFilterType]:
        """
        Get saved filters for a table (user's + shared).
        
        Args:
            table_slug: Table slug
        """
        tenant = get_tenant_from_context(info)
        user = get_current_user(info)
        if not tenant or not user:
            return []
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=table_slug)
            filters = SavedFilter.objects.filter(table=table).filter(
                Q(user=user) | Q(is_shared=True)
            )
            return [SavedFilterType.from_model(f) for f in filters]
        except TableDefinition.DoesNotExist:
            return []
    
    @strawberry.field
    def custom_views(
        self,
        info: Info,
        table_slug: str,
    ) -> List[CustomViewType]:
        """
        Get custom views for a table (user's + shared).
        
        Args:
            table_slug: Table slug
        """
        tenant = get_tenant_from_context(info)
        user = get_current_user(info)
        if not tenant or not user:
            return []
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=table_slug)
            views = CustomView.objects.filter(table=table).filter(
                Q(user=user) | Q(is_shared=True)
            )
            return [CustomViewType.from_model(v) for v in views]
        except TableDefinition.DoesNotExist:
            return []
    
    @strawberry.field
    def record_audit_logs(
        self,
        info: Info,
        table_slug: str,
        record_id: Optional[UUID] = None,
        page: int = 1,
        page_size: int = 50,
    ) -> List[AuditLogType]:
        """
        Get audit logs for a table or specific record.
        
        Args:
            table_slug: Table slug
            record_id: Optional record UUID (if None, return all table logs)
            page: Page number
            page_size: Logs per page
        """
        tenant = get_tenant_from_context(info)
        if not tenant:
            return []
        
        try:
            table = TableDefinition.objects.get(tenant=tenant, slug=table_slug)
            queryset = RecordAuditLog.objects.filter(table=table)
            
            if record_id:
                queryset = queryset.filter(record_id=record_id)
            
            offset = (page - 1) * page_size
            logs = queryset.order_by('-created_at')[offset:offset + page_size]
            return [AuditLogType.from_model(log) for log in logs]
        except TableDefinition.DoesNotExist:
            return []
