<?php

namespace App\Http\Controllers\Asn\Connection;

use App\Http\Controllers\Controller;
use App\Models\TechnicalSpecs;
use App\Models\AsnHardwareMapping;
use Facades\App\Models\MakeAndModel;
use App\Models\AssetType;
use App\Models\Asset;
use App\Models\AssetStatus;
use Facades\App\Repositories\HardwareStandards;
use App\Services\Asn\Connection\ConnectionHardwareMappingService;

class ConnectionHardwareMappingController extends Controller
{

    /**
     * @var \App\Services\Asn\Connection\ConnectionHardwareMappingService
     */
    protected $hardwareMappingService;


    /**
     * Constructor for the controller.
     *
     * @param \App\Services\ConnectionHardwareMappingService $hardwareMappingService The hardware mapping service instance.
     */
    public function __construct(ConnectionHardwareMappingService $hardwareMappingService)
    {
        $this->hardwareMappingService = $hardwareMappingService;
    }


    /**
     * Display a listing of connection hardware mappings.
     *
     * @return \Illuminate\View\View The view displaying the connection hardware mappings.
     */
    public function index()
    {
        $connectionMappings = $this->hardwareMappingService->getConnectionMappingData();
        $hardwareStandards = HardwareStandards::getHardwareStandardsWithoutAccessories();
        $hardwareStandardsArray = HardwareStandards::getHardwareStandardsWithoutAccessories()->pluck('makeAndModel', 'id');
        $assettypes = AssetType::allWithoutComputerAccessories()->pluck('name', 'id');
        $techSpechs = TechnicalSpecs::get()->pluck('details', 'id');

        return view('asn.connection.connection-hardware-mapping', compact('connectionMappings', 'assettypes', 'hardwareStandards', 'hardwareStandardsArray', 'techSpechs'));
    }


    /**
     * Search for connection hardware mappings.
     *
     * @return \Illuminate\Http\JsonResponse The JSON response containing the rendered search results view.
     */
    public function search()
    {
        $connectionMappings = $this->hardwareMappingService->filter();
        $view['hardware'] = view('asn.connection.partials.data.connection-hardware-mapping-data', compact('connectionMappings'))->render();

        return response()->json($view);
    }


    /**
     * Store a new connection hardware mapping.
     *
     * @return \Illuminate\Http\RedirectResponse The redirect response with a success or error message.
     */
    public function store()
    {
        request()->validate([
            'part_no' => ['required'],
            'make_and_model' => ['required'],
            'technical_spec' => ['required']
        ]);

        $venderMapping = AsnHardwareMapping::where(['provider' => 'connection', 'part_no' => request('part_no')])
            ->first();

        if (!$venderMapping) {
            AsnHardwareMapping::Create([
                'provider' => 'connection',
                'make_and_model_id' => request('make_and_model'),
                'technical_spec_id' => request('technical_spec'),
                'part_no' => request('part_no'),

            ]);

            if (request('sync_now') == 1) {
                $assetStatus = AssetStatus::whereIn('slug', ['connection_in_transit'])->pluck('id');
                $this->hardwareMappingService->individualHardwarePartResync($assetStatus, request('part_no'), request('make_and_model'), request('technical_spec'));
            }

            return redirect('/connection-hardware-mapping')->with('message', "Hardware mapped successfully.");
        }

        return redirect('/connection-hardware-mapping')->withErrors(['Mapping  for this part # already exist']);
    }


    /**
     * Update an existing connection hardware mapping.
     *
     * @return \Illuminate\Http\JsonResponse The JSON response with the status and message.
     */
    public function update()
    {
        $techData = TechnicalSpecs::where('id', request('technical_spec'))
            ->first();

        $makeModel = MakeAndModel::where('id', request('make_and_model'))
            ->first();

        $makeModelId  = $makeModel ? $makeModel->id : null;
        $techId       = $techData ? $techData->id : null;

        AsnHardwareMapping::findOrFail(request('id'))
            ->update([
                'make_and_model_id' => $makeModelId,
                'technical_spec_id' => $techId,
                'part_no'       => request('description'),
            ]);

        return response()->json(['status' => 'success', 'message' => "Hardware mapping updated successfully."]);
    }


    /**
     * Delete an existing connection hardware mapping.
     *
     * @return \Illuminate\Http\JsonResponse The JSON response with the status and success message.
     */
    public function destroy()
    {
        $asnHardwareMapping = AsnHardwareMapping::findOrFail(request('id'));
        $assetStatus = AssetStatus::whereIn('slug', ['connection_in_transit'])->pluck('id');

        $this->hardwareMappingService->resyncHardwarePartOnDelete($assetStatus, $asnHardwareMapping);
        $asnHardwareMapping->delete();

        return response()->json(['status' => 'success', 'message' => "Hardware mapping deleted successfully."]);
    }


    /**
     * Handle AJAX requests for updating or deleting connection hardware mappings.
     *
     * @return \Illuminate\Http\JsonResponse The JSON response with the status and message from the update or destroy method, or a boolean value.
     */
    public function ajax()
    {
        if (request('action') == 'edit') {
            return $this->update();
        } elseif (request('action') == 'delete') {
            return $this->destroy();
        }

        return response()->json(true);
    }


    /**
     * Resync connection hardware mappings.
     *
     * @return \Illuminate\Http\RedirectResponse The redirect response with a success or error message.
     */
    public function resync()
    {
        try {
            $allConnectionHardwareMappings = AsnHardwareMapping::where('provider', 'connection')->whereNotNull('part_no')->get();
            $assetStatusId = AssetStatus::whereIn('slug', ['connection_in_transit'])->pluck('id');

            foreach ($allConnectionHardwareMappings as $connectionHardwareMapping) {
                $makeAndModel = MakeAndModel::findOrFail($connectionHardwareMapping->make_and_model_id);

                Asset::whereIn('asset_status_id', $assetStatusId)->where('part_no', $connectionHardwareMapping->part_no)
                    ->update([
                        'make_and_model_id' => $connectionHardwareMapping->make_and_model_id,
                        'technical_spec_id' => $connectionHardwareMapping->technical_spec_id,
                        'asset_type_id' => $makeAndModel->asset_type_id
                    ]);
            }
        } catch (\Exception) {
            return redirect('/connection-hardware-mapping')->with('error', "Opration failed.");
        }

        return redirect('/connection-hardware-mapping')->with('message', "Resynced successfully.");
    }


    /**
     * Handle the bulk upload of connection hardware mappings.
     *
     * @return \Illuminate\Http\RedirectResponse The redirect response with a success or error message.
     */
    public function bulkUpload()
    {
        setUnlimitedExecutionTimeAndMemoryLimit();

        $result = $this->hardwareMappingService->bulkUpload();

        return redirect('/connection-hardware-mapping')->with(['message' => $result['message'] ?? '', 'error' => $result['errors'] ?? '']);
    }
}
