<?php

namespace App\Modules\Bookings;

use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Cache;
use App\Models\Status;
use Illuminate\Support\Facades\Auth;
use Keychain;
use Exception;
use App\Exceptions\JobModifiedSinceLastOpenedException;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use App\Modules\Bookings\Repair;
use App\Models\MobileToken;

class RepairsControllerREST extends BaseController
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index(Request $request)
    {
        $query = Repair::select('tasks.*')->repairs()->with('status', 'severity');

        if ($request->input('q')) {
            $query->where(function ($query) {
                $query->where('tasks.id', 'like', $request->input('q') . '%')->orWhere('seraph_id', '=', $request->input('q'));
            });
        }

        if ($request->input('items')) {
            $query = $query->with('items');
        }

        if ($request->input('user')) {
            $query = $query->with('user');
        }
        if ($request->input('client_id') && $request->input('client_type')) {
            $query = $query->where('client_id', $request->input('client_id'))->where('client_type', $request->input('client_type'));
        }
       
        if ($request->input('show')) {
            switch ($request->input('show')) {
                case 'completed':
                    $query->completed();
                    break;
                case 'open':
                    $query->open();
                    break;
            }
        }

        if ($request->input('unpaid')) {
            $query->unpaid();
        }

        if ($request->input('parts_total')) {
            $query->with('parts');
        }

        if ($request->input('results')) {
            switch ($request->input('results')) {
                case 'managers':
                    $query->where('completed', '=', 0)->with('user');
                    break;
                case 'own':
                    $query = $query->where('assigned_to', '=', $request->input('user_id', Auth::user()->id))->open();
                    break;
                case 'unassigned':
                    $query = $query->whereNull('assigned_to')->open();
            }
        }

        // Sort results based on priority
        $query->join('severities', 'severities.id', '=', 'tasks.severity_id', 'left');

        if ($request->input('summary')) {
            $query->orderBy('tasks.id', 'desc');
        } else {
            $query->orderBy('severities.priority', 'desc')
                ->orderBy('tasks.id', 'asc');
        }

        // Apply limits and execute the query
        // $query = $query->take(request()->input('limit', 20))->skip(request()->input('skip', 0))->get();
        $query = $query->paginate($request->input('limit', 20));

        foreach ($query as $value) {
            // Load all the clients
            // unfortuately eager loading is not available
            // for polymorphic relationships at the moment..
            if ($request->input('client') && $request->input('client') != 'false') {
                $value->client;

                // Load the contract data only if this is a business customer
                if ($value->client_type == 'client') {
                    $value->client->load('contract');
                }
            }

            if ($request->input('parts_total')) {
                $value->parts_total = 0;

                foreach ($value->parts as $part) {
                    $value->parts_total += $part->amount_paid;
                }
            }
            // Load all the comment stats
            $value->comments_count = [
                'total'   => $value->comments()->count(),
                'unread'  => $value->comments()->unread()->count(),
            ];
        }

        $response = [
            'success'      => true,
            'data'         => $query->getCollection()->toArray(),
            'total'        => $query->total(),
            'current_page' => $query->currentPage(),
            'last_page'    => $query->lastPage(),
            'from'         => $query->firstItem(),
            'to'           => $query->lastItem(),
        ];

        // Temporary logging to debug repairs queue issue
        if ($request->input('results') === 'unassigned') {
            \Log::info('Repairs Queue API Response', [
                'count' => count($response['data']),
                'total' => $response['total'],
                'first_5_ids' => array_slice(array_column($response['data'], 'id'), 0, 5)
            ]);
        }

        return response()->json($response, ($response['success']) ? 200 : 400)
            ->header('Cache-Control', 'no-cache, no-store, must-revalidate')
            ->header('Pragma', 'no-cache')
            ->header('Expires', '0');
    }

    public function checkStatusFromPin($id, $pin, $token = null)
    {
        $repair = Repair::find($id);

        //checking if the pin sent is the repair pin. Otherwise throw error.
        if ($repair->pin == $pin) {

            $repair->load('user', 'client', 'parts', 'parts.stock', 'parts.stock.order', 'parts.stock.order.status', 'devices', 'devices.model_number', 'devices.model_number.manufacturer', 'creator', 'standard_price', 'templates.items', 'template_items');

            $repair->statuses = Status::repairs()->get();

            if ($repair->client_type == 'client') {
                $repair->load('site', 'site_user', 'passwords');
            }

            $response = [
                'success' => true,
                'data'    => $repair->toArray(),
            ];



            if ($repair->status->name == 'Booked In') {
                $statusTitle = 'Booked In';
                $statusDescription = 'Your job is currently Booked In. We hope to have some news soon.';
            } else if ($repair->status->name == 'Work in progress') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Customer needs to be called') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Customer will get back to us') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Waiting for parts') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Cancelled') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Quality Control') {
                $statusTitle = 'Quality Control';
                $statusDescription = 'Your job is currently in Quality Control. Once this step is complete, you will receive a call from us.';
            } else if ($repair->status->name == 'Need to go Onsite') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Duplicate') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'RMA - return in process') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Customer does not want to proceed with the repair') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Not possible to repair') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'No issues found') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Sold new machine') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Sold refurbished computer') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Missing job details') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Customer is not responding') {
                $statusTitle = 'Work in progress';
                $statusDescription = 'Your job is currently in progress';
            } else if ($repair->status->name == 'Work Completed') {
                $statusTitle = 'Work Completed';
                $statusDescription = 'This job is closed.';
            }

            $repair->comments->load('creator');
            $comments =  $repair->comments;

            $filtered = $comments->filter(function ($item) {
                if ($item->public == 1) {
                    return $item;
                }
            })->values();


            $data = array();
            $data['token'] = $token;
            $data['related_id'] = $id;
            $data['related_type'] = 'task';
            $mobileToken = MobileToken::updateOrCreate($data);

            $responseLimited = [
                'success' => true,
                'data' => [
                    'id' => $repair->id,
                    'title' => $repair->title,
                    'status' => $statusTitle,
                    'assigned' => (isset($repair->user) ? $repair->user->name : "None"),
                    'ddi' => (isset($repair->user) ? $repair->user->direct_dial : "None"),
                    'labour' => $repair->labour,
                    'statusDescription' => $statusDescription,
                    'customer_name' => $repair->client->name,
                    'comments' => $filtered,
                    'tokens' =>  $repair->mobile_tokens,
                ]
            ];

            return response()->json($responseLimited, ($response['success']) ? 200 : 400);
        } else {
            return response()->json(['success' => false, 'errors' => ['Incorrect Pin!']], 400);
        }
    }

    public function deteleTokenUsingId($id, $token = null)
    {
        $repair = Repair::find($id);

        $response = [
            'success' => true,
            'data'    => $repair->toArray(),
        ];
        $data = array();
        $data['token'] = $token;
        $data['related_id'] = $id;
        $data['related_type'] = 'task';
        //   MobileToken::destroy(283);   
        //  $mobileToken = MobileToken::find(283);

        $tokens = $repair->mobile_tokens;


        foreach ($tokens as $item) {
            if ($item['token'] == $token) {
                $test = $item['id'];
                MobileToken::destroy($item['id']);
            } else {
                $test = null;
            }
        }


        $responseLimited = [
            'success' => true,
            'data' => [
                'id' => $repair->id,
                'title' => $repair->title,
                'TEST' =>  $test,
                'tokens' =>  $repair->mobile_tokens,
            ]
        ];

        return response()->json($responseLimited, ($response['success']) ? 200 : 400);
    }


    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store(Request $request)
    {
        if (!$request->has('devices') || count($request->input('devices', [])) == 0) {
            throw new Exception('The repair requires at least one device.', 1);
        }

        // Assign a default status
        $status = Status::repairs()->first();

        if (!$status) {
            return response()->json(['success' => false, 'errors' => ['No statuses defined']], 400);
        }

        $data = $request->except('id');
        $data['status_id'] = $status->id;

        // Generate a pin number
        $data['pin'] = rand(1000, 9999);

        // Check for passwords
        if ($request->input('has_password') == '1') {
            $keychains = $request->input('keychains', []);
            if (count($keychains) == 0) {
                return response()->json([
                    'success' => false,
                    'errors' => ['keychains' => ['Please enter at least one password']]
                ], 422);
            }

            //Check that all the keychains are correct
            foreach ($keychains as $index => $keychain) {
                if (!isset($keychain['username']) || !isset($keychain['password']) ||
                    strlen(trim($keychain['username'])) == 0 || strlen(trim($keychain['password'])) == 0) {

                    // Get device name for better error message
                    $deviceName = 'No device';
                    if (isset($keychain['device_id']) && $keychain['device_id']) {
                        $device = \App\Models\Device::find($keychain['device_id']);
                        if ($device) {
                            $deviceName = $device->name;
                        }
                    }

                    $type = isset($keychain['type']) ? ucfirst($keychain['type']) : 'Unknown';
                    $username = isset($keychain['username']) && !empty(trim($keychain['username']))
                        ? $keychain['username']
                        : 'empty username';

                    return response()->json([
                        'success' => false,
                        'errors' => ['keychains' => [
                            "Password entry has empty username or password (Device: {$deviceName}, Type: {$type}, Username: {$username}). Please remove this password entry or fill in the missing fields."
                        ]]
                    ], 422);
                }
            }
        }

        $repair = Repair::create($data);

        if (!$repair->id) {
            $response = [
                'success' => false,
                'errors'  => $repair->errors->all(),
            ];
        } else {
            if ($request->input('has_password') == '1') {
                //Add the keychains to the task and ignore if there is one repeated
                foreach ($keychains as $keychain) {
                    $repair->passwords()->attach($keychain['id']);
                }
            }

            if ($request->has('devices')) {
                $repair->devices()->sync(collect($request->input('devices'))->pluck('id'));
            }

            if ($request->has('templates')) {
                $repair->templates()->sync(collect($request->input('templates'))->pluck('id'));
            }

            $response = [
                'success' => true,
                'data'    => $repair->toArray(),
            ];
        }

        return response()->json($response, ($response['success']) ? 200 : 400);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function show($id)
    {
        // Cache key for repairs (separate from tasks)
        $cacheKey = "repair_show_{$id}";
        
        // Check cache first
        if (Cache::has($cacheKey)) {
            $cachedResponse = Cache::get($cacheKey);
            return response()->json($cachedResponse, 200);
        }

        $repair = Repair::find($id);

        // EXACT SAME BUSINESS LOGIC AS LARAVEL5 - NO CHANGES!
        // Load relationships exactly as Laravel5 did (line 377)
        $repair->load('user', 'client', 'parts', 'parts.stock', 'parts.stock.order', 'parts.stock.order.status', 'devices', 'devices.model_number', 'devices.model_number.manufacturer', 'creator', 'standard_price', 'templates.items', 'template_items');

        $repair->statuses = Status::repairs()->get();

        // Client relationships exactly as Laravel5 (lines 381-383)
        if ($repair->client_type == 'client') {
            $repair->load('client.sites', 'client.sites.users', 'site', 'site_user', 'passwords');
        }

        $response = [
            'success' => true,
            'data'    => $repair->toArray(),
        ];

        // Cache the result for 5 minutes
        Cache::put($cacheKey, $response, 5);

        return response()->json($response, ($response['success']) ? 200 : 400);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function update(Request $request, $id)
    {
        $repair = Repair::findOrFail($id);

        // Check to see if the job has been updated since the user first loaded it
        // and if it has throw an exception
        // We do not want people to overwrite other's changes
        if ($request->input('updated_at') && $request->input('updated_at') != $repair->updated_at) {
            throw new JobModifiedSinceLastOpenedException();
        }

        $data = $request->except('id', 'client_id', 'client_type');

        $repair->fill($data);

        if ($repair->save()) {
            // Synchronize the devices on pivot table
            if ($request->has('devices')) {
                $repair->devices()->sync(collect($request->input('devices'))->pluck('id'));
            }

            if ($request->has('templates')) {
                $repair->templates()->sync(collect($request->input('templates'))->pluck('id'));
            }

            $repair->load('user', 'devices', 'devices.model_number', 'devices.model_number.manufacturer', 'creator', 'standard_price', 'template_items', 'templates.items');

            if ($repair->client_type == 'client') {
                $repair->load('site', 'site_user');
            }

            return response()->json($repair->toArray());
        } else {
            return response()->json(['errors' => $repair->errors->all()], 400);
        }
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function destroy($id)
    {
        //
    }
}
