<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Business;
use App\Models\Document;
use App\Models\DocumentData;
use App\Models\DocumentHistory;
use App\Support\ApiResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class DocumentController extends Controller
{
    private const TYPE_MAP = [
        'SalesInvoice' => 'SalesInvoice',
        'PurchaseInvoice' => 'PurchaseInvoice',
        'BankStatement' => 'BankStatement',
        'OtherDocuments' => 'OtherDocuments',
        'Other' => 'OtherDocuments',
    ];

    private const STATUS_VALUES = [
        'Uploaded', 'Data Entered', 'Processing', 'Processed', 'Exported', 'Review', 'Deleted',
    ];

    private function assertBusiness(Request $request, int $businessId): Business
    {
        $user = $request->user();
        $query = Business::query()->where('id', $businessId);
        if ($user->role === 'client') {
            $query->where('user_id', $user->id);
        }
        return $query->firstOrFail();
    }

    public function listByType(Request $request, int $businessId, string $docType)
    {
        $this->assertBusiness($request, $businessId);
        $type = self::TYPE_MAP[$docType] ?? null;
        if (!$type) {
            return ApiResponse::error('Invalid document type', null, 422);
        }

        $hasPaging = $request->has('page') || $request->has('pageSize');
        $page = max(1, (int) $request->query('page', 1));
        $pageSize = max(1, (int) $request->query('pageSize', 10));
        $status = $request->query('status');
        $sortColumn = $request->query('sortColumn', 'Date');
        $sortOrder = strtolower($request->query('sortOrder', 'desc')) === 'asc' ? 'asc' : 'desc';

        $column = match (strtolower($sortColumn)) {
            'name' => 'file_name',
            'status' => 'status',
            default => 'uploaded_date',
        };

        $q = Document::with(['data', 'contact'])
            ->where('business_id', $businessId)
            ->where('document_type', $type)
            ->where('is_deleted', false)
            ->orderBy($column, $sortOrder);

        if ($status) {
            $q->where('status', $status);
        }

        if (!$hasPaging) {
            $docs = $q->get();
            return ApiResponse::success('Documents fetched', [
                'documents' => $docs,
                'items' => $docs,
                'pagination' => [
                    'currentPage' => 1,
                    'totalPages' => 1,
                    'totalRecords' => $docs->count(),
                    'pageSize' => $docs->count(),
                ],
            ]);
        }

        $paginator = $q->paginate($pageSize, ['*'], 'page', $page);
        return ApiResponse::paginated('Documents fetched', $paginator);
    }

    public function internalListByType(Request $request, int $businessId, string $docType)
    {
        $type = self::TYPE_MAP[$docType] ?? null;
        if (!$type) {
            return ApiResponse::error('Invalid document type', null, 422);
        }

        $business = Business::with('subscription')->findOrFail($businessId);

        $page = max(1, (int) $request->query('page', 1));
        $pageSize = max(1, (int) $request->query('pageSize', 10));
        $status = $request->query('status');
        $sortOrder = strtolower($request->query('sortOrder', 'desc')) === 'asc' ? 'asc' : 'desc';

        $q = Document::with(['data', 'contact'])
            ->where('business_id', $businessId)
            ->where('document_type', $type)
            ->where('is_deleted', false)
            ->orderBy('uploaded_date', $sortOrder);
        if ($status) $q->where('status', $status);

        $paginator = $q->paginate($pageSize, ['*'], 'page', $page);

        // Internal data-entry view groups docs under a "company" wrapper.
        $companyInfo = [
            'name'               => $business->business_name,
            'industry'           => $business->business_type,
            'country'            => null,
            'credit'             => $business->subscription?->document_limit ?? 0,
            'software'           => null,
            'duplicate'          => null,
            'vat'                => null,
            'vatScheme'          => null,
            'subscriptionStatus' => $business->subscription?->status,
            'subscriptionPlan'   => $business->subscription?->plan,
            'processingStatus'   => 'Processing',
            'dataEntryBy'        => 0,
            'dataEntryTime'      => null,
            'reviewedBy'         => 0,
            'reviewedTime'       => null,
            'source'             => 'web',
        ];

        return ApiResponse::success('Internal documents', [
            'docs' => [array_merge($companyInfo, [
                'documents' => $paginator->items(),
            ])],
            'pagination' => [
                'currentPage'  => $paginator->currentPage(),
                'totalPages'   => $paginator->lastPage(),
                'totalRecords' => $paginator->total(),
                'pageSize'     => $paginator->perPage(),
            ],
        ]);
    }

    public function deletedList(Request $request, int $businessId)
    {
        $this->assertBusiness($request, $businessId);
        $sortOrder = strtolower($request->query('sortOrder', 'desc')) === 'asc' ? 'asc' : 'desc';
        $docs = Document::with('data')
            ->where('business_id', $businessId)
            ->where('is_deleted', true)
            ->orderBy('uploaded_date', $sortOrder)
            ->get();
        return ApiResponse::success('Deleted documents', [
            'documents' => $docs,
            'items' => $docs,
            'pagination' => [
                'currentPage' => 1,
                'totalPages' => 1,
                'totalRecords' => $docs->count(),
                'pageSize' => $docs->count(),
            ],
        ]);
    }

    public function internalList(Request $request)
    {
        // The internal "View All Entity List" screen expects one row per business,
        // summarising how much pending work each entity has — NOT a flat list of
        // documents. Aggregate accordingly.
        $page = max(1, (int) $request->query('page', 1));
        $pageSize = max(1, (int) $request->query('pageSize', 10));

        // Statuses that still need attention from data-entry / supervisors.
        $pendingStatus = 'Uploaded';
        $inProcessStatuses = ['Processing', 'Data Entered', 'Review'];

        $businesses = Business::with('subscription')
            ->whereHas('documents', function ($q) use ($pendingStatus, $inProcessStatuses) {
                $q->where('is_deleted', false)
                  ->whereIn('status', array_merge([$pendingStatus], $inProcessStatuses));
            })
            ->get();

        $rows = $businesses->map(function (Business $business) use ($pendingStatus, $inProcessStatuses) {
            $docs = Document::where('business_id', $business->id)
                ->where('is_deleted', false)
                ->get(['document_type', 'status', 'uploaded_date']);

            $pendingDocs = $docs->where('status', $pendingStatus);
            $pendingOf = fn (string $type) => $pendingDocs->where('document_type', $type)->count();
            $inProcess = $docs->whereIn('status', $inProcessStatuses)->count();

            return [
                'organization'             => $business->business_name,
                'status'                   => $business->subscription?->status ?? 'Active',
                'remainingCredits'         => $business->subscription?->document_limit ?? 0,
                'processingCredits'        => $inProcess,
                'estimatedCredits'         => $pendingDocs->count(),
                'entityName'               => $business->business_name,
                'entityId'                 => $business->id,
                'businessId'               => $business->id,
                'oldestDocElapsedTime'     => $pendingDocs->min('uploaded_date'),
                'latestDocElapsedTime'     => $pendingDocs->max('uploaded_date'),
                'elapsedLoginTime'         => null,
                'pendingPurchaseInvoices'  => $pendingOf('PurchaseInvoice'),
                'pendingSalesInvoices'     => $pendingOf('SalesInvoice'),
                'pendingStatements'        => $pendingOf('BankStatement'),
                'pendingSplittedDocuments' => 0,
                'pendingDocuments'         => $pendingOf('OtherDocuments'),
                'inProcess'                => $inProcess,
            ];
        })->values();

        // Paginate over the aggregated rows.
        $total = $rows->count();
        $paged = $rows->forPage($page, $pageSize)->values();

        return ApiResponse::success('Internal documents', [
            'documents' => $paged,
            'items' => $paged,
            'pagination' => [
                'currentPage' => $page,
                'totalPages' => max(1, (int) ceil($total / max(1, $pageSize))),
                'totalRecords' => $total,
                'pageSize' => $pageSize,
            ],
        ]);
    }

    public function upload(Request $request)
    {
        // Frontend sends multipart FormData with mixed casing — accept both.
        $businessId   = (int) ($request->input('BusinessId') ?? $request->input('businessId') ?? 0);
        $documentType = $request->input('DocumentType') ?? $request->input('documentType');

        if (!$businessId) return ApiResponse::error('businessId is required', null, 422);
        if (!$documentType) return ApiResponse::error('documentType is required', null, 422);

        $business = $this->assertBusiness($request, $businessId);
        $type = self::TYPE_MAP[$documentType] ?? null;
        if (!$type) {
            return ApiResponse::error('Invalid document type: ' . $documentType, null, 422);
        }

        // Files can come as `Files` (multiple) or `file` (single).
        $files = $request->file('Files') ?? $request->file('files') ?? $request->file('file');
        if (!$files) {
            return ApiResponse::error('No files received', null, 422);
        }
        if (!is_array($files)) $files = [$files];

        $created = [];
        foreach ($files as $file) {
            $guid = (string) \Illuminate\Support\Str::uuid();
            $fileName = $guid . '_' . $file->getClientOriginalName();
            $stored = $file->storeAs("Uploads/Documents/{$type}", $fileName, 'public');

            $doc = Document::create([
                'business_id'   => $business->id,
                'document_type' => $type,
                'file_name'     => $file->getClientOriginalName(),
                'file_url'      => Storage::url($stored),
                'mime_type'     => $file->getClientMimeType(),
                'file_size'     => $file->getSize(),
                'status'        => 'Uploaded',
                'uploaded_by'   => $request->user()->id,
                'uploaded_date' => now(),
            ]);

            DocumentHistory::create([
                'document_id' => $doc->id,
                'user_id'     => $request->user()->id,
                'action'      => 'Uploaded',
                'to_status'   => 'Uploaded',
            ]);

            $created[] = $doc;
        }

        return ApiResponse::success(
            count($created) === 1 ? 'Document uploaded' : count($created) . ' documents uploaded',
            count($created) === 1 ? $created[0] : $created
        );
    }

    public function show(Request $request, int $documentId)
    {
        $doc = Document::with(['data', 'business', 'contact', 'history'])->findOrFail($documentId);
        return ApiResponse::success('Document', $doc);
    }

    public function exportDocument(Request $request)
    {
        $docId = (int) $request->query('doc');
        if (!$docId) return ApiResponse::error('doc query parameter required', null, 422);
        $doc = Document::findOrFail($docId);
        $path = ltrim(parse_url($doc->file_url, PHP_URL_PATH) ?? '', '/');
        $fullPath = public_path($path);
        if (!is_file($fullPath)) {
            $fullPath = storage_path('app/public/' . preg_replace('#^/?storage/#', '', $path));
        }
        if (!is_file($fullPath)) {
            return ApiResponse::error('File not found', null, 404);
        }
        return response()->download($fullPath, $doc->file_name);
    }

    public function getImage(Request $request)
    {
        $url = $request->query('url');
        if (!$url) return ApiResponse::error('URL required', null, 422);

        // Accept either a full URL or a relative path. Strip query/fragment.
        $path = parse_url($url, PHP_URL_PATH) ?? $url;
        $path = ltrim($path, '/');

        // Common shapes we may receive:
        //   storage/Uploads/Documents/...           (already public-relative)
        //   Uploads/Documents/...                   (raw stored path on the public disk)
        //   /full/host/path/storage/Uploads/...     (after parse_url strips host)
        $candidates = [
            public_path($path),
            storage_path('app/public/' . preg_replace('#^storage/#', '', $path)),
            storage_path('app/public/' . $path),
        ];

        $fullPath = null;
        foreach ($candidates as $c) {
            if ($c && is_file($c)) { $fullPath = $c; break; }
        }
        if (!$fullPath) {
            return ApiResponse::error('File not found at ' . $path, null, 404);
        }

        $mime = mime_content_type($fullPath) ?: 'application/octet-stream';
        return response()->file($fullPath, [
            'Content-Type' => $mime,
            'Cache-Control' => 'private, max-age=300',
            'Content-Disposition' => 'inline; filename="' . basename($fullPath) . '"',
        ]);
    }

    public function markExported(Request $request)
    {
        // Frontend may send { documents_ids: [...], status: "Exported" }
        // OR a bare array of IDs. Handle both.
        $payload = $request->isJson() ? $request->json()->all() : $request->all();
        $ids    = [];
        $status = 'Exported';

        if (is_array($payload)) {
            if (isset($payload['documents_ids']) && is_array($payload['documents_ids'])) {
                $ids    = $payload['documents_ids'];
                $status = $payload['status'] ?? 'Exported';
            } elseif (array_is_list($payload)) {
                $ids = $payload;
            }
        }

        $ids = array_values(array_filter(array_map('intval', $ids)));
        if (empty($ids)) {
            return ApiResponse::error('No document IDs provided', null, 422);
        }

        Document::whereIn('id', $ids)->update([
            'status'         => $status,
            'processed_date' => now(),
            'processed_by'   => $request->user()->id,
        ]);

        foreach ($ids as $id) {
            DocumentHistory::create([
                'document_id' => $id,
                'user_id'     => $request->user()->id,
                'action'      => $status,
                'to_status'   => $status,
            ]);
        }

        return ApiResponse::success('Documents updated', ['count' => count($ids), 'status' => $status]);
    }

    public function saveData(Request $request, int $id)
    {
        $doc = Document::findOrFail($id);
        $payload = $request->all();

        DocumentData::updateOrCreate(
            ['document_id' => $doc->id],
            [
                'invoice_number' => $payload['invoiceNumber'] ?? $payload['invoice_number'] ?? null,
                'supplier_id' => $payload['supplierId'] ?? $payload['supplier_id'] ?? null,
                'customer_id' => $payload['customerId'] ?? $payload['customer_id'] ?? null,
                'document_date' => $payload['documentDate'] ?? $payload['document_date'] ?? null,
                'due_date' => $payload['dueDate'] ?? $payload['due_date'] ?? null,
                'subtotal' => $payload['subtotal'] ?? 0,
                'tax_total' => $payload['taxTotal'] ?? $payload['tax_total'] ?? 0,
                'total_amount' => $payload['totalAmount'] ?? $payload['total_amount'] ?? 0,
                'currency' => $payload['currency'] ?? null,
                'description' => $payload['description'] ?? null,
                'line_items' => $payload['lineItems'] ?? $payload['items'] ?? null,
                'extracted_data' => $payload['extractedData'] ?? null,
            ]
        );

        $doc->status = 'Data Entered';
        $doc->processed_by = $request->user()->id;
        $doc->processed_date = now();
        $doc->save();

        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id' => $request->user()->id,
            'action' => 'Data Entered',
            'to_status' => 'Data Entered',
        ]);

        return ApiResponse::success('Document saved', $doc->load('data'));
    }

    public function reAssign(Request $request, int $id)
    {
        $status = $request->query('status', 'Review');
        if (!in_array($status, self::STATUS_VALUES, true)) {
            return ApiResponse::error('Invalid status', null, 422);
        }
        $doc = Document::findOrFail($id);
        $from = $doc->status;
        $doc->status = $status;
        $doc->save();
        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id' => $request->user()->id,
            'action' => 'Reassigned',
            'from_status' => $from,
            'to_status' => $status,
        ]);
        return ApiResponse::success('Document reassigned', $doc);
    }

    public function updateStatus(Request $request, string $status, int $id)
    {
        if (!in_array($status, self::STATUS_VALUES, true)) {
            return ApiResponse::error('Invalid status', null, 422);
        }
        $doc = Document::findOrFail($id);
        $from = $doc->status;
        $doc->status = $status;
        if (in_array($status, ['Processed', 'Exported', 'Data Entered'])) {
            $doc->processed_by = $request->user()->id;
            $doc->processed_date = now();
        }
        $doc->save();

        if ($request->isJson() && is_array($request->json()->all())) {
            $payload = $request->json()->all();
            if (!empty($payload) && (isset($payload['invoiceNumber']) || isset($payload['totalAmount']) || isset($payload['lineItems']))) {
                DocumentData::updateOrCreate(
                    ['document_id' => $doc->id],
                    [
                        'invoice_number' => $payload['invoiceNumber'] ?? null,
                        'supplier_id' => $payload['supplierId'] ?? null,
                        'customer_id' => $payload['customerId'] ?? null,
                        'document_date' => $payload['documentDate'] ?? null,
                        'due_date' => $payload['dueDate'] ?? null,
                        'subtotal' => $payload['subtotal'] ?? 0,
                        'tax_total' => $payload['taxTotal'] ?? 0,
                        'total_amount' => $payload['totalAmount'] ?? 0,
                        'currency' => $payload['currency'] ?? null,
                        'description' => $payload['description'] ?? null,
                        'line_items' => $payload['lineItems'] ?? null,
                    ]
                );
            }
        }

        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id' => $request->user()->id,
            'action' => $status,
            'from_status' => $from,
            'to_status' => $status,
        ]);

        return ApiResponse::success('Status updated', $doc->load('data'));
    }

    public function attachDoc(Request $request, int $id)
    {
        $request->validate(['file' => 'required|file|max:51200']);
        $doc = Document::findOrFail($id);
        $file = $request->file('file');
        $guid = (string) \Illuminate\Support\Str::uuid();
        $fileName = $guid . '_' . $file->getClientOriginalName();
        $stored = $file->storeAs('Uploads/Documents/' . $doc->document_type, $fileName, 'public');
        $doc->file_name = $file->getClientOriginalName();
        $doc->file_url = Storage::url($stored);
        $doc->mime_type = $file->getClientMimeType();
        $doc->file_size = $file->getSize();
        $doc->save();
        return ApiResponse::success('File attached', $doc);
    }

    public function reclassify(Request $request)
    {
        // Frontend sends { documents_Id: [...], doctype: "SalesInvoice" }
        // OR an array of row objects { id, documentType }
        $payload = $request->isJson() ? $request->json()->all() : $request->all();

        if (is_array($payload) && isset($payload['documents_Id']) && is_array($payload['documents_Id'])) {
            $type = self::TYPE_MAP[$payload['doctype'] ?? ''] ?? null;
            if (!$type) {
                return ApiResponse::error('Invalid document type', null, 422);
            }
            $ids = array_values(array_filter(array_map('intval', $payload['documents_Id'])));
            if (empty($ids)) {
                return ApiResponse::error('No document IDs provided', null, 422);
            }
            Document::whereIn('id', $ids)->update(['document_type' => $type]);
            foreach ($ids as $id) {
                DocumentHistory::create([
                    'document_id' => $id,
                    'user_id'     => $request->user()->id,
                    'action'      => 'Reclassified',
                    'notes'       => 'Type changed to ' . $type,
                ]);
            }
            return ApiResponse::success('Documents reclassified', ['updated' => count($ids)]);
        }

        if (!is_array($payload)) $payload = [];
        $updated = 0;
        foreach ($payload as $row) {
            $id = $row['id'] ?? null;
            $type = $row['documentType'] ?? $row['type'] ?? null;
            if (!$id || !$type) continue;
            $type = self::TYPE_MAP[$type] ?? null;
            if (!$type) continue;
            Document::where('id', $id)->update(['document_type' => $type]);
            DocumentHistory::create([
                'document_id' => $id,
                'user_id'     => $request->user()->id,
                'action'      => 'Reclassified',
                'notes'       => 'Type changed to ' . $type,
            ]);
            $updated++;
        }
        return ApiResponse::success('Documents reclassified', ['updated' => $updated]);
    }

    public function deleteDocuments(Request $request)
    {
        // Frontend sends { documents_ids: [...], reason: "..." } OR a bare ID array.
        $payload = $request->isJson() ? $request->json()->all() : $request->all();
        $ids = [];
        $reason = null;

        if (is_array($payload)) {
            if (isset($payload['documents_ids']) && is_array($payload['documents_ids'])) {
                $ids    = $payload['documents_ids'];
                $reason = $payload['reason'] ?? null;
            } elseif (array_is_list($payload)) {
                $ids = $payload;
            }
        }

        $ids = array_values(array_filter(array_map('intval', $ids)));
        if (empty($ids)) {
            return ApiResponse::error('No document IDs provided', null, 422);
        }

        Document::whereIn('id', $ids)->update(['is_deleted' => true, 'status' => 'Deleted']);
        foreach ($ids as $id) {
            DocumentHistory::create([
                'document_id' => $id,
                'user_id'     => $request->user()->id,
                'action'      => 'Deleted',
                'to_status'   => 'Deleted',
                'notes'       => $reason,
            ]);
        }
        return ApiResponse::success('Documents deleted', ['count' => count($ids)]);
    }

    public function destroy(Request $request, int $id)
    {
        $doc = Document::findOrFail($id);
        $doc->is_deleted = true;
        $doc->status = 'Deleted';
        $doc->save();
        return ApiResponse::success('Document deleted', $doc);
    }

    public function history(Request $request)
    {
        $docId = $request->query('doc');
        $history = DocumentHistory::with('user:id,full_name,email')
            ->where('document_id', $docId)
            ->orderByDesc('id')
            ->get();
        return ApiResponse::success('Document history', $history);
    }

    public function byContact(Request $request)
    {
        $contactId = $request->query('contactId');
        $docs = Document::with('data')
            ->whereHas('data', function ($q) use ($contactId) {
                $q->where('supplier_id', $contactId)->orWhere('customer_id', $contactId);
            })
            ->orderByDesc('id')
            ->get();
        return ApiResponse::success('Documents by contact', $docs);
    }

    // -----------------------------------------------------------------------
    // Endpoints required by the .NET swagger spec but absent from earlier work
    // -----------------------------------------------------------------------

    public function exportDataFile(Request $request)
    {
        $docId = (int) $request->query('doc');
        if (!$docId) return ApiResponse::error('doc query parameter required', null, 422);
        $doc = Document::with('data')->findOrFail($docId);
        // Emit a CSV with the structured DocumentData so the client gets a
        // spreadsheet-friendly export (mirrors the .NET API's behaviour).
        $rows = [
            ['Field', 'Value'],
            ['Document ID', $doc->id],
            ['Document Type', $doc->document_type],
            ['File Name', $doc->file_name],
            ['Status', $doc->status],
            ['Uploaded Date', (string) $doc->uploaded_date],
            ['Invoice Number', $doc->data?->invoice_number],
            ['Document Date', (string) $doc->data?->document_date],
            ['Due Date', (string) $doc->data?->due_date],
            ['Supplier ID', $doc->data?->supplier_id],
            ['Customer ID', $doc->data?->customer_id],
            ['Subtotal', $doc->data?->subtotal],
            ['VAT Amount', $doc->data?->vat_amount],
            ['Total Amount', $doc->data?->total_amount],
            ['Currency', $doc->data?->currency],
            ['Description', $doc->data?->description],
        ];
        $handle = fopen('php://temp', 'w+');
        foreach ($rows as $row) fputcsv($handle, $row);
        rewind($handle);
        $csv = stream_get_contents($handle);
        fclose($handle);
        return response($csv, 200, [
            'Content-Type'        => 'text/csv',
            'Content-Disposition' => 'attachment; filename="document-' . $doc->id . '.csv"',
        ]);
    }

    public function transfer(Request $request, int $id, int $businessId)
    {
        $doc = Document::findOrFail($id);
        $business = Business::findOrFail($businessId);
        $oldBusinessId = $doc->business_id;
        $doc->business_id = $business->id;
        $doc->save();
        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id'     => $request->user()->id,
            'action'      => 'Transferred',
            'notes'       => "Transferred from business {$oldBusinessId} to {$business->id}",
        ]);
        return ApiResponse::success('Document transferred', $doc);
    }

    public function approve(Request $request, int $id)
    {
        $doc = Document::findOrFail($id);
        $payload = $request->isJson() ? $request->json()->all() : $request->all();
        DocumentData::updateOrCreate(
            ['document_id' => $doc->id],
            DocumentData::mapFromRequest($payload)
        );
        $from = $doc->status;
        $doc->status        = 'Exported';
        $doc->processed_by  = $request->user()->id;
        $doc->processed_date = now();
        $doc->save();
        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id'     => $request->user()->id,
            'action'      => 'Approved',
            'from_status' => $from,
            'to_status'   => 'Exported',
        ]);
        return ApiResponse::success('Document approved', $doc->load('data'));
    }

    public function processed(Request $request, int $id)
    {
        $doc = Document::findOrFail($id);
        $payload = $request->isJson() ? $request->json()->all() : $request->all();
        DocumentData::updateOrCreate(
            ['document_id' => $doc->id],
            DocumentData::mapFromRequest($payload)
        );
        $from = $doc->status;
        $doc->status        = 'Processed';
        $doc->processed_by  = $request->user()->id;
        $doc->processed_date = now();
        $doc->save();
        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id'     => $request->user()->id,
            'action'      => 'Processed',
            'from_status' => $from,
            'to_status'   => 'Processed',
        ]);
        return ApiResponse::success('Document marked processed', $doc->load('data'));
    }

    public function restore(Request $request, int $id)
    {
        $doc = Document::findOrFail($id);
        $doc->is_deleted = false;
        $doc->status = 'Uploaded';
        $doc->save();
        DocumentHistory::create([
            'document_id' => $doc->id,
            'user_id'     => $request->user()->id,
            'action'      => 'Restored',
            'to_status'   => 'Uploaded',
        ]);
        return ApiResponse::success('Document restored', $doc);
    }

    public function bulkProcess(Request $request)
    {
        $payload = $request->isJson() ? $request->json()->all() : $request->all();
        $ids = $payload['documents_ids'] ?? [];
        $ids = array_values(array_filter(array_map('intval', is_array($ids) ? $ids : [])));
        if (empty($ids)) return ApiResponse::error('No document IDs provided', null, 422);

        $mapped = DocumentData::mapFromRequest($payload);
        foreach ($ids as $docId) {
            DocumentData::updateOrCreate(['document_id' => $docId], $mapped);
            DocumentHistory::create([
                'document_id' => $docId,
                'user_id'     => $request->user()->id,
                'action'      => 'Bulk Processed',
                'to_status'   => 'Processed',
            ]);
        }
        Document::whereIn('id', $ids)->update([
            'status'         => 'Processed',
            'processed_by'   => $request->user()->id,
            'processed_date' => now(),
        ]);
        return ApiResponse::success('Documents processed', ['count' => count($ids)]);
    }

    public function bulkReject(Request $request)
    {
        $payload = $request->isJson() ? $request->json()->all() : $request->all();
        $ids = $payload['documents_ids'] ?? [];
        $ids = array_values(array_filter(array_map('intval', is_array($ids) ? $ids : [])));
        $status = $payload['status'] ?? 'Review';
        if (empty($ids)) return ApiResponse::error('No document IDs provided', null, 422);

        Document::whereIn('id', $ids)->update(['status' => $status]);
        foreach ($ids as $docId) {
            DocumentHistory::create([
                'document_id' => $docId,
                'user_id'     => $request->user()->id,
                'action'      => 'Bulk Rejected',
                'to_status'   => $status,
            ]);
        }
        return ApiResponse::success('Documents updated', ['count' => count($ids), 'status' => $status]);
    }
}
