<?php

declare(strict_types=1);

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

namespace App\Http\Controllers;

use App\Business\Inventory\InventoryWarningService;
use App\Models\DberpInventoryBalance;
use App\Services\DberpAuditService;
use App\Services\DberpPermissionService;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

final class InventoryWarningExportController extends Controller
{
    public function __invoke(Request $request, InventoryWarningService $warningService, DberpPermissionService $permissionService, DberpAuditService $auditService): StreamedResponse
    {
        abort_unless($permissionService->allowsReportExport($request->user(), 'inventory-warning-report'), 403);

        $query = $warningService->query()
            ->when($request->integer('warehouse_id') > 0, fn ($builder) => $builder->where('warehouse_id', $request->integer('warehouse_id')))
            ->when($request->integer('product_id') > 0, fn ($builder) => $builder->where('product_id', $request->integer('product_id')))
            ->when($request->integer('category_id') > 0, fn ($builder) => $builder->whereHas('product', fn ($productQuery) => $productQuery->where('category_id', $request->integer('category_id'))))
            ->when(in_array($request->string('warning_type')->toString(), ['low_stock', 'zero_stock'], true), function ($builder) use ($request): void {
                $warningType = $request->string('warning_type')->toString();

                if ($warningType === 'zero_stock') {
                    $builder->zeroStock();

                    return;
                }

                $builder->lowStock();
            })
            ->orderBy('warehouse_id')
            ->orderBy('product_id');

        /** @var \Illuminate\Database\Eloquent\Collection<int, DberpInventoryBalance> $balances */
        $balances = $query->get();

        $auditService->log('dberp.report.exported', null, null, [
            'report_name' => '库存预警',
            'report_key' => 'inventory-warning-report',
            'filter_summary' => $this->filterSummary($request),
            'column_scope' => '商品编码、商品名称、商品分类、仓库、实时库存、可用库存、安全库存、预警类型、最近变动时间',
            'field_boundary' => '仅导出库存预警列表已展示字段，不额外展开库存明细或批次快照。',
            'row_count' => $balances->count(),
        ]);

        return response()->streamDownload(function () use ($balances, $warningService): void {
            echo "\xEF\xBB\xBF";

            $handle = fopen('php://output', 'wb');

            if ($handle === false) {
                return;
            }

            fputcsv($handle, ['商品编码', '商品名称', '商品分类', '仓库', '实时库存', '可用库存', '安全库存', '预警类型', '最近变动时间']);

            foreach ($balances as $balance) {
                fputcsv($handle, [
                    $balance->product?->code,
                    $balance->product?->name,
                    $balance->product?->category?->name,
                    $balance->warehouse?->name,
                    (string) $balance->realtime_quantity,
                    (string) $balance->available_quantity,
                    (string) $balance->safety_stock,
                    $warningService->warningTypeLabel($balance),
                    $balance->last_moved_at?->format('Y-m-d H:i:s'),
                ]);
            }

            fclose($handle);
        }, 'inventory-warnings-'.now()->format('Ymd_His').'.csv', [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ]);
    }

    private function filterSummary(Request $request): string
    {
        $pairs = [];

        foreach (['warehouse_id', 'product_id', 'category_id', 'warning_type'] as $key) {
            $value = $request->input($key);

            if ($value === null || $value === '') {
                continue;
            }

            $pairs[] = $key.'='.(string) $value;
        }

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