<?php

namespace App\Http\Controllers\Assets\Settings;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\SpecialUpload;
use App\Services\BulkUpload\BulkLostStolenService;
use App\Services\BulkUpload\SpecialBulkLostStolenService;
use App\Http\Requests\CsvFileUploadRequest;
use App\Http\Traits\FileSanitizationTrait;
use Illuminate\Support\Facades\Storage;

class BulkLostStolenController extends Controller
{
    use FileSanitizationTrait;

    public function __construct(protected BulkLostStolenService $bulkLostStolen, protected SpecialBulkLostStolenService $specialBulkLostStolen) {}

    public function index()
    {
        session(['asset_count' => 0]);

        return view('settings.bulk-lost-stolen');
    }

    /**
     * Handle the upload of a CSV file for bulk lost or stolen asset updates.
     *
     * This method processes the uploaded file, stores it in a specific directory,
     * and delegates the file processing to the bulkLostStolen service.
     *
     * @param \App\Http\Requests\CsvFileUploadRequest $request
     *        The validated request containing the uploaded CSV file.
     *
     * @return mixed
     *         The response from the bulkLostStolen service after processing the file.
     */
    public function upload(CsvFileUploadRequest $request)
    {
        setUnlimitedExecutionTimeAndMemoryLimit();

        // Get the uploaded file from the request
        $file = $request->file('file');

        // Get the file extension in lowercase
        $extension = strtolower($file->getClientOriginalExtension());

        $fileName = 'lost-stolen-asset-items-' . date("m-d-y") . '-' . time() . '.' . $extension;
        $path = $file->storeAs('public/asset_bulk_lost_stolen', $fileName);

        return $this->bulkLostStolen->getViewData(storage_path('app/' . $path), $fileName);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $errors = [];
        $updatedCount = 0;

        if ($request->count == 0) {
            return redirect(route('bulk-lost-stolen.index'))->with('error', 'Assets cannot be updated.');
        }

        $basePath = storage_path('app/public/asset_bulk_lost_stolen');
        $filePath = $this->sanitizeFilePath($request->filePath, $basePath);
        $fileName = $this->sanitizeFileName($request->fileName);

        for ($i = 1; $i <= $request->count; $i++) {

            if (!$request->has('asset_id' . $i)) {
                continue; //row was deleted before submitting
            }

            $updateResponse = $this->bulkLostStolen->saveData($request->all(), $i);
            if ($updateResponse === false) {
                $errors[] = request('serial_no' . $i);
                continue;
            }

            $updatedCount++;
        }

        $this->bulkLostStolen->attachFiletoTicket(request('ticket_no1'), $filePath, $fileName);
        if (empty($errors)) {

            return redirect(route('bulk-lost-stolen.index'))->with('message', 'Assets updated successfully.');
        }

        if ($request->count != count($errors)) {
            return redirect(route('bulk-lost-stolen.index'))
                ->with([
                    'message' => "Total {$updatedCount} assets updated successfully.",
                    'error' => 'Assets ' . implode(', ', $errors) . ' cannot be updated.',
                ]);
        }

        return redirect(route('bulk-lost-stolen.index'))->with('error', 'Assets cannot be updated.');
    }

    /**
     * Handles the special upload for bulk lost or stolen asset updates.
     *
     * This function sets unlimited execution time and memory for handling large
     * file uploads. It saves the uploaded file in the public/asset_bulk_lost_stolen
     * directory with a unique filename, and processes the file using the
     * specialBulkLostStolen service to import asset data.
     *
     * Validation errors are logged in a timestamped file in the same directory,
     * and the function redirects back to the bulk-lost-stolen.index route with
     * the error details. If other errors occur, they are also logged and the
     * function redirects back with a message indicating partial success along
     * with the error details.
     *
     * On successful completion without errors, the function redirects back to
     * the bulk-lost-stolen.index route with a success message.
     *
     * @param \App\Http\Requests\SpecialUpload $request
     *        The validated request containing the uploaded file for bulk processing.
     *
     * @return \Illuminate\Http\RedirectResponse
     *         A redirect response indicating the outcome of the bulk upload process.
     */
    public function specialUpload(SpecialUpload $request)
    {
        setUnlimitedExecutionTimeAndMemoryLimit();

        $file   = $request->file('bulk_upload_asset');

        $extension  = strtolower($file->getClientOriginalExtension());
        $fileName   = 'lost-stolen-asset-items-' . date("m-d-y") . '-' . time() . '.' . $extension;
        $path       = $file->storeAs('public/asset_bulk_lost_stolen', $fileName);
        $path       = storage_path('app/' . $path);

        $errors = $this->specialBulkLostStolen->importAssetData($path, $fileName);

        if (isset($errors['validationErrors']) && !empty($errors['validationErrors'])) {
            Storage::put('public/asset_bulk_lost_stolen/lost-stolen-error-' . date("m-d-y") . '-' . time() . '.txt', json_encode($errors['validationErrors']));

            return redirect(route('bulk-lost-stolen.index'))->with(['error' => implode(",\n", $errors['validationErrors'])]);
        }

        if ($errors && !isset($errors['validationErrors'])) {
            Storage::put('public/asset_bulk_lost_stolen/lost-stolen-error-' . date("m-d-y") . '-' . time() . '.txt', json_encode($errors));

            return redirect(route('bulk-lost-stolen.index'))->with(['message' => "Bulk status updated with errors", 'errors' => $errors]);
        }

        return redirect(route('bulk-lost-stolen.index'))->with(['message' => "Bulk status updated successfully"]);
    }
}
