<?php

namespace App\Http\Controllers\api;

use Exception;
use App\Http\Controllers\Controller;
use App\Http\Requests\ModelRequest;
use App\Models\Application\GuaranteeModel;

class ModelController extends Controller
{
    protected $MESSAGES = [
        'INDEX' => 'WARNING.MODEL_INDEX',
        'STORE' => 'WARNING.MODEL_STORE',
        'UPDATE' => 'WARNING.MODEL_UPDATE',
        'DESTROY' => 'WARNING.MODEL_DESTROY',
        'DUPLICATED' => 'WARNING.MODEL_DUPLICATED',
        'STATUS' => 'WARNING.MODEL_STATUS',
        'VISIBLE' => 'WARNING.MODEL_VISIBLE',
        'LIST' => 'WARNING.MODEL_LIST',
        'SHOW' => 'WARNING.MODEL_SHOW',
    ];

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

    public function index(ModelRequest $request)
    {
        try {
            $isSystemAdministrator = $this->hasSystemAdministrator($request->fk_office);

            $models = GuaranteeModel::with(['brand', 'user_creator', 'user_updater'])->where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', !$this->hasSpecial($request->fk_office)]
            ])->when(!$isSystemAdministrator, function ($query) {
                $query->where('visible', true);
            })->orderBy('id')->get();

            if (!$isSystemAdministrator) {
                $this->makeFieldHidden($models, ['visible', 'user_updater', 'user_creator']);
            }

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

    public function store(ModelRequest $request)
    {
        try {
            $isDuplicated = GuaranteeModel::where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['modelname', mb_strtoupper(trim($request->modelname), $this->UTF_ENCODING)],
                ['is_active', true]
            ])->exists();

            if ($isDuplicated) {
                return $this->responseJson($this->MESSAGES['DUPLICATED'], 501);
            }

            GuaranteeModel::create([
                'fk_site' => $request->fk_site,
                'fk_office' => $request->fk_office,
                'fk_brand' => $request->fk_brand,
                'modelname' => mb_strtoupper(trim($request->modelname), $this->UTF_ENCODING),
                '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(ModelRequest $request)
    {
        try {
            $route = $request->route()->getName();
            $model = GuaranteeModel::findOrFail($request->id);

            $actions = [
                'model.update' => fn() => $this->updateModel($request, $model),
                'model.changeStatus' => fn() => $this->updateBooleanStatus($request, $model),
                'model.changeVisibility' => fn() => $this->updateBooleanStatus($request, $model, 'visible'),
            ];

            if (array_key_exists($route, $actions)) {
                $actions[$route]();
            }

            return $this->responseJson(null, true, 201);
        } catch (Exception $ex) {
            $responses = [
                'model.update' => $this->MESSAGES['UPDATE'],
                'model.changeStatus' => $this->MESSAGES['STATUS'],
                'model.changeVisibility' => $this->MESSAGES['VISIBLE']
            ];

            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($responses[$route], null, 501);
        }
    }

    private function updateModel(ModelRequest $request, GuaranteeModel $model)
    {
        $isDuplicated = GuaranteeModel::where([
            ['fk_office', $request->fk_office],
            ['fk_brand', $request->fk_brand],
            ['modelname', mb_strtoupper(trim($request->modelname), $this->UTF_ENCODING)],
            ['is_active', true]
        ])->where('id', '!=', $model->id)->exists();

        if ($isDuplicated) {
            throw new Exception($this->MESSAGES['DUPLICATED']);
        }

        $model->update([
            'fk_brand' => $request->fk_brand,
            'modelname' => mb_strtoupper(trim($request->modelname), $this->UTF_ENCODING),
            'fk_userupdater' => $this->user()->id
        ]);
    }

    public function destroy(ModelRequest $request)
    {
        try {
            $model = GuaranteeModel::findOrFail($request->id);

            $model->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);
        }
    }
}
