<?php

namespace Kylin\Export\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Kylin\Core\ApiResponse;
use Kylin\Core\Controllers\BaseController;
use Kylin\Export\Models\Export;
use Kylin\Export\Services\DownloadToken;
use Kylin\Export\Services\ExportService;
use Symfony\Component\HttpFoundation\StreamedResponse;

/**
 * 导出控制器
 *
 * 提供数据导出任务的创建、查询和下载 API。
 *
 * 合规要求：
 *  - 依据等保 2.0 (GB/T 22239) 8.1.4.1，导出操作需进行访问控制
 *  - 依据《数据安全法》第二十一条，下载需 Token 验证
 */
class ExportController extends BaseController
{
    public function __construct(private readonly ExportService $service) {}

    public function index(Request $request): JsonResponse
    {
        $this->authorize('viewAny', Export::class);

        $exports = Export::where('user_id', $request->user()->id)
            ->orderByDesc('id')
            ->paginate($request->input('per_page', 15));
        return ApiResponse::paginate($exports);
    }

    public function store(Request $request): JsonResponse
    {
        $this->authorize('create', Export::class);

        $data = $request->validate([
            'type' => 'required|string|max:50',
            'filename' => 'required|string|max:255',
            'filters' => 'nullable|array',
        ]);
        $export = $this->service->create($data['type'], $data['filename'], $data['filters'] ?? null, $request->user()->id);

        // 生成下载 Token
        $token = DownloadToken::generate($export->id, $request->user()->id);

        return ApiResponse::created([
            'export' => $export,
            'download_token' => $token,
            'token_expires_in_minutes' => DownloadToken::ttl(),
        ]);
    }

    public function show(int $id): JsonResponse
    {
        $this->authorize('view', Export::findOrFail($id));

        return ApiResponse::success(Export::findOrFail($id));
    }

    public function download(int $id, Request $request): StreamedResponse
    {
        $export = Export::findOrFail($id);

        // Token 验证
        $token = $request->query('token') ?? $request->bearerToken();
        if (! $token || ! DownloadToken::verify($token, $id)) {
            abort(403, '下载链接无效或已过期，请重新请求导出。');
        }

        abort_if($export->status !== 'completed' || ! $export->path, 404, '文件不存在');

        // 下载审计
        $this->service->auditExportDownload($export);

        return Storage::download($export->path, $export->filename);
    }
}