<?php

namespace App\Http\Controllers\Dealer;

use App\Models\Term;
use Illuminate\View\View;
use App\Traits\FileUploader;
use Illuminate\Http\Request;
use App\Models\Dealers\Dealer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use App\Http\Requests\Profile\ProfileUpdateRequest;
use App\Http\Requests\Profile\PasswordUpdateRequest;

class ProfileController extends Controller
{
    use FileUploader;

    public function index(): View
    {
        $user = auth()->user();
        
        $dealer = Dealer::with(['user', 'representatives', 'finances', 'addresses', 'branches', 'operations'])
            ->whereHas('user', function ($q) use ($user) {
                $q->where('id', $user->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        return view('dealer.profile.index', compact('dealer'));
    }

    /**
     * Display the user's profile form.
     */
    public function edit(): View
    {
        $user = auth()->user();

        $dealer = Dealer::with(['user', 'representatives', 'finances', 'addresses', 'branches', 'operations', 'media'])
            ->whereHas('user', function ($q) use ($user) {
                $q->where('id', $user->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

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

    /**
     * Update the user's profile information.
     */
    public function update(ProfileUpdateRequest $request): JsonResponse
    {
        try {
            $only = [
                'first_name',
                'last_name',
                'gender',
                'dob',
            ];

            auth()->user()->update($request->only($only));

            $params = [];

            foreach ($only as $field) {
                $params[$field] = auth()->user()?->$field;
            }

            $params['name'] = auth()->user()->fullName;
            $params['dob'] = frontendDate(auth()->user()->dob);

            return $this->jsonResponse([
                'message' => trans('profile.toast.success.updated'),
                'params' => $params
            ], JsonResponse::HTTP_OK);
        } catch (\Exception $e) {
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    /**
     * Show the terms of services page for the authenticated user.
     */
    public function terms(): View
    {
        $term = Term::wherePosition('terms_of_services')->first();

        return view('dealer.profile.terms', compact('term'));
    }

    public function editCompany(): View
    {
        $dealer = Dealer::with(['user', 'addresses'])
            ->whereHas('user', fn($q) => $q->where('id', auth()->user()->id))
            ->first();

        return view('dealer.profile.modals.company-info', compact('dealer'));
    }

    public function updateCompany(Request $request): JsonResponse
    {
        $dealer = Dealer::with('addresses')
            ->whereHas('user', fn($q) => $q->where('id', auth()->user()->id))
            ->first();

        try {
            DB::beginTransaction();

            // Update dealer core info
            $dealer->update($request->only([
                'company_name',
                'registration_number',
                'tax_identification_number',
            ]));

            // Refresh address (delete old and create new)
            $dealer->addresses()->delete();
            $dealer->addresses()->create([
                'country'     => $request->input('country'),
                'state'       => $request->input('state'),
                'city'        => $request->input('city'),
                'street'      => $request->input('street'),
                'postal_code' => $request->input('postal_code'),
            ]);

            DB::commit();
            return $this->jsonResponse(['message' => trans('profile.toast.success.updated')], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function createRepresentative(): View
    {
        $dealer = Dealer::with(['user'])
            ->whereHas('user', function ($q) {
                $q->where('id', auth()->user()->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }
        return view('dealer.profile.modals.representative-create', compact('dealer'));
    }

    public function storeRepresentative(Request $request): JsonResponse
    {
        $request->validate([
            'rep_name' => 'required|string|max:255',
            'rep_cnic' => 'required|string|max:255',
            'rep_position' => 'nullable|string|max:255',
            'rep_contact' => 'nullable|string|max:255',
            'rep_email' => 'nullable|email|max:255',
        ]);
        $dealer = Dealer::whereHas('user', fn($q) => $q->where('id', auth()->user()->id))->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        try {
            DB::beginTransaction();

            $dealer->representatives()->create([
                'full_name'      => $request->input('rep_name'),
                'nic_number'     => $request->input('rep_cnic'),
                'position'       => $request->input('rep_position'),
                'contact_phone'  => $request->input('rep_contact'),
                'contact_email'  => $request->input('rep_email') ?? null,
            ]);

            DB::commit();
            return $this->jsonResponse([
                'message' => trans('profile.toast.success.created'),
                'redirect' => route('dealers.profile.index')
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function editRepresentative($id): View
    {
        $dealer = Dealer::with(['user', 'representatives'])
            ->whereHas('user', function ($q) {
                $q->where('id', auth()->user()->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        $representative = $dealer->representatives()->findOrFail($id);
        
        return view('dealer.profile.modals.representative-info', compact('dealer', 'representative'));
    }

    public function updateRepresentative(Request $request, $id): JsonResponse
    {
        $request->validate([
            'rep_name' => 'required|string|max:255',
            'rep_cnic' => 'required|string|max:255',
            'rep_position' => 'nullable|string|max:255',
            'rep_contact' => 'nullable|string|max:255',
            'rep_email' => 'nullable|email|max:255',
        ]);
        
        $dealer = Dealer::with('representatives')
            ->whereHas('user', fn($q) => $q->where('id', auth()->user()->id))
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        $representative = $dealer->representatives()->findOrFail($id);

        try {
            DB::beginTransaction();

            $representative->update([
                'full_name'      => $request->input('rep_name'),
                'nic_number'     => $request->input('rep_cnic'),
                'position'       => $request->input('rep_position'),
                'contact_phone'  => $request->input('rep_contact'),
                'contact_email'  => $request->input('rep_email') ?? null,
            ]);

            DB::commit();
            return $this->jsonResponse(['message' => trans('profile.toast.success.updated')], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function createFinancial(): View
    {
        $dealer = Dealer::with(['user'])
            ->whereHas('user', function ($q) {
                $q->where('id', auth()->user()->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        return view('dealer.profile.modals.financial-create', compact('dealer'));
    }

    public function storeFinancial(Request $request): JsonResponse
    {
        $request->validate([
            'bank_name' => 'required|string|max:255',
            'account_holder_name' => 'required|string|max:255',
            'account_number' => 'required|string|max:255',
        ]);
        $dealer = Dealer::whereHas('user', fn($q) => $q->where('id', auth()->user()->id))->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        try {
            DB::beginTransaction();

            $dealer->finances()->create([
                'name'                => $request->input('bank_name'),
                'account_holder_name' => $request->input('account_holder_name'),
                'account_number'      => $request->input('account_number'),
            ]);

            DB::commit();
            return $this->jsonResponse([
                'message' => trans('profile.toast.success.created'),
                'redirect' => route('dealers.profile.index')
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function editFinancial($id): View
    {
        $dealer = Dealer::with(['user', 'finances'])
            ->whereHas('user', function ($q) {
                $q->where('id', auth()->user()->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        $finance = $dealer->finances()->findOrFail($id);

        return view('dealer.profile.modals.financial-info', compact('dealer', 'finance'));
    }

    public function updateFinancial(Request $request, $id): JsonResponse
    {
        $request->validate([
            'bank_name' => 'required|string|max:255',
            'account_holder_name' => 'required|string|max:255',
            'account_number' => 'required|string|max:255',
        ]);

        $dealer = Dealer::with('finances')
            ->whereHas('user', fn($q) => $q->where('id', auth()->user()->id))
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        $finance = $dealer->finances()->findOrFail($id);

        try {
            DB::beginTransaction();

            $finance->update([
                'name'                => $request->input('bank_name'),
                'account_holder_name' => $request->input('account_holder_name'),
                'account_number'      => $request->input('account_number'),
            ]);

            DB::commit();
            return $this->jsonResponse(['message' => trans('profile.toast.success.updated')], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function editBusiness(): View
    {
        $dealer =  Dealer::with(['user', 'branches', 'operations'])
            ->whereHas('user', function ($q) {
                $q->where('id', auth()->user()->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        return view('dealer.profile.modals.business-info', compact('dealer'));
    }

    public function updateBusiness(Request $request): JsonResponse
    {
        $dealer = Dealer::with(['branches', 'operations'])
            ->whereHas('user', fn($q) => $q->where('id', auth()->user()->id))
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        try {
            DB::beginTransaction();

            // Reset branches & operations
            $dealer->branches()->delete();
            $dealer->operations()->delete();

            // Recreate branches
            if ($request->filled('branches')) {
                foreach ($request->input('branches') as $branch) {
                    $dealer->branches()->create([
                        'branch_name' => $branch['branch_name'] ?? null,
                        'status'      => $branch['status'] ?? 1,
                    ]);
                }
            }

            // Recreate operations
            if ($request->filled('operations')) {
                foreach ($request->input('operations') as $operation) {
                    $dealer->operations()->create([
                        'operation' => $operation['operation'],
                    ]);
                }
            }

            DB::commit();
            return $this->jsonResponse(['message' => trans('profile.toast.success.updated')], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function editDocuments(): View
    {
        $dealer = Dealer::with(['user', 'media'])
            ->whereHas('user', function ($q) {
                $q->where('id', auth()->user()->id);
            })
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        return view('dealer.profile.modals.documents-info', compact('dealer'));
    }

    public function updateDocuments(Request $request): JsonResponse
    {
        $dealer = Dealer::with('media')
            ->whereHas('user', fn($q) => $q->where('id', auth()->user()->id))
            ->first();

        if (!$dealer) {
            abort(404, 'Dealer profile not found.');
        }

        try {
            DB::beginTransaction();

            // Handle document uploads if provided
            if ($request->hasFile('documents')) {
                foreach ($request->file('documents') as $document) {
                    $path = $this->uploadPublicImage($document, 'dealer-documents');
                    $dealer->media()->create([
                        'path' => $path,
                        'type' => $document->getMimeType(),
                    ]);
                }
            }

            DB::commit();
            return $this->jsonResponse(['message' => trans('profile.toast.success.updated')], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function editAvatar(): View
    {
        return view('dealer.profile.modals.avatar');
    }

    public function updateAvatar(Request $request): JsonResponse
    {
        try {
            $validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
                'avatar' => 'required|file|mimes:jpg,png,gif|max:10240',
            ], [
                'avatar.size' => 'Avatar must be less then 1 MB.'
            ]);

            if ($validator->fails()) {
                throw new \Exception($validator->errors()->first(), JsonResponse::HTTP_UNPROCESSABLE_ENTITY);
            }

            $path = $this->uploadPublicImage(
                $request->file('avatar'),
                'avatars',
                auth()->user()->avatar
            );

            auth()->user()->update([
                'avatar' => $path,
            ]);

            return $this->jsonResponse([
                'message' => 'Avatar updated successfully.',
                'params' => [
                    'url' => \Illuminate\Support\Facades\Storage::url($path)
                ]
            ]);
        } catch (\Exception $e) {
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }

    public function editPassword(): View
    {
        return view('dealer.profile.modals.password');
    }

    public function updatePassword(\App\Http\Requests\Profile\PasswordUpdateRequest $request): JsonResponse
    {
        try {
            if (!(\Illuminate\Support\Facades\Hash::check($request->get('old_password'), auth()->user()->password))) {
                return $this->jsonResponse([
                    'old_password' => ['The provided old password is incorrect.']
                ], JsonResponse::HTTP_UNPROCESSABLE_ENTITY);
            }

            auth()->user()->update([
                'password' => \Illuminate\Support\Facades\Hash::make($request->password),
            ]);

            return $this->jsonResponse('Password updated successfully.', JsonResponse::HTTP_OK);
        } catch (\Exception $e) {
            Log::error($e->getMessage(), $e->getTrace());
            return $this->sendServerErrorResponse($e);
        }
    }
}

