"""
库存变动记录列表查询视图
"""

from rest_framework import status, views
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from datetime import datetime, timedelta
import logging

from stock import models as stock_models
from drf_spectacular.utils import extend_schema, OpenApiParameter
from drf_spectacular.types import OpenApiTypes

from .mixins import StockChangeViewMixin

logger = logging.getLogger(__name__)


class ListStockChangesView(StockChangeViewMixin, views.APIView):
    """获取库存变动记录列表"""
    
    permission_classes = [IsAuthenticated]
    
    @extend_schema(
        tags=['读取出入库列表'],
        parameters=[
            OpenApiParameter(name='start', type=OpenApiTypes.DATE, description='开始日期 (YYYY-MM-DD)，默认为昨天'),
            OpenApiParameter(name='end', type=OpenApiTypes.DATE, description='结束日期 (YYYY-MM-DD)，默认为昨天'),
            OpenApiParameter(name='type', type=OpenApiTypes.INT, description='变动类型 (1=入库, 2=出库)'),
            OpenApiParameter(name='source_type', type=OpenApiTypes.INT, description='来源类型 (如采购=1)'),
            OpenApiParameter(name='source_id', type=OpenApiTypes.INT, description='来源业务单据ID'),
            OpenApiParameter(name='source_id_isnull', type=OpenApiTypes.BOOL, description='来源业务单据ID是否为空'),
            OpenApiParameter(name='warehouse', type=OpenApiTypes.INT, description='仓库ID'),
            OpenApiParameter(name='product', type=OpenApiTypes.INT, description='产品ID'),
            OpenApiParameter(name='is_finished', type=OpenApiTypes.BOOL, description='是否已完成'),
            OpenApiParameter(name='include_details', type=OpenApiTypes.BOOL, description='是否包含明细，默认true'),
        ],
        responses={200: dict},
        summary="获取库存变动记录列表",
        description="按时间范围查询库存变动记录，支持多种过滤条件"
    )
    def get(self, request):
        """
        获取库存变动记录列表（按时间范围查询）
        
        查询参数:
        - start: 开始日期 (YYYY-MM-DD)，可选，默认为昨天
        - end: 结束日期 (YYYY-MM-DD)，可选，默认为昨天
        - type: 变动类型 (1=入库, 2=出库)，可选
        - source_type: 来源类型（可选）
        - source_id: 来源业务单据ID（可选）
        - source_id_isnull: 来源业务单据ID是否为空（可选，true/false）
        - warehouse: 仓库ID，可选
        - product: 产品ID，可选
        - is_finished: 是否已完成 (true/false)，可选
        - include_details: 是否包含明细记录 (true/false)，可选，默认为 true
        """
        
        # 检查员工权限
        if not self.check_employee_permission(request):
            return self.permission_error_response('无权限访问')
        
        merchant_id = self.get_merchant_id(request)
        
        try:
            # 获取查询参数
            start_date_str = request.GET.get('start')
            end_date_str = request.GET.get('end')
            
            # 默认查询昨天的数据
            if not start_date_str and not end_date_str:
                yesterday = datetime.now().date() - timedelta(days=1)
                start_date = yesterday
                end_date = yesterday
            else:
                # 解析日期参数
                try:
                    if start_date_str:
                        start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
                    else:
                        start_date = datetime.now().date() - timedelta(days=1)
                    
                    if end_date_str:
                        end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
                    else:
                        end_date = start_date
                except ValueError:
                    return Response({
                        'error': '日期格式错误，请使用 YYYY-MM-DD 格式'
                    }, status=status.HTTP_400_BAD_REQUEST)
            
            # 验证日期范围
            if start_date > end_date:
                return Response({
                    'error': '开始日期不能大于结束日期'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 构建查询
            queryset = stock_models.StockChangeRecord.objects.filter(
                merchant_id=merchant_id,
                created_at__date__gte=start_date,
                created_at__date__lte=end_date
            ).select_related('warehouse', 'created_by')
            
            # 可选过滤条件
            change_type = request.GET.get('type')
            if change_type:
                try:
                    queryset = queryset.filter(type=int(change_type))
                except ValueError:
                    return Response({
                        'error': 'type 参数必须为整数'
                    }, status=status.HTTP_400_BAD_REQUEST)

            source_type = request.GET.get('source_type')
            if source_type:
                try:
                    queryset = queryset.filter(source_type=int(source_type))
                except ValueError:
                    return Response({
                        'error': 'source_type 参数必须为整数'
                    }, status=status.HTTP_400_BAD_REQUEST)

            source_id = request.GET.get('source_id')
            if source_id:
                try:
                    queryset = queryset.filter(source_id=int(source_id))
                except ValueError:
                    return Response({
                        'error': 'source_id 参数必须为整数'
                    }, status=status.HTTP_400_BAD_REQUEST)
            else:
                source_id_isnull = request.GET.get('source_id_isnull')
                if source_id_isnull is not None:
                    if source_id_isnull.lower() == 'true':
                        queryset = queryset.filter(source_id__isnull=True)
                    elif source_id_isnull.lower() == 'false':
                        queryset = queryset.filter(source_id__isnull=False)
            
            warehouse_id = request.GET.get('warehouse')
            if warehouse_id:
                try:
                    warehouse_id = int(warehouse_id)
                    # 验证仓库是否对用户可见
                    if not self.validate_warehouse_visibility(warehouse_id, request):
                        return Response({
                            'error': f'仓库ID {warehouse_id} 对当前用户不可见'
                        }, status=status.HTTP_403_FORBIDDEN)
                    queryset = queryset.filter(warehouse_id=warehouse_id)
                except ValueError:
                    return Response({
                        'error': 'warehouse 参数必须为整数'
                    }, status=status.HTTP_400_BAD_REQUEST)
            
            # 产品过滤参数
            product_id = request.GET.get('product')
            if product_id:
                try:
                    product_id = int(product_id)
                    # 验证产品是否对用户可见
                    if not self.validate_product_visibility(product_id, request):
                        return Response({
                            'error': f'产品ID {product_id} 对当前用户不可见'
                        }, status=status.HTTP_403_FORBIDDEN)
                    # 只返回包含该产品的库存变动记录
                    queryset = queryset.filter(details__product_id=product_id).distinct()
                except ValueError:
                    return Response({
                        'error': 'product 参数必须为整数'
                    }, status=status.HTTP_400_BAD_REQUEST)
            
            is_finished = request.GET.get('is_finished')
            if is_finished is not None:
                if is_finished.lower() == 'true':
                    queryset = queryset.filter(is_finished=True)
                elif is_finished.lower() == 'false':
                    queryset = queryset.filter(is_finished=False)
            
            # 是否包含明细记录，默认为 true
            include_details_str = request.GET.get('include_details', 'true')
            include_details = include_details_str.lower() != 'false'
            
            # 过滤掉用户不可见的仓库和产品的记录
            visible_records = []
            for record in queryset:
                # 检查仓库可见性
                if not self.validate_warehouse_visibility(record.warehouse_id, request):
                    continue
                
                # 检查该记录是否包含至少一个用户可见的产品
                has_visible_product = False
                record_details = stock_models.StockChangeDetail.objects.filter(
                    stock_change_record=record
                ).select_related('product')
                
                for detail in record_details:
                    if self.validate_product_visibility(detail.product_id, request):
                        has_visible_product = True
                        break
                
                # 只有当记录包含至少一个可见产品时才添加
                if has_visible_product:
                    visible_records.append(record)
            
            # 构建响应数据
            results = []
            for record in visible_records:
                # 获取该记录的所有明细
                all_details = stock_models.StockChangeDetail.objects.filter(
                    stock_change_record=record
                ).select_related('product')
                
                # 只统计和返回用户可见的产品明细
                visible_details = self.filter_visible_details(all_details, request)
                total_quantity = sum(float(detail.quantity) for detail in visible_details)
                
                record_data = self.build_record_data(record)
                record_data['details_count'] = len(visible_details)
                record_data['total_quantity'] = total_quantity
                
                # 如果需要包含明细，则添加明细数据
                if include_details:
                    record_data['details'] = [self.build_detail_data(detail) for detail in visible_details]
                
                results.append(record_data)
            
            response_data = {
                'count': len(results),
                'results': results,
                'date_range': {
                    'start': start_date.strftime('%Y-%m-%d'),
                    'end': end_date.strftime('%Y-%m-%d')
                }
            }
            
            logger.info(
                f"用户 {request.user.username} 查询库存变动记录列表，"
                f"时间范围: {start_date} 到 {end_date}，共 {len(results)} 条"
            )
            return Response(response_data, status=status.HTTP_200_OK)
            
        except AttributeError as e:
            logger.error(f"用户 {request.user.username} 无员工信息: {str(e)}", exc_info=True)
            return self.permission_error_response('用户无员工信息，无权访问')
        
        except Exception as e:
            logger.error(f"查询库存变动记录列表失败: {str(e)}", exc_info=True)
            return Response({
                'error': '查询库存变动记录列表失败',
                'message': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class ListStockChangeDetailsView(StockChangeViewMixin, views.APIView):
    """获取库存变动明细列表"""
    
    permission_classes = [IsAuthenticated]
    
    @extend_schema(
        tags=['读取库存明细'],
        parameters=[
            OpenApiParameter(name='warehouse_id', type=OpenApiTypes.INT, required=True, description='仓库ID'),
            OpenApiParameter(name='product_id', type=OpenApiTypes.INT, required=True, description='产品ID'),
            OpenApiParameter(name='direction', type=OpenApiTypes.STR, required=False, description='变动方向 (inbound=入库, outbound=出库)，默认为inbound'),
        ],
        responses={200: dict},
        summary="获取库存变动明细列表",
        description="根据仓库和产品查询库存变动明细，不查询StockChangeRecord"
    )
    def get(self, request):
        """
        获取库存变动明细列表（根据仓库和产品查询）
        
        查询参数:
        - warehouse_id: 仓库ID，必填
        - product_id: 产品ID，必填
        - direction: 变动方向 (inbound=入库, outbound=出库)，可选，默认为inbound
        """
        
        # 检查员工权限
        if not self.check_employee_permission(request):
            return self.permission_error_response('无权限访问')
        
        merchant_id = self.get_merchant_id(request)
        
        try:
            # 获取查询参数
            warehouse_id_str = request.GET.get('warehouse_id')
            product_id_str = request.GET.get('product_id')
            direction = request.GET.get('direction', 'inbound')  # 默认为入库
            
            # 验证必填参数
            if not warehouse_id_str:
                return Response({
                    'error': '缺少必要参数',
                    'message': 'warehouse_id 参数为必填'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            if not product_id_str:
                return Response({
                    'error': '缺少必要参数',
                    'message': 'product_id 参数为必填'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 验证direction参数
            if direction not in ['inbound', 'outbound']:
                return Response({
                    'error': '参数格式错误',
                    'message': 'direction 参数必须为 inbound 或 outbound'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 解析参数
            try:
                warehouse_id = int(warehouse_id_str)
                product_id = int(product_id_str)
            except ValueError:
                return Response({
                    'error': '参数格式错误',
                    'message': 'warehouse_id 和 product_id 必须为整数'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 验证仓库是否对用户可见
            if not self.validate_warehouse_visibility(warehouse_id, request):
                return Response({
                    'error': f'仓库ID {warehouse_id} 对当前用户不可见'
                }, status=status.HTTP_403_FORBIDDEN)
            
            # 验证产品是否对用户可见
            if not self.validate_product_visibility(product_id, request):
                return Response({
                    'error': f'产品ID {product_id} 对当前用户不可见'
                }, status=status.HTTP_403_FORBIDDEN)
            
            # 根据direction参数确定变动类型
            if direction == 'inbound':
                change_type = stock_models.StockChangeTypeEnum.ADD  # 入库
            else:  # outbound
                change_type = stock_models.StockChangeTypeEnum.REMOVE  # 出库
            
            # 查询库存变动明细，仅查询未被消耗的明细（consumed_by_detail为空）
            active_freeze_statuses = [
                status
                for status in stock_models.StockFreezeStatusEnum.values
                if status not in {
                    stock_models.StockFreezeStatusEnum.CANCELLED,
                    stock_models.StockFreezeStatusEnum.COMPLETED,
                }
            ]
            details = stock_models.StockChangeDetail.objects.filter(
                stock_change_record__merchant_id=merchant_id,
                stock_change_record__warehouse_id=warehouse_id,
                stock_change_record__type=change_type,
                product_id=product_id,
                consumed_by_detail__isnull=True  # 仅查询未被消耗的明细
            ).exclude(
                stock_freezes__status__in=active_freeze_statuses
            ).select_related(
                'stock_change_record',
                'product'
            ).order_by('-stock_change_record__created_at')
            
            # 构建响应数据
            results = []
            for detail in details:
                detail_data = self.build_detail_data(detail)
                # 添加记录的额外信息
                detail_data['record_type'] = detail.stock_change_record.type
                detail_data['record_type_display'] = detail.stock_change_record.get_type_display()
                detail_data['source_type'] = detail.stock_change_record.source_type
                detail_data['source_type_display'] = detail.stock_change_record.get_source_type_display()
                detail_data['record_created_at'] = detail.stock_change_record.created_at
                detail_data['record_created_by'] = detail.stock_change_record.created_by.username
                results.append(detail_data)
            
            response_data = {
                'count': len(results),
                'results': results,
                'filters': {
                    'warehouse_id': warehouse_id,
                    'product_id': product_id,
                    'direction': direction
                }
            }
            
            logger.info(
                f"用户 {request.user.username} 查询库存变动明细，"
                f"仓库ID: {warehouse_id}，产品ID: {product_id}，共 {len(results)} 条"
            )
            return Response(response_data, status=status.HTTP_200_OK)
            
        except AttributeError as e:
            logger.error(f"用户 {request.user.username} 无员工信息: {str(e)}", exc_info=True)
            return self.permission_error_response('用户无员工信息，无权访问')
        
        except Exception as e:
            logger.error(f"查询库存变动明细失败: {str(e)}", exc_info=True)
            return Response({
                'error': '查询库存变动明细失败',
                'message': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
