<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Http\Controllers\Report;

use App\Business\Inventory\InventoryWarningService;
use App\Business\Report\ComprehensiveSummaryAnalysisService;
use App\Business\Report\CsvExportService;
use App\Business\Report\InventoryAnalysisReportService;
use App\Business\Report\InventoryReportService;
use App\Business\Report\PurchaseAnalysisReportService;
use App\Business\Report\PurchaseReportService;
use App\Business\Report\QueryCenterService;
use App\Business\Report\SalesAnalysisReportService;
use App\Business\Report\SalesReportService;
use App\Business\Report\SettlementAnalysisReportService;
use App\Business\Settlement\Enums\PayableStatus;
use App\Business\Settlement\Enums\ReceivableStatus;
use App\Business\Settlement\SettlementAgingAnalysisService;
use App\Http\Controllers\Controller;
use App\Models\DberpInventoryBalance;
use App\Models\DberpProduct;
use App\Models\DberpProductSku;
use App\Models\DberpPurchasePriceReferenceSnapshot;
use App\Services\DberpAuditService;
use App\Services\DberpPermissionService;
use App\Support\DberpAuditDisplay;
use App\Support\DberpDocumentQueryPresentation;
use App\Support\DberpNumberFormatter;
use App\Support\DberpPriceLevelDictionary;
use App\Support\DberpReportSkuPresentation;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpFoundation\StreamedResponse;

final class ReportExportController extends Controller
{
    public function __construct(
        private readonly CsvExportService $csvExportService,
        private readonly SalesReportService $salesReportService,
        private readonly SalesAnalysisReportService $salesAnalysisReportService,
        private readonly PurchaseReportService $purchaseReportService,
        private readonly PurchaseAnalysisReportService $purchaseAnalysisReportService,
        private readonly InventoryReportService $inventoryReportService,
        private readonly InventoryAnalysisReportService $inventoryAnalysisReportService,
        private readonly InventoryWarningService $inventoryWarningService,
        private readonly QueryCenterService $queryCenterService,
        private readonly SettlementAnalysisReportService $settlementAnalysisReportService,
        private readonly SettlementAgingAnalysisService $settlementAgingAnalysisService,
        private readonly ComprehensiveSummaryAnalysisService $comprehensiveSummaryAnalysisService,
        private readonly DberpPermissionService $permissionService,
        private readonly DberpAuditService $auditService,
    ) {}

    public function __invoke(Request $request, string $report): StreamedResponse
    {
        abort_unless($this->permissionService->allowsReportExport($request->user(), $report), 403);

        $rawFilters = array_merge(
            (array) $request->input('tableFilters', []),
            (array) $request->input('filters', []),
        );

        $filters = $this->normalizeFilters($rawFilters);

        return match ($report) {
            'sales-statistics' => $this->downloadReport(
                $report,
                '销售统计',
                'sales-statistics-'.now()->format('Ymd_His').'.csv',
                ['销售单号', '客户', '状态', '业务时间', '总数量', '成交金额', '应收金额', '已收金额', '未收金额', '应收状态'],
                $this->salesReportService->statisticsQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->code,
                    (string) $record->customer?->name,
                    __('dberp.options.sales_order_status')[$record->status] ?? (string) $record->status,
                    $record->business_time?->format('Y-m-d H:i:s'),
                    DberpNumberFormatter::quantity($record->total_quantity),
                    DberpNumberFormatter::money($record->final_amount),
                    DberpNumberFormatter::money($record->receivable_amount),
                    DberpNumberFormatter::money($record->received_amount),
                    DberpNumberFormatter::money($record->unreceived_amount),
                    ReceivableStatus::tryFrom((string) $record->receivable_status)?->label() ?? (string) $record->receivable_status,
                ])->all(),
                $filters,
            ),
            'purchase-statistics' => $this->downloadReport(
                $report,
                '采购统计',
                'purchase-statistics-'.now()->format('Ymd_His').'.csv',
                ['采购单号', '供应商', '状态', '业务时间', '总数量', '采购金额', '应付金额', '已付金额', '未付金额', '应付状态'],
                $this->purchaseReportService->statisticsQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->code,
                    (string) $record->supplier?->name,
                    __('dberp.options.purchase_order_status')[$record->status] ?? (string) $record->status,
                    $record->business_time?->format('Y-m-d H:i:s'),
                    DberpNumberFormatter::quantity($record->total_quantity),
                    DberpNumberFormatter::money($record->total_amount),
                    DberpNumberFormatter::money($record->payable_amount),
                    DberpNumberFormatter::money($record->paid_amount),
                    DberpNumberFormatter::money($record->unpaid_amount),
                    PayableStatus::tryFrom((string) $record->payable_status)?->label() ?? (string) $record->payable_status,
                ])->all(),
                $filters,
            ),
            'inventory-summary' => $this->downloadReport(
                $report,
                '进销存汇总',
                'inventory-summary-'.now()->format('Ymd_His').'.csv',
                [
                    '汇总视角',
                    '物料编码',
                    '物料名称',
                    '规格摘要',
                    '规格编码',
                    '分类',
                    '仓库',
                    '实时库存',
                    '可用库存',
                    '区间总入库',
                    '区间总出库',
                    '采购入库',
                    '销售出库',
                    '调拨入库',
                    '调拨出库',
                    '最近变动时间',
                ],
                (function () use ($filters) {
                    $mode = (string) ($filters['aggregate_level'] ?? 'sku_detail');
                    $query = $mode === 'product_summary'
                        ? $this->inventoryReportService->productSummaryQuery($filters)
                        : $this->inventoryReportService->summaryQuery($filters);

                    $modeLabel = $mode === 'product_summary'
                        ? '按商品汇总'
                        : '按商品规格明细';

                    return $query->get()->map(fn (DberpInventoryBalance $record): array => [
                        $modeLabel,
                        (string) $record->product?->code,
                        (string) $record->product?->name,
                        DberpReportSkuPresentation::inventoryBalanceSpecSummary(
                            $record->getAttribute('product_sku_id') !== null ? (int) $record->getAttribute('product_sku_id') : null,
                            (string) ($record->productSku?->spec_text ?? ''),
                            (string) ($record->productSku?->sku_code ?? ''),
                        ),
                        (function () use ($record): string {
                            $skuId = $record->getAttribute('product_sku_id') !== null ? (int) $record->getAttribute('product_sku_id') : null;
                            if ($skuId === null || $skuId === 0) {
                                return DberpReportSkuPresentation::unspecifiedSpecLabel();
                            }

                            $code = trim((string) ($record->productSku?->sku_code ?? ''));

                            return $code !== '' ? $code : DberpReportSkuPresentation::unspecifiedSpecLabel();
                        })(),
                        (string) $record->product?->category?->name,
                        (string) $record->warehouse?->name,
                        DberpNumberFormatter::quantity($record->realtime_quantity),
                        DberpNumberFormatter::quantity($record->available_quantity),
                        DberpNumberFormatter::quantity($record->total_in_quantity),
                        DberpNumberFormatter::quantity($record->total_out_quantity),
                        DberpNumberFormatter::quantity($record->purchase_in_quantity),
                        DberpNumberFormatter::quantity($record->sales_out_quantity),
                        DberpNumberFormatter::quantity($record->transfer_in_quantity),
                        DberpNumberFormatter::quantity($record->transfer_out_quantity),
                        $record->last_moved_at?->format('Y-m-d H:i:s'),
                    ])->all();
                })(),
                $filters,
            ),
            'inventory-transaction-query' => $this->downloadReport(
                $report,
                '库存流水',
                'inventory-transaction-query-'.now()->format('Ymd_His').'.csv',
                ['业务时间', '业务类型', '方向', '物料名称', '物料编码', '规格摘要', '规格编码', '计量单位', '仓库', '变动数量', '变动前', '变动后', '业务单号', '操作人'],
                $this->queryCenterService->inventoryTransactionQuery($filters)->get()->map(fn ($record): array => [
                    $record->business_time?->format('Y-m-d H:i:s'),
                    __('dberp.options.inventory_business_type')[$record->business_type] ?? (string) $record->business_type,
                    __('dberp.options.inventory_direction')[$record->direction] ?? (string) $record->direction,
                    (string) (($record->product_name !== null && $record->product_name !== '') ? $record->product_name : ($record->product?->name ?? '')),
                    (string) (($record->product_code !== null && $record->product_code !== '') ? $record->product_code : ($record->product?->code ?? '')),
                    (string) DberpReportSkuPresentation::inventoryBalanceSpecSummary(
                        $record->product_sku_id !== null ? (int) $record->product_sku_id : null,
                        (string) ($record->spec_text ?? ''),
                        (string) ($record->sku_code ?? ''),
                    ),
                    (function () use ($record): string {
                        $skuId = $record->product_sku_id !== null ? (int) $record->product_sku_id : null;
                        if ($skuId === null || $skuId === 0) {
                            return DberpReportSkuPresentation::unspecifiedSpecLabel();
                        }

                        $code = trim((string) ($record->sku_code ?? ''));

                        return $code !== '' ? $code : DberpReportSkuPresentation::unspecifiedSpecLabel();
                    })(),
                    (string) ($record->unit_name ?? ''),
                    (string) $record->warehouse?->name,
                    DberpNumberFormatter::quantity($record->change_quantity),
                    DberpNumberFormatter::quantity($record->before_quantity),
                    DberpNumberFormatter::quantity($record->after_quantity),
                    (string) $record->business_number,
                    (string) $record->operator?->name,
                ])->all(),
                $filters,
            ),
            'inventory-warning-report' => $this->downloadReport(
                $report,
                '库存预警',
                'inventory-warning-report-'.now()->format('Ymd_His').'.csv',
                ['商品编码', '商品名称', '分类', '仓库', '实时库存', '可用库存', '安全库存', '预警类型'],
                $this->inventoryReportService->warningQuery($filters)->get()->map(fn (DberpInventoryBalance $record): array => [
                    (string) $record->product?->code,
                    (string) $record->product?->name,
                    (string) $record->product?->category?->name,
                    (string) $record->warehouse?->name,
                    DberpNumberFormatter::quantity($record->realtime_quantity),
                    DberpNumberFormatter::quantity($record->available_quantity),
                    DberpNumberFormatter::quantity($record->safety_stock),
                    $this->inventoryWarningService->warningTypeLabel($record),
                ])->all(),
                $filters,
            ),
            'customer-sales-ranking' => $this->downloadReport(
                $report,
                '客户销售排行',
                'customer-sales-ranking-'.now()->format('Ymd_His').'.csv',
                ['客户编码', '客户名称', '业务员', '销售单数', '销售金额', '已收金额'],
                $this->salesReportService->customerRankingQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->code,
                    (string) $record->name,
                    (string) $record->salesperson?->name,
                    (string) $record->order_count,
                    DberpNumberFormatter::money($record->sales_amount),
                    DberpNumberFormatter::money($record->received_amount_total),
                ])->all(),
                $filters,
            ),
            'supplier-purchase-ranking' => $this->downloadReport(
                $report,
                '供应商采购排行',
                'supplier-purchase-ranking-'.now()->format('Ymd_His').'.csv',
                ['供应商编码', '供应商名称', '采购单数', '采购金额', '已付金额'],
                $this->purchaseReportService->supplierRankingQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->code,
                    (string) $record->name,
                    (string) $record->order_count,
                    DberpNumberFormatter::money($record->purchase_amount),
                    DberpNumberFormatter::money($record->paid_amount_total),
                ])->all(),
                $filters,
            ),
            'supplier-performance' => $this->downloadReport(
                $report,
                '供应表现',
                'supplier-performance-'.now()->format('Ymd_His').'.csv',
                [
                    '供应商编码',
                    '供应商名称',
                    '采购单数',
                    '采购金额',
                    '平均交期(天)',
                    '近30天异常数',
                    '有效入库笔数',
                    '异常率',
                    '近30天退货单数',
                    '有效价格参考数',
                    '最近采购时间',
                    '最近参考价日期',
                ],
                $this->purchaseReportService->supplierPerformanceQuery($filters)->get()->map(function ($record): array {
                    $receiptCount = max((int) ($record->effective_receipt_count ?? 0), 1);
                    $exceptionRate = ((int) ($record->exception_count_30d ?? 0)) / $receiptCount * 100;
                    $lastPurchaseRaw = $record->last_purchase_date ?? null;
                    $lastPurchaseStr = $lastPurchaseRaw !== null && $lastPurchaseRaw !== ''
                        ? Carbon::parse((string) $lastPurchaseRaw)->format('Y-m-d H:i:s')
                        : '';
                    $latestRefRaw = $record->latest_reference_date ?? null;
                    $latestRefStr = $latestRefRaw !== null && $latestRefRaw !== ''
                        ? Carbon::parse((string) $latestRefRaw)->format('Y-m-d')
                        : '';

                    return [
                        (string) $record->code,
                        (string) $record->name,
                        (string) $record->order_count,
                        DberpNumberFormatter::money($record->purchase_amount),
                        (string) ($record->avg_lead_time_days ?? ''),
                        (string) ($record->exception_count_30d ?? ''),
                        (string) ($record->effective_receipt_count ?? ''),
                        DberpNumberFormatter::percent((string) $exceptionRate, false),
                        (string) ($record->return_order_count_30d ?? ''),
                        (string) ($record->active_price_reference_count ?? ''),
                        $lastPurchaseStr,
                        $latestRefStr,
                    ];
                })->all(),
                $filters,
            ),
            'purchase-price-reference' => $this->downloadReport(
                $report,
                '采购价格沉淀',
                'purchase-price-reference-'.now()->format('Ymd_His').'.csv',
                [
                    '范围类型',
                    '供应商',
                    '商品',
                    '最近成交单价',
                    '最近成交日期',
                    '最近到货日期',
                    '最近交期(天)',
                    '刷新时间',
                ],
                $this->purchaseReportService->priceReferenceQuery($filters)->get()->map(function (DberpPurchasePriceReferenceSnapshot $record): array {
                    $scopeLabel = __('dberp.options.purchase_price_reference_scope_type')[$record->scope_type] ?? (string) $record->scope_type;

                    return [
                        (string) $scopeLabel,
                        (string) ($record->supplier?->name ?? ''),
                        (string) ($record->product?->name ?? ''),
                        DberpNumberFormatter::price($record->latest_transaction_unit_price),
                        $record->latest_transaction_date?->format('Y-m-d') ?? '',
                        $record->latest_receipt_date?->format('Y-m-d') ?? '',
                        (string) ($record->latest_lead_time_days ?? ''),
                        $record->refreshed_at?->format('Y-m-d H:i:s') ?? '',
                    ];
                })->all(),
                $filters,
            ),
            'product-sales-ranking' => $this->downloadReport(
                $report,
                '商品销售排行',
                'product-sales-ranking-'.now()->format('Ymd_His').'.csv',
                (string) ($filters['ranking_dimension'] ?? 'product') === 'product_spec'
                    ? ['商品编码', '商品名称', '分类', '规格摘要', '规格编码', '销售订单数', '销售数量', '销售金额']
                    : ['商品编码', '商品名称', '分类', '销售订单数', '销售数量', '销售金额'],
                (function () use ($filters) {
                    $specMode = (string) ($filters['ranking_dimension'] ?? 'product') === 'product_spec';
                    $query = $specMode
                        ? $this->salesReportService->productSkuRankingQuery($filters)
                        : $this->salesReportService->productRankingQuery($filters);

                    if ($specMode) {
                        return $query->get()->map(fn (DberpProductSku $record): array => [
                            (string) $record->product?->code,
                            (string) $record->product?->name,
                            (string) ($record->product?->category?->name ?? ''),
                            DberpReportSkuPresentation::skuRecordSpecSummary($record),
                            (string) ($record->sku_code ?? ''),
                            (string) $record->sales_order_count,
                            DberpNumberFormatter::quantity($record->sales_quantity),
                            DberpNumberFormatter::money($record->sales_amount),
                        ])->all();
                    }

                    return $query->get()->map(fn (DberpProduct $record): array => [
                        (string) $record->code,
                        (string) $record->name,
                        (string) $record->category?->name,
                        (string) $record->sales_order_count,
                        DberpNumberFormatter::quantity($record->sales_quantity),
                        DberpNumberFormatter::money($record->sales_amount),
                    ])->all();
                })(),
                $filters,
            ),
            'product-purchase-ranking' => $this->downloadReport(
                $report,
                '商品采购排行',
                'product-purchase-ranking-'.now()->format('Ymd_His').'.csv',
                (string) ($filters['ranking_dimension'] ?? 'product') === 'product_spec'
                    ? ['商品编码', '商品名称', '分类', '规格摘要', '规格编码', '采购订单数', '采购数量', '采购金额']
                    : ['商品编码', '商品名称', '分类', '采购订单数', '采购数量', '采购金额'],
                (function () use ($filters) {
                    $specMode = (string) ($filters['ranking_dimension'] ?? 'product') === 'product_spec';
                    $query = $specMode
                        ? $this->purchaseReportService->productSkuRankingQuery($filters)
                        : $this->purchaseReportService->productRankingQuery($filters);

                    if ($specMode) {
                        return $query->get()->map(fn (DberpProductSku $record): array => [
                            (string) $record->product?->code,
                            (string) $record->product?->name,
                            (string) ($record->product?->category?->name ?? ''),
                            DberpReportSkuPresentation::skuRecordSpecSummary($record),
                            (string) ($record->sku_code ?? ''),
                            (string) $record->purchase_order_count,
                            (string) $record->purchase_quantity,
                            DberpNumberFormatter::money($record->purchase_amount),
                        ])->all();
                    }

                    return $query->get()->map(fn (DberpProduct $record): array => [
                        (string) $record->code,
                        (string) $record->name,
                        (string) $record->category?->name,
                        (string) $record->purchase_order_count,
                        (string) $record->purchase_quantity,
                        DberpNumberFormatter::money($record->purchase_amount),
                    ])->all();
                })(),
                $filters,
            ),
            'document-query' => $this->downloadReport(
                $report,
                '单据综合查询',
                'document-query-'.now()->format('Ymd_His').'.csv',
                ['单据类型', '单号', '状态', '业务时间', '客户', '供应商', '仓库', '经办人', '数量', '金额'],
                $this->queryCenterService->documentQuery($filters)->get()->map(fn ($record): array => [
                    __('dberp.options.document_type')[$record->document_type] ?? (string) $record->document_type,
                    (string) $record->code,
                    DberpDocumentQueryPresentation::statusLabel((string) $record->document_type, $record->status),
                    $record->business_time?->format('Y-m-d H:i:s'),
                    (string) $record->customer?->name,
                    (string) $record->supplier?->name,
                    (string) $record->warehouse?->name,
                    (string) $record->handlerEmployee?->name,
                    DberpNumberFormatter::quantity($record->total_quantity),
                    DberpNumberFormatter::money($record->total_amount),
                ])->all(),
                $filters,
            ),
            'product-business-query' => $this->downloadReport(
                $report,
                '商品经营查询',
                'product-business-query-'.now()->format('Ymd_His').'.csv',
                (string) ($filters['business_aggregate_level'] ?? 'product') === 'product_spec'
                    ? ['商品编码', '商品名称', '分类', '规格摘要', '规格编码', '当前库存', '销售数量', '销售金额', '采购数量', '采购金额']
                    : ['商品编码', '商品名称', '分类', '当前库存', '销售数量', '销售金额', '采购数量', '采购金额'],
                (function () use ($filters) {
                    $specMode = (string) ($filters['business_aggregate_level'] ?? 'product') === 'product_spec';
                    $service = $this->queryCenterService;
                    $query = $specMode
                        ? $service->productSkuBusinessQuery($filters)
                        : $service->productBusinessQuery($filters);

                    if ($specMode) {
                        return $query->get()->map(fn (DberpProductSku $record): array => [
                            (string) $record->product?->code,
                            (string) $record->product?->name,
                            (string) ($record->product?->category?->name ?? ''),
                            DberpReportSkuPresentation::skuRecordSpecSummary($record),
                            (string) ($record->sku_code ?? ''),
                            DberpNumberFormatter::quantity($record->current_stock_quantity),
                            DberpNumberFormatter::quantity($record->sales_quantity),
                            DberpNumberFormatter::money($record->sales_amount),
                            DberpNumberFormatter::quantity($record->purchase_quantity),
                            DberpNumberFormatter::money($record->purchase_amount),
                        ])->all();
                    }

                    return $query->get()->map(fn (DberpProduct $record): array => [
                        (string) $record->code,
                        (string) $record->name,
                        (string) $record->category?->name,
                        DberpNumberFormatter::quantity($record->current_stock_quantity),
                        DberpNumberFormatter::quantity($record->sales_quantity),
                        DberpNumberFormatter::money($record->sales_amount),
                        DberpNumberFormatter::quantity($record->purchase_quantity),
                        DberpNumberFormatter::money($record->purchase_amount),
                    ])->all();
                })(),
                $filters,
            ),
            'customer-settlement-query' => $this->downloadReport(
                $report,
                '客户往来查询',
                'customer-settlement-query-'.now()->format('Ymd_His').'.csv',
                ['客户', '变动类型', '来源类型', '单号', '变动金额', '变动后余额', '业务时间'],
                $this->queryCenterService->customerSettlementQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->customer?->name,
                    __('dberp.options.settlement_change_type')[$record->change_type] ?? (string) $record->change_type,
                    __('dberp.options.settlement_source_type')[$record->source_type] ?? (string) $record->source_type,
                    (string) $record->document_number,
                    DberpNumberFormatter::money($record->change_amount),
                    DberpNumberFormatter::money($record->balance_after),
                    $record->business_time?->format('Y-m-d H:i:s'),
                ])->all(),
                $filters,
            ),
            'supplier-settlement-query' => $this->downloadReport(
                $report,
                '供应商往来查询',
                'supplier-settlement-query-'.now()->format('Ymd_His').'.csv',
                ['供应商', '变动类型', '来源类型', '单号', '变动金额', '变动后余额', '业务时间'],
                $this->queryCenterService->supplierSettlementQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->supplier?->name,
                    __('dberp.options.settlement_change_type')[$record->change_type] ?? (string) $record->change_type,
                    __('dberp.options.settlement_source_type')[$record->source_type] ?? (string) $record->source_type,
                    (string) $record->document_number,
                    DberpNumberFormatter::money($record->change_amount),
                    DberpNumberFormatter::money($record->balance_after),
                    $record->business_time?->format('Y-m-d H:i:s'),
                ])->all(),
                $filters,
            ),
            'receipt-payment-query' => $this->downloadReport(
                $report,
                __('dberp.resources.receipt_payment_query.label'),
                'receipt-payment-query-'.now()->format('Ymd_His').'.csv',
                [
                    __('dberp.fields.direction'),
                    __('dberp.fields.document_code'),
                    __('dberp.fields.status'),
                    __('dberp.fields.payment_method'),
                    __('dberp.fields.amount'),
                    __('dberp.fields.customer'),
                    __('dberp.fields.supplier'),
                    __('dberp.fields.sales_order_code'),
                    __('dberp.fields.purchase_order_code'),
                    __('dberp.fields.handler_employee'),
                    __('dberp.fields.business_time'),
                    __('dberp.fields.effective_at'),
                    __('dberp.fields.voided_at'),
                    __('dberp.fields.remark'),
                ],
                $this->queryCenterService->receiptPaymentQuery($filters)->get()->map(fn ($record): array => [
                    __('dberp.options.receipt_payment_direction')[$record->direction] ?? (string) $record->direction,
                    (string) $record->code,
                    __('dberp.options.common_document_status')[$record->status] ?? (string) $record->status,
                    (string) optional($record->paymentMethodItem)->label,
                    DberpNumberFormatter::money($record->amount),
                    (string) optional($record->customer)->name,
                    (string) optional($record->supplier)->name,
                    (string) optional($record->salesOrder)->code,
                    (string) optional($record->purchaseOrder)->code,
                    (string) optional($record->handlerEmployee)->name,
                    $record->business_time?->format('Y-m-d H:i:s'),
                    $record->effective_at?->format('Y-m-d H:i:s') ?? '',
                    $record->voided_at?->format('Y-m-d H:i:s') ?? '',
                    (string) ($record->remark ?? ''),
                ])->all(),
                $filters,
            ),
            'audit-log' => $this->downloadReport(
                $report,
                '审计日志',
                'audit-log-'.now()->format('Ymd_His').'.csv',
                ['时间', '操作人', '动作', '关联对象', 'IP'],
                $this->queryCenterService->auditLogQuery($filters)->get()->map(fn ($record): array => [
                    $record->created_at?->format('Y-m-d H:i:s'),
                    (string) (($record->user?->name !== null && $record->user?->name !== '') ? $record->user->name : __('dberp.audit.operator_system')),
                    DberpAuditDisplay::actionLabel($record->action),
                    DberpAuditDisplay::auditableSummary($record->auditable_type, $record->auditable_id),
                    (string) ($record->ip_address ?? ''),
                ])->all(),
                $filters,
            ),
            'sales-quote' => $this->downloadReport(
                $report,
                '报价管理',
                'sales-quote-'.now()->format('Ymd_His').'.csv',
                ['报价单号', '客户', '状态', '报价日期', '生效日期', '失效日期', '业务员', '成交金额', '已转销售单'],
                $this->queryCenterService->salesQuoteQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->code,
                    (string) $record->customer?->name,
                    __('dberp.options.sales_quote_status')[$record->status] ?? (string) $record->status,
                    $record->quote_date?->format('Y-m-d'),
                    $record->valid_from?->format('Y-m-d'),
                    $record->valid_until?->format('Y-m-d'),
                    (string) $record->handlerEmployee?->name,
                    DberpNumberFormatter::money($record->final_amount),
                    (string) ($record->converted_sales_order_no ?: '-'),
                ])->all(),
                $filters,
            ),
            'customer-price-rule' => $this->downloadReport(
                $report,
                '客户价格规则',
                'customer-price-rule-'.now()->format('Ymd_His').'.csv',
                [__('dberp.fields.rule_name'), __('dberp.fields.rule_type'), __('dberp.fields.customer'), __('dberp.fields.price_level_code'), __('dberp.fields.product'), __('dberp.fields.unit_price'), __('dberp.fields.status'), __('dberp.fields.valid_from'), __('dberp.fields.valid_until')],
                $this->queryCenterService->customerPriceRuleQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->rule_name,
                    __('dberp.options.customer_price_rule_type')[$record->rule_type] ?? (string) $record->rule_type,
                    (string) $record->customer?->name,
                    DberpPriceLevelDictionary::displayLabel($record->price_level_code) ?: '-',
                    (string) $record->product?->name,
                    DberpNumberFormatter::price($record->unit_price),
                    __('dberp.options.customer_price_rule_status')[$record->status] ?? (string) $record->status,
                    $record->valid_from?->format('Y-m-d'),
                    $record->valid_until?->format('Y-m-d'),
                ])->all(),
                $filters,
            ),
            'integration-sync-log' => $this->downloadReport(
                $report,
                '联通日志',
                'integration-sync-log-'.now()->format('Ymd_His').'.csv',
                ['渠道', '来源系统', '目标系统', '联通对象', '方向', '状态', '来源单号', '外部标识', '错误类型', '最近重试结果', '摘要', '时间'],
                $this->queryCenterService->integrationSyncLogQuery($filters)->get()->map(fn ($record): array => [
                    (string) $record->channel,
                    (string) $record->source_system,
                    (string) $record->target_system,
                    (string) $record->sync_object_type,
                    (string) $record->direction,
                    (string) $record->status,
                    (string) $record->source_document_no,
                    (string) $record->external_reference,
                    (string) $record->error_type,
                    (string) ($record->latest_retry_status ?: '-'),
                    (string) ($record->result_summary ?: $record->message),
                    $record->created_at?->format('Y-m-d H:i:s'),
                ])->all(),
                $filters,
            ),
            'sales-analysis' => $this->downloadReport(
                $report,
                __('dberp.resources.sales_analysis.label'),
                'sales-analysis-'.now()->format('Ymd_His').'.csv',
                $this->analysisExportHeaders(),
                $this->salesAnalysisRows($filters),
                $filters,
            ),
            'purchase-analysis' => $this->downloadReport(
                $report,
                __('dberp.resources.purchase_analysis.label'),
                'purchase-analysis-'.now()->format('Ymd_His').'.csv',
                $this->analysisExportHeaders(),
                $this->purchaseAnalysisRows($filters),
                $filters,
            ),
            'inventory-analysis' => $this->downloadReport(
                $report,
                __('dberp.resources.inventory_analysis.label'),
                'inventory-analysis-'.now()->format('Ymd_His').'.csv',
                $this->analysisExportHeaders(),
                $this->inventoryAnalysisRows($filters),
                $filters,
            ),
            'settlement-analysis' => $this->downloadReport(
                $report,
                __('dberp.resources.settlement_analysis.label'),
                'settlement-analysis-'.now()->format('Ymd_His').'.csv',
                $this->analysisExportHeaders(),
                $this->settlementAnalysisRows($filters),
                $filters,
            ),
            'settlement-aging-analysis' => $this->downloadReport(
                $report,
                __('dberp.resources.settlement_aging_analysis.label'),
                'settlement-aging-analysis-'.now()->format('Ymd_His').'.csv',
                $this->analysisExportHeaders(),
                $this->settlementAgingAnalysisRows($filters),
                $filters,
            ),
            'comprehensive-summary-analysis' => $this->downloadReport(
                $report,
                __('dberp.resources.comprehensive_summary_analysis.label'),
                'comprehensive-summary-analysis-'.now()->format('Ymd_His').'.csv',
                $this->analysisExportHeaders(),
                $this->comprehensiveSummaryRows($filters),
                $filters,
            ),
            default => abort(404),
        };
    }

    /**
     * @param  list<string>  $headers
     * @param  list<list<string|null>>  $rows
     * @param  array<string, mixed>  $filters
     */
    private function downloadReport(string $reportKey, string $reportName, string $filename, array $headers, array $rows, array $filters): StreamedResponse
    {
        $this->auditService->log('dberp.report.exported', null, null, [
            'report_name' => $reportName,
            'report_key' => $reportKey,
            'filter_summary' => $this->formatFilters($filters),
            'column_scope' => implode('、', $headers),
            'field_boundary' => $this->fieldBoundary($reportKey),
            'row_count' => count($rows),
        ]);

        return $this->csvExportService->download($filename, $headers, $rows);
    }

    /**
     * @return list<string>
     */
    private function analysisExportHeaders(): array
    {
        return ['区块', '主项', '值1', '值2', '值3', '值4', '值5', '值6', '统计说明'];
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<list<string|null>>
     */
    private function salesAnalysisRows(array $filters): array
    {
        $summary = $this->salesAnalysisReportService->summary($filters);
        $trend = $this->salesAnalysisReportService->dailyTrend($filters);
        $topCustomers = $this->salesAnalysisReportService->topCustomers($filters, 8);
        $topProducts = $this->salesAnalysisReportService->topProducts($filters, 8);

        $rows = [
            ['核心汇总', '销售单数', (string) $summary['order_count'], null, null, null, null, null, '以销售订单统计，不含未提交。'],
            ['核心汇总', '销售金额', (string) $summary['final_amount'], null, null, null, null, null, '金额取订单头成交金额。'],
            ['核心汇总', '应收 / 已收 / 未收', (string) $summary['receivable_amount'], (string) $summary['received_amount'], (string) $summary['unreceived_amount'], null, null, null, '往来金额承接销售订单头应收字段。'],
            ['核心汇总', '销售数量', (string) $summary['total_quantity'], null, null, null, null, null, '数量取订单头累计数量。'],
            ['核心汇总', '出库状态单数', (string) $summary['confirmed_order_count'], (string) $summary['partial_shipped_order_count'], (string) $summary['fully_shipped_order_count'], null, null, null, '分别对应已确认、部分出库、全部出库。'],
        ];

        foreach ($trend as $row) {
            $rows[] = ['按业务日趋势', $row['date'], (string) $row['order_count'], $row['amount'], null, null, null, null, '按业务时间按日汇总单数与金额。'];
        }

        foreach ($topCustomers as $row) {
            $rows[] = ['客户结构', $row['name'], $row['amount'], (string) $row['order_count'], null, null, null, null, '按客户聚合成交额与订单数，默认 Top 8。'];
        }

        foreach ($topProducts as $row) {
            $structureNote = ($filters['sales_ranking_dimension'] ?? null) === 'product_spec'
                ? '按商品规格明细聚合成交额、数量与订单数，默认 Top 8。'
                : '按商品聚合成交额、数量与订单数，默认 Top 8。';
            $rows[] = ['商品结构', $row['name'], $row['amount'], $row['quantity'], (string) $row['order_count'], null, null, null, $structureNote];
        }

        return $rows;
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<list<string|null>>
     */
    private function purchaseAnalysisRows(array $filters): array
    {
        $summary = $this->purchaseAnalysisReportService->summary($filters);
        $trend = $this->purchaseAnalysisReportService->dailyTrend($filters);
        $topSuppliers = $this->purchaseAnalysisReportService->topSuppliers($filters, 8);
        $topProducts = $this->purchaseAnalysisReportService->topProducts($filters, 8);

        $rows = [
            ['核心汇总', '采购单数', (string) $summary['order_count'], null, null, null, null, null, '以采购订单统计，不含未提交。'],
            ['核心汇总', '采购 / 已付 / 未付', (string) $summary['total_amount'], (string) $summary['paid_amount'], (string) $summary['unpaid_amount'], null, null, null, '金额分别取采购总额、已付金额、未付金额。'],
            ['核心汇总', '采购 / 已到 / 待到数量', (string) $summary['total_quantity'], (string) $summary['arrived_quantity'], (string) $summary['remaining_arrival_quantity'], null, null, null, '数量承接采购订单头累计值。'],
            ['核心汇总', '超期待到货 / 部分到货 / 全部到货', (string) $summary['overdue_arrival_order_count'], (string) $summary['partial_received_order_count'], (string) $summary['fully_received_order_count'], null, null, null, '到货关注按预计到货日与当前日期判断。'],
            ['核心汇总', '区间异常 / 区间退货', (string) $summary['exception_count'], (string) $summary['return_order_count'], null, null, null, null, '异常按发现时间统计，退货按业务时间统计。'],
        ];

        foreach ($trend as $row) {
            $rows[] = ['按业务日趋势', $row['date'], (string) $row['order_count'], $row['amount'], null, null, null, null, '按业务时间按日汇总单数与金额。'];
        }

        foreach ($topSuppliers as $row) {
            $rows[] = ['供应商结构', $row['name'], $row['amount'], (string) $row['order_count'], null, null, null, null, '按供应商聚合采购金额与订单数，默认 Top 8。'];
        }

        foreach ($topProducts as $row) {
            $rows[] = ['商品结构', $row['name'], $row['amount'], $row['quantity'], (string) $row['order_count'], null, null, null, '按商品聚合采购金额、数量与订单数，默认 Top 8。'];
        }

        return $rows;
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<list<string|null>>
     */
    private function inventoryAnalysisRows(array $filters): array
    {
        $summary = $this->inventoryAnalysisReportService->summary($filters);
        $trend = $this->inventoryAnalysisReportService->dailyFlowTrend($filters);
        $topProducts = $this->inventoryAnalysisReportService->topProductsByFlow($filters, 8);
        $topWarehouses = $this->inventoryAnalysisReportService->topWarehousesByFlow($filters, 8);

        $rows = [
            ['核心汇总', '库存维度数', (string) $summary['sku_location_count'], null, null, null, null, null, '按仓库与规格组合汇总当前库存结余行数。'],
            ['核心汇总', '现存量 / 可售量', (string) $summary['realtime_quantity_total'], (string) $summary['available_quantity_total'], null, null, null, null, '结余类指标为当前库存余额快照。'],
            ['核心汇总', '预警 SKU 数', (string) $summary['warning_sku_count'], null, null, null, null, null, '按当前库存预警规则命中结果统计。'],
            ['核心汇总', '区间入库 / 区间出库', (string) $summary['period_inbound_quantity'], (string) $summary['period_outbound_quantity'], null, null, null, null, '按库存流水业务时间在区间内汇总。'],
            ['核心汇总', '待处理库存异常 / 盘点差异', (string) $summary['open_exception_count'], (string) $summary['pending_stocktake_difference_count'], null, null, null, null, '异常按发生时间，盘点差异按创建时间统计。'],
        ];

        foreach ($trend as $row) {
            $rows[] = ['出入库趋势', $row['date'], $row['inbound'], $row['outbound'], null, null, null, null, '按业务日汇总入库量与出库量。'];
        }

        foreach ($topProducts as $row) {
            $rows[] = ['商品结构', $row['name'], $row['inbound'], $row['outbound'], null, null, null, null, '按商品汇总区间流量，默认 Top 8。'];
        }

        foreach ($topWarehouses as $row) {
            $rows[] = ['仓库结构', $row['name'], $row['inbound'], $row['outbound'], null, null, null, null, '按仓库汇总区间流量，默认 Top 8。'];
        }

        return $rows;
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<list<string|null>>
     */
    private function settlementAnalysisRows(array $filters): array
    {
        $summary = $this->settlementAnalysisReportService->summary($filters);
        $receiptTrend = $this->settlementAnalysisReportService->dailyReceiptTrend($filters);
        $paymentTrend = $this->settlementAnalysisReportService->dailyPaymentTrend($filters);
        $topCustomers = $this->settlementAnalysisReportService->topCustomersByRemaining($filters, 8);
        $topSuppliers = $this->settlementAnalysisReportService->topSuppliersByRemaining($filters, 8);
        $receivableAging = $this->settlementAnalysisReportService->receivableAgingBuckets($filters);
        $payableAging = $this->settlementAnalysisReportService->payableAgingBuckets($filters);

        $rows = [
            ['核心汇总', '应收 / 应付余额', (string) $summary['receivable_remaining_total'], (string) $summary['payable_remaining_total'], null, null, null, null, '仅统计仍有余额且未作废的往来记录。'],
            ['核心汇总', '区间收款 / 区间付款', (string) $summary['receipt_amount_period'], (string) $summary['payment_amount_period'], null, null, null, null, '仅统计已确认收付款登记。'],
            ['核心汇总', '已确认核销 / 已确认对账', (string) $summary['write_off_confirmed_count'], (string) $summary['statement_confirmed_count'], null, null, null, null, '分别按核销单、对账单业务日期统计。'],
            ['核心汇总', '未核销收款 / 未核销付款', (string) $summary['receipt_unwritten_count'], (string) $summary['payment_unwritten_count'], null, null, null, null, '按资金使用状态仍为未核销统计。'],
            ['核心汇总', '应收逾期 / 应付逾期', (string) $summary['receivable_overdue_open_count'], (string) $summary['payable_overdue_open_count'], null, null, null, null, '逾期判断以统计截至日期为准。'],
        ];

        foreach ($receiptTrend as $row) {
            $rows[] = ['收款趋势', $row['date'], $row['amount'], null, null, null, null, null, '按业务日汇总已确认收款金额。'];
        }

        foreach ($paymentTrend as $row) {
            $rows[] = ['付款趋势', $row['date'], $row['amount'], null, null, null, null, null, '按业务日汇总已确认付款金额。'];
        }

        foreach ($topCustomers as $row) {
            $rows[] = ['客户结构', $row['name'], $row['amount'], null, null, null, null, null, '按客户汇总未结应收余额，默认 Top 8。'];
        }

        foreach ($topSuppliers as $row) {
            $rows[] = ['供应商结构', $row['name'], $row['amount'], null, null, null, null, null, '按供应商汇总未结应付余额，默认 Top 8。'];
        }

        foreach ($receivableAging as $bucket => $amount) {
            $rows[] = ['应收账龄', $bucket, $amount, null, null, null, null, null, (string) __('dberp.resources.settlement_analysis.export_note_receivable_aging')];
        }

        foreach ($payableAging as $bucket => $amount) {
            $rows[] = ['应付账龄', $bucket, $amount, null, null, null, null, null, (string) __('dberp.resources.settlement_analysis.export_note_payable_aging')];
        }

        return $rows;
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<list<string|null>>
     */
    private function settlementAgingAnalysisRows(array $filters): array
    {
        $normalized = $this->settlementAgingAnalysisService->normalizeFilters($filters);
        $analysis = $this->settlementAgingAnalysisService->analyze($normalized);
        $sideLabel = __('dberp.options.settlement_business_side')[$normalized['settlement_side']] ?? $normalized['settlement_side'];

        $rows = [
            [
                '筛选条件',
                '结算方向',
                $sideLabel,
                '统计截至日期',
                $normalized['as_of_date'],
                $normalized['counterparty_id'] > 0 ? (string) $normalized['counterparty_id'] : '全部',
                null,
                null,
                '导出继承当前账龄分析页筛选。',
            ],
        ];

        $bucketLabels = [
            'current_amount' => __('dberp.resources.settlement_analysis.bucket_current'),
            'bucket_1_30_amount' => __('dberp.resources.settlement_analysis.bucket_1_30'),
            'bucket_31_60_amount' => __('dberp.resources.settlement_analysis.bucket_31_60'),
            'bucket_61_90_amount' => __('dberp.resources.settlement_analysis.bucket_61_90'),
            'bucket_91_plus_amount' => __('dberp.resources.settlement_analysis.bucket_91_plus'),
            'total_amount' => __('dberp.resources.settlement_aging_analysis.col_total'),
        ];

        foreach ($bucketLabels as $key => $label) {
            $rows[] = [
                (string) __('dberp.resources.settlement_aging_analysis.section_bucket_summary'),
                $label,
                DberpNumberFormatter::money($analysis['totals'][$key] ?? 0),
                null,
                null,
                null,
                null,
                null,
                (string) __('dberp.resources.settlement_aging_analysis.export_note_aging_detail'),
            ];
        }

        foreach ($analysis['rows'] as $row) {
            $rows[] = [
                '按往来对象',
                (string) $row['counterparty_name'],
                (string) $row['record_count'],
                DberpNumberFormatter::money($row['current_amount'] ?? 0),
                DberpNumberFormatter::money($row['bucket_1_30_amount'] ?? 0),
                DberpNumberFormatter::money($row['bucket_31_60_amount'] ?? 0),
                DberpNumberFormatter::money($row['bucket_61_90_amount'] ?? 0),
                DberpNumberFormatter::money($row['bucket_91_plus_amount'] ?? 0),
                '合计 '.DberpNumberFormatter::money($row['total_amount'] ?? 0),
            ];
        }

        return $rows;
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<list<string|null>>
     */
    private function comprehensiveSummaryRows(array $filters): array
    {
        $salesSummary = $this->comprehensiveSummaryAnalysisService->salesSummary($filters);
        $purchaseSummary = $this->comprehensiveSummaryAnalysisService->purchaseSummary($filters);
        $inventorySummary = $this->comprehensiveSummaryAnalysisService->inventorySummary($filters);
        $settlementSummary = $this->comprehensiveSummaryAnalysisService->settlementSummary($filters);
        $trendOverview = $this->comprehensiveSummaryAnalysisService->trendOverview($filters);

        $rows = [
            ['销售摘要', '销售单数 / 销售金额', (string) $salesSummary['order_count'], (string) $salesSummary['final_amount'], null, null, null, null, '销售摘要沿用销售分析页统计说明。'],
            ['销售摘要', '未收金额 / 全部出库单数', (string) $salesSummary['unreceived_amount'], (string) $salesSummary['fully_shipped_order_count'], null, null, null, null, '不额外扩展毛利与成本统计。'],
            ['采购摘要', '采购单数 / 采购金额', (string) $purchaseSummary['order_count'], (string) $purchaseSummary['total_amount'], null, null, null, null, '采购摘要沿用采购分析页统计说明。'],
            ['采购摘要', '未付金额 / 超期待到货单数', (string) $purchaseSummary['unpaid_amount'], (string) $purchaseSummary['overdue_arrival_order_count'], null, null, null, null, '超期判断按当前日期即时判断。'],
            ['库存摘要', '现存量 / 可售量', (string) $inventorySummary['realtime_quantity_total'], (string) $inventorySummary['available_quantity_total'], null, null, null, null, '库存摘要沿用库存分析页统计说明。'],
            ['库存摘要', '库存预警 / 库存异常', (string) $inventorySummary['warning_sku_count'], (string) $inventorySummary['open_exception_count'], null, null, null, null, '异常与预警继续使用既有规则结果。'],
            ['结算摘要', '应收余额 / 应付余额', (string) $settlementSummary['receivable_remaining_total'], (string) $settlementSummary['payable_remaining_total'], null, null, null, null, '结算摘要沿用往来结算分析页统计说明。'],
            ['结算摘要', '区间收款 / 区间付款', (string) $settlementSummary['receipt_amount_period'], (string) $settlementSummary['payment_amount_period'], null, null, null, null, '收付款金额按已确认登记单汇总。'],
            ['结算摘要', '应收逾期 / 应付逾期笔数', (string) $settlementSummary['receivable_overdue_open_count'], (string) $settlementSummary['payable_overdue_open_count'], null, null, null, null, '逾期按统计结束日判断。'],
        ];

        foreach ($trendOverview as $row) {
            $rows[] = ['日趋势', $row['date'], $row['sales_amount'], $row['purchase_amount'], $row['inbound_quantity'], $row['outbound_quantity'], $row['receipt_amount'], $row['payment_amount'], '按业务日汇总。'];
        }

        return $rows;
    }

    /**
     * @param  array<string, mixed>  $filters
     */
    private function formatFilters(array $filters): string
    {
        $pairs = [];

        foreach ($this->flattenFilters($filters) as $key => $value) {
            $pairs[] = $key.'='.$value;
        }

        return $pairs === [] ? '当前为默认筛选' : implode('；', $pairs);
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, string>
     */
    private function flattenFilters(array $filters, string $prefix = ''): array
    {
        $flattened = [];

        foreach ($filters as $key => $value) {
            $fullKey = $prefix === '' ? (string) $key : $prefix.'.'.$key;

            if (is_array($value)) {
                $flattened = array_merge($flattened, $this->flattenFilters($value, $fullKey));

                continue;
            }

            $flattened[$fullKey] = is_bool($value) ? ($value ? '是' : '否') : (string) $value;
        }

        return $flattened;
    }

    private function fieldBoundary(string $reportKey): string
    {
        return match ($reportKey) {
            'sales-analysis', 'purchase-analysis', 'inventory-analysis', 'settlement-analysis', 'settlement-aging-analysis', 'comprehensive-summary-analysis' => '仅导出当前分析页已展示的汇总与趋势字段，不额外展开底层单据明细。',
            'audit-log' => '仅导出审计列表基础字段，不额外展开完整变更前后镜像。',
            default => '仅导出当前报表列表已展示字段，不额外展开关联明细、快照行或未展示字段。',
        };
    }

    private function normalizeFilters(array $tableFilters): array
    {
        $normalized = [];

        foreach ($tableFilters as $key => $value) {
            if (is_array($value) && array_key_exists('value', $value)) {
                $normalized[$key] = $value['value'];

                continue;
            }

            if (is_array($value)) {
                foreach ($value as $subKey => $subValue) {
                    if (is_int($subKey)) {
                        continue;
                    }

                    $normalized[$subKey === 'value' ? $key : $key.'_'.$subKey] = $subValue;
                }

                continue;
            }

            $normalized[$key] = $value;
        }

        return $normalized;
    }
}
