<?php

namespace App\Http\Controllers\Admin\Dealers;

use App\Enum\Status;
use App\Http\Controllers\Controller;
use App\Models\Dealers\Dealer;
use App\Models\User;
use App\Services\ActivityLogs\AuthLogService;
use App\Services\ActivityLogs\UserLogService;
use App\Services\DataTableActionLinksService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Yajra\DataTables\DataTables;

// assuming dealers are stored in users table with dealer role

class DealerController extends Controller implements HasMiddleware
{
    /**
     * Define middleware for the controller.
     */
    public static function middleware(): array
    {
        return [
            new Middleware('permission:dealers.add', only: ['create', 'store']),
            new Middleware('permission:dealers.view', only: ['index', 'show', 'dataTable', 'archivedDataTable']),
            new Middleware('permission:dealers.update', only: ['edit', 'update']),
            new Middleware('permission:dealers.delete', only: ['destroy']),
            new Middleware('permission:dealers.restore', only: ['restore']),
            new Middleware('permission:dealers.verify_email', only: ['verifyEmail']),
            new Middleware('permission:dealers.approve', only: ['approve']),
            new Middleware('permission:dealers.approve', only: ['approve', 'reject']),
        ];
    }

    /**
     * Display dealer listing page.
     */
    public function index(): View
    {
        return view('dealers.index');
    }

    /**
     * Show the details of a dealers.
     */
    public function show(string $id): View
    {
        $dealer = Dealer::whereUuid($id)->with(['user', 'representatives', 'finances', 'addresses', 'branches', 'operations'])->first();

        if (empty($dealer)) throw new NotFoundHttpException(trans('global.toast.not_found'));

        return view('dealers.modals.show', compact('dealer'));
    }

    /**
     * Approve a dealer account.
     */
    public function approve(string $id): JsonResponse
    {
        try {
            $dealer = Dealer::whereUuid($id)
                ->with('user')
                ->first();

            if (empty($dealer) || !$dealer->user?->hasRole('dealer')) throw new NotFoundHttpException(trans('global.toast.not_found'));

            DB::beginTransaction();

            $dealer->update([
                'verified_at' => now(),
            ]);

            $dealer->user->update([
                'status' => Status::ACTIVE,
            ]);

            (new UserLogService())->approved($dealer->user);

            DB::commit();

            return $this->jsonResponse(['message' => trans('dealers.toast.success.approved')]);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->jsonResponseInternalServerError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * Reject a dealer account.
     */
    public function reject(string $id): JsonResponse
    {
        try {
            $dealer = Dealer::whereUuid($id)
                ->with('user')
                ->first();

            if (empty($dealer) || !$dealer->user?->hasRole('dealer')) {
                throw new NotFoundHttpException(trans('global.toast.not_found'));
            }

            DB::beginTransaction();

            $dealer->user->update([
                'status' => Status::SUSPENDED,
            ]);

            (new UserLogService())->rejected($dealer->user);

            DB::commit();

            return $this->jsonResponse(['message' => trans('dealers.toast.success.rejected')]);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->jsonResponseInternalServerError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * Soft delete the specified dealers.
     */
    public function destroy(string $id): JsonResponse
    {
        try {
            $dealer = Dealer::whereUuid($id)->with('user')->first();

            if (empty($dealer) || !$dealer->user?->hasRole('dealer')) throw new NotFoundHttpException(trans('global.toast.not_found'));

            if ($dealer->user->id === auth()->id()) throw new BadRequestException(trans('global.toast.unable_to_update'));

            DB::beginTransaction();

            $dealer->delete();
            $dealer->user->delete();

            (new UserLogService())->deleted($dealer->user);

            DB::commit();

            return $this->jsonResponse(['message' => trans('dealers.toast.success.deleted')]);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->jsonResponseInternalServerError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * Restore a previously deleted dealers.
     */
    public function restore(string $id): JsonResponse
    {
        try {
            $dealer = Dealer::onlyTrashed()->whereUuid($id)->with('user')->first();

            if (empty($dealer) || !$dealer->user?->hasRole('dealer')) throw new NotFoundHttpException(trans('global.toast.not_found'));

            DB::beginTransaction();

            $dealer->restore();
            $dealer->user->restore();

            (new UserLogService())->restored($dealer->user);

            DB::commit();

            return $this->jsonResponse(['message' => trans('dealers.toast.success.restored')]);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->jsonResponseInternalServerError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * Verify dealer email manually.
     */
    public function verifyEmail(string $id): JsonResponse
    {
        try {
            $dealer = Dealer::whereUuid($id)->with('user')->first();

            if (empty($dealer) || !$dealer->user || $dealer->user->email_verified_at) throw new NotFoundHttpException(trans('global.toast.not_found'));

            DB::beginTransaction();

            $dealer->user->update([
                'status' => Status::VERIFIED,
                'email_verified_at' => now(),
            ]);

            (new AuthLogService())->emailVerified($dealer->user);

            DB::commit();

            return $this->jsonResponse(['message' => trans('dealers.toast.success.verified')]);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->jsonResponseInternalServerError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * Dealers DataTable.
     */
    public function dataTable(Request $request): JsonResponse
    {
        $dealers = Dealer::with('user')->orderBy('id', 'desc');

        $dt = DataTables::of($dealers);

        // 🔎 Searching
        $dt->filter(function ($query) use ($request) {
            if (!$request->has('search')) return;

            $search = trim($request->input('search')['value']);
            $keywords = explode(' ', $search);

            $query->whereHas('user', function ($q) use ($keywords) {
                foreach ($keywords as $word) {
                    $q->where(function ($sq) use ($word) {
                        $sq->where('first_name', 'like', "%$word%")
                            ->orWhere('last_name', 'like', "%$word%")
                            ->orWhere('email', 'like', "%$word%")
                            ->orWhere('phone', 'like', "%$word%")
                            ->orWhere('status', 'like', "%$word%");
                    });
                }
            });
        });

        // 🧑 Name Column
        $dt->addColumn('name', fn($record) => '<div class="user-card">
            <div class="user-avatar ' . getRandomColorClass() . ' d-none d-sm-flex">'
            . getAvatarHtml($record->user) . '</div>
            <div class="user-info">
                <span class="tb-lead">' . $record->user->fullName . '</span>
                <span>' . $record->user->email . '</span>
            </div>
        </div>');

        $dt->addColumn('phone', fn($record) => canEmpty($record->user->phone));

        $dt->addColumn('status', fn($record) => $record->user->getStatusBadge());

        $dt->addColumn('created', fn($record) => createdAt($record));

        $dt->addColumn('updated', fn($record) => updatedAt($record));

        $dt->addColumn('actions', function ($record) {
            $user = $record->user;
            $dealer = $record;
            $links = [
                [
                    'action' => 'custom',
                    'shouldRender' => auth()->user()->can('dealers.verify_email') && !$user->isVerified(),
                    'url' => route('dealers.verify-email', $record->uuid),
                    'attributes' => 'confirm-btn data-title="' . trans('dealers.confirmable.verify.title') . '"
                        data-message="' . trans('dealers.confirmable.verify.message') . '"
                        data-confirm-btn-text="' . trans('dealers.confirmable.verify.button') . '"
                        data-cancel-btn-text="' . trans('global.confirmable.button.cancel') . '"
                        data-method="post" data-datatable="#dealers-dt"',
                    'icon' => 'mail',
                    'buttonText' => trans('dealers.table.actions.verify_email'),
                    'syncResponse' => true,
                ],
                [
                    'action' => 'custom',
                    'shouldRender' => auth()->user()->can('dealers.approve') && $user->status == Status::VERIFIED,
                    'url' => route('dealers.approve', $record->uuid),
                    'attributes' => 'confirm-btn data-method="post" data-datatable="#dealers-dt"
                        data-title="' . trans('dealers.confirmable.approve.title') . '"
                        data-message="' . trans('dealers.confirmable.approve.message') . '"
                        data-confirm-btn-text="' . trans('dealers.confirmable.approve.button') . '"
                        data-cancel-btn-text="' . trans('global.confirmable.button.cancel') . '"',
                    'icon' => 'check',
                    'buttonText' => trans('dealers.table.actions.approve_account'),
                    'syncResponse' => true,
                ],
                [
                    'action' => 'custom',
                    'shouldRender' => auth()->user()->can('dealers.approve') && ($user->status == Status::VERIFIED || $user->status == Status::ACTIVE),
                    'url' => route('dealers.reject', $record->uuid),
                    'attributes' => 'confirm-btn data-method="post" data-datatable="#dealers-dt"
                        data-title="' . trans('dealers.confirmable.reject.title') . '"
                        data-message="' . trans('dealers.confirmable.reject.message') . '"
                        data-confirm-btn-text="' . trans('dealers.confirmable.reject.button') . '"
                        data-cancel-btn-text="' . trans('global.confirmable.button.cancel') . '"',
                    'icon' => 'x',
                    'buttonText' => trans('dealers.table.actions.reject_account'),
                    'syncResponse' => true,
                ],
                ['action' => 'delete'],
                ['action' => 'view', 'modalSize' => 'lg'],
            ];

            return (new DataTableActionLinksService(
                model: $record,
                routeNamespace: 'dealers',
                permissionNamespace: 'dealer',
                datatableId: '#dealers-dt',
                isLocked: false
            ))->byArray($links);
        });

        $dt->addIndexColumn();

        $dt->rawColumns(['actions', 'name', 'phone', 'status', 'created', 'updated']);

        return $dt->make(true);
    }

    /**
     * Dealers archived DataTable.
     */
    public function archivedDataTable(Request $request): JsonResponse
    {
        $dealers = Dealer::with('user')->onlyTrashed()->orderBy('id', 'desc');

        $dt = DataTables::of($dealers);

        $dt->addColumn('name', fn($record) => '<div class="user-card">
            <div class="user-avatar ' . getRandomColorClass() . ' d-none d-sm-flex">'
            . getAvatarHtml($record->user) . '</div>
            <div class="user-info">
                <span class="tb-lead">' . canEmpty($record->user->fullName) . '</span>
                <span>' . canEmpty($record->user->email) . '</span>
            </div>
        </div>');

        $dt->addColumn('phone', fn($record) => canEmpty($record->user->phone));

        $dt->addColumn('status', fn($record) => $record->user->getStatusBadge());

        $dt->addColumn('created', fn($record) => createdAt($record->user));

        $dt->addColumn('updated', fn($record) => updatedAt($record->user));

        $dt->addColumn('actions', function ($record) {

            $links = [['action' => 'restore']];

            return (new DataTableActionLinksService(
                model: $record,
                routeNamespace: 'dealers',
                permissionNamespace: 'c',
                datatableId: '#archived-dealers-dt',
                isLocked: false
            ))->byArray($links);
        });

        $dt->addIndexColumn();

        $dt->rawColumns(['actions', 'name', 'phone', 'status', 'created', 'updated']);

        return $dt->make(true);
    }
}
