<?php

namespace App\Http\Controllers;

use App\Models\Dispatch;
use App\Models\DispatchItem;
use App\Models\Device;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Models\StockMovement;

use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;

class DispatchController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return [

            new Middleware(
                'permission:dispatch.view',
                only: ['index']
            ),

            new Middleware(
                'permission:dispatch.create',
                only: ['store']
            ),

            new Middleware(
                'permission:dispatch.receive',
                only: ['receive']
            ),

        ];
    }
    //

    public function index()
    {
        $query = Dispatch::with([
            'salesUser',
            'creator'
        ])->withCount('items');

        // Sales can only see their own dispatches
        if (Auth::user()->hasRole('Sales')) {

            $query->where(
                'sales_user_id',
                Auth::id()
            );
        }

        $dispatches = $query
            ->latest()
            ->get();

        $salesUsers = User::role('Sales')
            ->where('status', 1)
            ->get();

        return view(
            'dispatch.index',
            compact(
                'dispatches',
                'salesUsers'
            )
        );
    }


    public function store(Request $request)
    {
        $request->validate([
            'sales_user_id' => 'required',
            'serial_numbers' => 'required',
        ]);

        DB::beginTransaction();

        try {

            $serialNumbers = preg_split(
                '/\r\n|\r|\n/',
                trim($request->serial_numbers)
            );

            $serialNumbers = array_filter(
                array_map('trim', $serialNumbers)
            );

            $devices = Device::whereIn(
                'serial_number',
                $serialNumbers
            )
                ->where('status', 'store_stock')
                ->get();

            if ($devices->count() != count($serialNumbers)) {

                DB::rollBack();

                return back()->with(
                    'error',
                    'Some serial numbers were not found or are not in store stock.'
                );
            }

            $dispatch = Dispatch::create([

                'dispatch_no' => 'DSP-' . now()->format('YmdHis'),

                'sales_user_id' => $request->sales_user_id,

                'dispatch_date' => now(),

                'status' => 'pending',

                'created_by' => Auth::id(),

                'updated_by' => Auth::id(),

            ]);

            foreach ($devices as $device) {

                DispatchItem::create([
                    'dispatch_id' => $dispatch->id,
                    'device_id' => $device->id,
                ]);

                $device->update([
                    'status' => 'pending',
                    'sales_user_id' => $request->sales_user_id
                ]);


                StockMovement::create([
                    'device_id'      => $device->id,
                    'movement_type'  => 'DISPATCH',
                    'from_location'  => 'STORE',
                    'to_location'    => 'PENDING',
                    'user_id'        => Auth::id(),
                    'remarks'        => 'Dispatched to sales user: ' . $dispatch->salesUser->name,
                ]);
            }

            DB::commit();

            return back()->with(
                'success',
                'Dispatch created successfully.'
            );
        } catch (\Exception $e) {

            DB::rollBack();

            return back()->with(
                'error',
                $e->getMessage()
            );
        }
    }


    public function receive(Dispatch $dispatch)
    {
        // Sales users can only receive their own dispatches
        if (
            Auth::user()->hasRole('Sales') &&
            $dispatch->sales_user_id != Auth::id()
        ) {
            abort(403, 'Unauthorized.');
        }

        DB::beginTransaction();

        try {

            foreach ($dispatch->items()->with('device')->get() as $item) {

                $item->device->update([
                    'status' => 'sales_stock'
                ]);

                StockMovement::create([
                    'device_id'      => $item->device->id,
                    'movement_type'  => 'RECEIVED',
                    'from_location'  => 'PENDING',
                    'to_location'    => 'SALES_STOCK',
                    'user_id'        => Auth::id(),
                    'remarks'        => 'Dispatch assigned to ' .
                        $dispatch->salesUser->name .
                        ' and received by ' .
                        Auth::user()->name,
                ]);
            }

            $dispatch->update([
                'status'     => 'received',
                'updated_by' => Auth::id()
            ]);

            DB::commit();

            return back()->with(
                'success',
                'Dispatch received successfully.'
            );
        } catch (\Exception $e) {

            DB::rollBack();

            return back()->with(
                'error',
                $e->getMessage()
            );
        }
    }


    public function devices(Dispatch $dispatch)
    {

        if (
            Auth::user()->hasRole('Sales') &&
            $dispatch->sales_user_id != Auth::id()
        ) {
            abort(403);
        }


        return response()->json([
            'dispatch' => [
                'dispatch_no'   => $dispatch->dispatch_no,
                'sales_user'    => $dispatch->salesUser?->name,
                'dispatch_date' => $dispatch->created_at?->format('d M Y H:i:s'),
                'received_date' => $dispatch->status == 'received'
                    ? $dispatch->updated_at?->format('d M Y H:i:s')
                    : 'Not Received',
            ],

            'devices' => DispatchItem::with('device')
                ->where('dispatch_id', $dispatch->id)
                ->get()
        ]);
    }
}
