<?php

namespace App\Http\Controllers\api;

use Exception;
use App\Models\Application\Client;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Http\Requests\RClientRequest;
use App\Models\Application\RequestClient;

class RequestClientController extends Controller
{
    private $MESSAGES = [
        'INDEX' => 'WARNING.REQUEST_CLIENT_INDEX',
        'STORE' => 'WARNING.REQUEST_CLIENT_STORE',
        'UPDATE' => 'WARNING.REQUEST_CLIENT_UPDATE',
        'DESTROY' => 'WARNING.REQUEST_CLIENT_DESTROY',
        'LIST' => 'WARNING.REQUEST_CLIENT_LIST',
        'DUPLICATED' => 'WARNING.REQUEST_CLIENT_DUPLICATED',
    ];

    public function __construct()
    {
        $this->CHANNEL = 'requestclient_errors';
    }

    public function index(RClientRequest $request)
    {
        try {
            $isSysAdmin = $this->hasSystemAdministrator();

            $clients = RequestClient::select(
                'id',
                'fk_city',
                'firstname',
                'lastname',
                'secondlastname',
                DB::raw("CONCAT(firstname, ' ', lastname, ' ', secondlastname) as fullname"),
                'curp',
                'phonenumber',
                'colony',
                'address',
                'has_employee',
                'fk_usercreator',
                'created_at',
                'fk_userupdater',
                'updated_at',
                'visible',
            )->with(['city', 'user_creator', 'user_updater'])->where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->when(!$isSysAdmin, function ($query) {
                $query->where('visible', true);
            })->get();

            if (!$isSysAdmin) {
                $this->makeFieldHidden($clients, ['city', 'visible', 'user_creator', 'user_updater']);
            }

            return $this->responseJson(null, $clients, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['INDEX'], null, 501);
        }
    }

    public function store(RClientRequest $request)
    {
        try {
            $existsInClient = Client::where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->where(function ($query) use ($request) {
                $query->where([
                    ['firstname', trim(mb_strtoupper($request->firstname, $this->UTF_ENCODING))],
                    ['lastname', trim(mb_strtoupper($request->lastname, $this->UTF_ENCODING))],
                    ['secondlastname', trim(mb_strtoupper($request->secondlastname, $this->UTF_ENCODING))],
                ])->orWhere('curp', $request->curp);
            })->exists();

            $existsInRequestClient = RequestClient::where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->where(function ($query) use ($request) {
                $query->where([
                    ['firstname', trim(mb_strtoupper($request->firstname, $this->UTF_ENCODING))],
                    ['lastname', trim(mb_strtoupper($request->lastname, $this->UTF_ENCODING))],
                    ['secondlastname', trim(mb_strtoupper($request->secondlastname, $this->UTF_ENCODING))],
                ])->orWhere('curp', $request->curp);
            })->exists();

            if ($existsInClient || $existsInRequestClient) {
                return $this->responseJson($this->MESSAGES['DUPLICATED'], null, 409);
            }

            RequestClient::create([
                'fk_site' => $request->fk_site,
                'fk_office' => $request->fk_office,
                'firstname' => trim(mb_strtoupper($request->firstname, $this->UTF_ENCODING)),
                'lastname' => trim(mb_strtoupper($request->lastname, $this->UTF_ENCODING)),
                'secondlastname' => trim(mb_strtoupper($request->secondlastname, $this->UTF_ENCODING)),
                'curp' => trim(mb_strtoupper($request->curp, $this->UTF_ENCODING)),
                'fk_city' => $request->fk_city,
                'colony' => trim(mb_strtoupper($request->colony, $this->UTF_ENCODING)),
                'address' => trim(mb_strtoupper($request->address, $this->UTF_ENCODING)),
                'phonenumber' => trim($request->phonenumber),
                'has_employee' => $request->has_employee,
                'fk_usercreator' => $this->user()->id,
            ]);

            return $this->responseJson(null, true, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['STORE'], null, 501);
        }
    }

    public function update(RClientRequest $request)
    {
        try {
            $client = RequestClient::find($request->id);

            $existsInClient = Client::where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->where(function ($query) use ($request) {
                $query->where([
                    ['firstname', trim(mb_strtoupper($request->firstname, $this->UTF_ENCODING))],
                    ['lastname', trim(mb_strtoupper($request->lastname, $this->UTF_ENCODING))],
                    ['secondlastname', trim(mb_strtoupper($request->secondlastname, $this->UTF_ENCODING))],
                ])->orWhere('curp', $request->curp);
            })->exists();

            $existsInRequestClient = RequestClient::where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->where(function ($query) use ($request) {
                $query->where([
                    ['firstname', trim(mb_strtoupper($request->firstname, $this->UTF_ENCODING))],
                    ['lastname', trim(mb_strtoupper($request->lastname, $this->UTF_ENCODING))],
                    ['secondlastname', trim(mb_strtoupper($request->secondlastname, $this->UTF_ENCODING))],
                ])->orWhere('curp', $request->curp);
            })->where('id', '!=', $request->id)->exists();

            if ($existsInClient || $existsInRequestClient) {
                return $this->responseJson($this->MESSAGES['DUPLICATED'], null, 501);
            }

            $client->update([
                'firstname' => trim(mb_strtoupper($request->firstname, $this->UTF_ENCODING)),
                'lastname' => trim(mb_strtoupper($request->lastname, $this->UTF_ENCODING)),
                'secondlastname' => trim(mb_strtoupper($request->secondlastname, $this->UTF_ENCODING)),
                'curp' => trim(mb_strtoupper($request->curp, $this->UTF_ENCODING)),
                'fk_city' => $request->fk_city,
                'colony' => trim(mb_strtoupper($request->colony, $this->UTF_ENCODING)),
                'address' => trim(mb_strtoupper($request->address, $this->UTF_ENCODING)),
                'phonenumber' => trim($request->phonenumber),
                'has_employee' => $request->has_employee,
                'fk_userupdater' => $this->user()->id,
            ]);

            return $this->responseJson(null, true, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['UPDATE'], null, 501);
        }
    }

    public function updateEmployeeStatus(RClientRequest $request)
    {
        try {
            $requestclient = RequestClient::findOrFail($request->id);

            $requestclient->update([
                'has_employee' => $request->has_employee,
                'fk_userupdater' => $this->user()->id,
            ]);

            return $this->responseJson(null, true, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['UPDATE'], null, 501);
        }
    }

    public function destroy(RClientRequest $request)
    {
        try {
            $client = RequestClient::find($request->id);

            $client->update([
                'is_active' => $this->hasSpecial($request->fk_office),
                'fk_userupdater' => $this->user()->id,
            ]);

            return $this->responseJson(null, true, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['DESTROY'], null, 501);
        }
    }

    public function list(RClientRequest $request)
    {
        try {
            $isSysAdmin = $this->hasSystemAdministrator();

            $clients = RequestClient::select(
                'id',
                DB::raw('null as id_client'),
                DB::raw("CONCAT(firstname, ' ', lastname, ' ', secondlastname) as fullname")
            )->where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->when(!$isSysAdmin, function ($query) {
                $query->where('visible', true);
            });

            $clients = $clients->union(Client::select(
                DB::raw('null as id'),
                'id as id_client',
                DB::raw("CONCAT(firstname, ' ', lastname, ' ', secondlastname) as fullname")
            )->where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->when(!$isSysAdmin, function ($query) {
                $query->where('visible', true);
            }))->distinct()->orderBy('fullname')
                ->get();

            return $this->responseJson(null, $clients, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['LIST'], null, 501);
        }
    }
}
