<?php

    namespace Modules\Lpj\Http\Controllers;

    use App\Http\Controllers\Controller;
    use Exception;
    use Illuminate\Http\JsonResponse;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\DB;
    use Maatwebsite\Excel\Facades\Excel;
    use Modules\Location\Models\City;
    use Modules\Location\Models\District;
    use Modules\Location\Models\Province;
    use Modules\Location\Models\Village;
    use Modules\Lpj\Exports\PermohonanExport;
    use Modules\Lpj\Http\Requests\PermohonanRequest;
    use Modules\Lpj\Models\Branch;
    use Modules\Lpj\Models\Debiture;
    use Modules\Lpj\Models\DokumenJaminan;
    use Modules\Lpj\Models\JenisFasilitasKredit;
    use Modules\Lpj\Models\NilaiPlafond;
    use Modules\Lpj\Models\Penilaian;
    use Modules\Lpj\Models\Permohonan;
    use Modules\Lpj\Models\PermohonanPembatalan;
    use Modules\Lpj\Models\PersetujuanPenawaran;
    use Modules\Lpj\Models\StatusPermohonan;
    use Modules\Lpj\Models\TujuanPenilaian;
    use Modules\Lpj\Services\PermohonanHistoryService;
    use Modules\Lpj\Models\Noc;



    class PermohonanController extends Controller
    {
        public    $user;
        protected $historyService;

        public function __construct(PermohonanHistoryService $historyService)
        {
            $this->historyService = $historyService;
        }

        public function index()
        {
            return view('lpj::permohonan.index');
        }

        public function store(PermohonanRequest $request)
        {
            $validate = $request->validated();
            if ($validate) {
                if(auth()->user()->hasRole('admin')){
                       $validate['status'] = "preregister";
                }
                try {
                    // Process file upload
                    $filePath = null;
                    if ($request->hasFile('attachment')) {
                        $file     = $request->file('attachment');
                        $fileName = time() . '_' . $file->getClientOriginalName();
                        $filePath = $file->storeAs('permohonan_attachments', $fileName, 'public');
                    }

                    // Get keterangan if provided
                    $keterangan = $request->input('keterangan') ?? null;


                    // Save to database
                    $permohonan = Permohonan::create($validate);

                    // Create history
                    $this->historyService->createHistory(
                        $permohonan,
                        $validate['status'],
                        $keterangan,
                        [],  // beforeRequest is empty for new permohonan
                        $permohonan->toArray(),
                        $filePath,
                    );

                    $documents = DokumenJaminan::where('permohonan_id', $permohonan->id)->get();
                    if (count($documents) < 1) {
                        return redirect()->route(
                            'debitur.jaminan.create',
                            array_merge(['permohonan_id' => $permohonan->id], ['id' => $permohonan->debiture->id]),
                        )->with('success', 'Permohonan created successfully, Lengkapi data jaminan terlebih dahulu');
                    }
                    return redirect()
                        ->route('permohonan.index')->with('success', 'Permohonan created successfully');
                } catch (Exception $e) {
                    return redirect()
                        ->route('permohonan.create')->with('error', 'Failed to create permohonan' . $e->getMessage());
                }
            } else {
                return redirect()
                    ->route('permohonan.create')->with('success', 'error naon iye')->withInput();
            }
        }

        public function create()
        {
            return view('lpj::permohonan.create');
        }

        public function createPermohonan($debitur)
        {
            $branches        = Branch::all();
            $debitur         = Debiture::find($debitur);
            $tujuanPenilaian = TujuanPenilaian::all();
            $status          = StatusPermohonan::all();
            $fasilitasKredit = JenisFasilitasKredit::all();
            $plafond         = NilaiPlafond::all();

            return view(
                'lpj::permohonan.form',
                compact('branches', 'debitur', 'tujuanPenilaian', 'status', 'fasilitasKredit', 'plafond'),
            );
        }

        public function edit($id)
        {
            $permohonan      = Permohonan::find($id);
            $branches        = Branch::all();
            $debitur         = Debiture::find($permohonan->debiture_id);
            $tujuanPenilaian = TujuanPenilaian::all();
            $status          = StatusPermohonan::all();
            $provinces       = Province::all();
            $cities          = City::where('province_code', $debitur->province_code)->get();
            $districts       = District::where('city_code', $debitur->city_code)->get();
            $villages        = Village::where('district_code', $debitur->district_code)->get();
            $documents       = DokumenJaminan::with('pemilik', 'detail')->where('debiture_id', $id)->get();

            $fasilitasKredit = JenisFasilitasKredit::all();
            $plafond         = NilaiPlafond::all();

            return view(
                'lpj::permohonan.form',
                compact(
                    'permohonan',
                    'branches',
                    'debitur',
                    'tujuanPenilaian',
                    'status',
                    'provinces',
                    'cities',
                    'districts',
                    'villages',
                    'documents',
                    'fasilitasKredit',
                    'plafond',
                ),
            );
        }

        public function destroy($id)
        {
            try {
                // Delete from database
                $permohonan = Permohonan::find($id);
                $permohonan->delete();

                echo json_encode(['success' => true, 'message' => 'Permohonan deleted successfully']);
            } catch (Exception $e) {
                echo json_encode(['success' => false, 'message' => 'Failed to delete permohonan']);
            }
        }

        public function dataForDatatables(Request $request)
        {
            if (is_null($this->user) || !$this->user->can('debitur.view')) {
                //abort(403, 'Sorry! You are not allowed to view users.');
            }

            // Retrieve data from the database
            $query = Permohonan::query();

            if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
                $query = $query->where('branch_id', Auth::user()->branch_id);
            }

            $query = $query->orderBy('nomor_registrasi', 'desc');
            // Apply search filter if provided
            if ($request->has('search') && !empty($request->get('search'))) {
                $search = $request->get('search');
                $query->where(function ($q) use ($search) {
                    $q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
                    $q->orWhere('mig_mst_lpj_nomor_jaminan', 'LIKE', '%' . $search . '%');
                    $q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhere('status', 'LIKE', '%' . $search . '%');
                });
            }

            // Apply sorting if provided
            if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
                $order  = $request->get('sortOrder');
                $column = $request->get('sortField');
                $query->orderBy($column, $order);
            }

            // Get the total count of records
            $totalRecords = $query->count();
            $size         = $request->get('size', 10);
            if ($size == 0) {
                $size = 10;
            }

            // Apply pagination if provided
            if ($request->has('page') && $request->has('size')) {
                $page   = $request->get('page');
                $size   = $request->get('size');
                $offset = ($page - 1) * $size; // Calculate the offset

                $query->skip($offset)->take($size);
            }

            // Get the filtered count of records
            $filteredRecords = $query->count();

            // Get the data for the current page
            $data = $query->get();

            $data = $data->map(function ($item) {
                return [
                    'id'                        => $item->id,
                    'nomor_registrasi'          => $item->nomor_registrasi,
                    'mig_mst_lpj_nomor_jaminan' => $item->mig_mst_lpj_nomor_jaminan,
                    'tanggal_permohonan'        => $item->tanggal_permohonan ? dateFormat(
                        $item->tanggal_permohonan,
                    ) : null,
                    'pemohon'                   => $item->user->name ?? 'N/A',
                    'branch'                    => $item->branch->name ?? 'N/A',
                    'debiture'                  => [
                        'name' => $item->debiture->name,
                    ],
                    'tujuan_penilaian'          => [
                        'code' => $item->tujuanPenilaian->code ?? null,
                        'name' => $item->tujuanPenilaian->name ?? null,
                    ],
                    'status'                    => $item->status,
                    'documents'                 => count($item->documents),
                    'keterangan'                => $item->keterangan,
                    'penilaian'                 => [
                        'id'                => $item->penilaian->id ?? null,
                        'waktu_penilaian'   => $item->penilaian->waktu_penilaian ?? null,
                        'rejected_note'     => $item->penilaian->rejected_note ?? null,
                        'authorized_status' => $item->penilaian->authorized_status ?? null,
                    ],
                    'registrasi_catatan'        => $item->registrasi_catatan,
                ];
            });

            // Calculate the page count
            $pageCount = ceil($totalRecords / $size);

            // Calculate the current page number
            $currentPage = max(1, $request->get('page', 1));

            // Return the response data as a JSON object
            return response()->json([
                'draw'            => $request->get('draw'),
                'recordsTotal'    => $totalRecords,
                'recordsFiltered' => $filteredRecords,
                'pageCount'       => $pageCount,
                'page'            => $currentPage,
                'totalCount'      => $totalRecords,
                'data'            => $data,
            ]);
        }

        public function export()
        {
            return Excel::download(new PermohonanExport(), 'permohonan.xlsx');
        }

        public function authorization()
        {
            return view('lpj::permohonan.authorization.index');
        }

        public function dataForAuthorization(Request $request)
        {
            if (is_null($this->user) || !$this->user->can('debitur.view')) {
                //abort(403, 'Sorry! You are not allowed to view users.');
            }

            // Retrieve data from the database
            $query = Permohonan::query()->with('documents')->has('documents', '>', 0)->where('status', '=', 'order');

            if (!Auth::user()->hasAnyRole(['administrator'])) {
                $query = $query->where('branch_id', Auth::user()->branch_id);
            }

            // Apply search filter if provided
            if ($request->has('search') && !empty($request->get('search'))) {
                $search = $request->get('search');
                $query->where(function ($q) use ($search) {
                    $q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
                    $q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
                    $q->orWhere('status', 'LIKE', '%' . $search . '%');
                });
            }

            // Apply sorting if provided
            if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
                $order  = $request->get('sortOrder');
                $column = $request->get('sortField');
                $query->orderBy($column, $order);
            }

            // Get the total count of records
            $totalRecords = $query->count();

            // Apply pagination if provided
            if ($request->has('page') && $request->has('size')) {
                $page   = $request->get('page');
                $size   = $request->get('size');
                $offset = ($page - 1) * $size; // Calculate the offset

                $query->skip($offset)->take($size);
            }

            // Get the filtered count of records
            $filteredRecords = $query->count();

            // Get the data for the current page
            $data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->get();

            // Calculate the page count
            $pageCount = ceil($totalRecords / $request->get('size'));

            // Calculate the current page number
            $currentPage = 0 + 1;

            // Return the response data as a JSON object
            return response()->json([
                'draw'            => $request->get('draw'),
                'recordsTotal'    => $totalRecords,
                'recordsFiltered' => $filteredRecords,
                'pageCount'       => $pageCount,
                'page'            => $currentPage,
                'totalCount'      => $totalRecords,
                'data'            => $data,
            ]);
        }

        public function showAuthorization($id)
        {
            $permohonan = Permohonan::find($id);
            return view('lpj::permohonan.authorization.show', compact('permohonan'));
        }

        public function updateAuthorization(Request $request, $id)
        {
            try {
                $permohonan             = Permohonan::find($id);
                $permohonan->status     = $request->status;
                $permohonan->keterangan = $request->keterangan;
                $permohonan->save();

                if ($permohonan->status_bayar == 'belum_bayar') {
                    PersetujuanPenawaran::firstOrCreate(
                        ['permohonan_id' => $id],
                        ['created_by' => Auth::id()]
                    );
                }

                if ($permohonan->status == 'sudah_dibayar') {

                    $documents = $permohonan->dokumenjaminan->first(function ($doc) {
                        return $doc->detail && $doc->detail->contains('name', 'Bukti Bayar');
                    });

                    $buktiBayar = $documents->detail->filter(function ($detail) {
                        return $detail->name == 'Bukti Bayar';
                    })->first() ?? null;

                    if ($buktiBayar->isEmpty()) {
                        return redirect()->route('authorization.show', $id)->with('error', 'Bukti Bayar harus diunggah');
                    }

                    $dokumenJaminan = json_decode($buktiBayar->dokumen_jaminan);

                    $persetujuanPenawaran = PersetujuanPenawaran::firstOrCreate(
                        ['permohonan_id' => $id],
                        [
                            'created_by' => Auth::id(),
                            'bukti_bayar' => $buktiBayar->first()->dokumen_jaminan[0],
                        ]
                    );

                    try {
                        Noc::updateOrCreate([
                            'permohonan_id' => $persetujuanPenawaran->permohonan_id,
                            'persetujuan_penawaran_id' => $persetujuanPenawaran->id
                        ],[
                            'bukti_bayar' => $persetujuanPenawaran->bukti_bayar,
                        ]);
                    } catch (\Exception $e) {
                        \Log::error('Failed to create or update NOC: ' . $e->getMessage());
                        return redirect()
                            ->route('persetujuan-penawaran.index')
                            ->with('error', 'Persetujuan Penawaran berhasil disimpan tetapi gagal membuat NOC: ' . $e->getMessage());
                    }
                }



            } catch (Exception $e) {
                return redirect()->route('authorization.show', $id)->with('error', 'Failed to update permohonan');
            }

            return redirect()->route('authorization.index')->with('success', 'Permohonan updated successfully');
        }

        public function show($id)
        {
            $permohonan = Permohonan::find($id);

            return view('lpj::permohonan.show', compact('permohonan'));
        }

        public function print($id)
        {
            $permohonan = Permohonan::find($id);
            return view('lpj::permohonan.print', compact('permohonan'));

            //            $pdf = Pdf::loadView('lpj::permohonan.print', compact('permohonan'));
            //          return $pdf->stream();
        }

        public function showPembatalan($id)
        {
            $permohonan = Permohonan::with(['pembatalan', 'debiture'])->findOrFail($id);
            return view('lpj::permohonan.pembatalan-form', compact('permohonan'));
        }

        public function pembatalan(Request $request)
        {
            // Validate the request
            $validatedData = $request->validate([
                'permohonan_id'     => 'required|exists:permohonan,id',
                'alasan_pembatalan' => 'required|string',
                'file_pembatalan'   => 'required|file|mimes:pdf,doc,docx|max:2048',
            ]);

            // Handle file upload
            if ($request->hasFile('file_pembatalan')) {
                $file                             = $request->file('file_pembatalan');
                $filename                         = time() . '_' . $file->getClientOriginalName();
                $filePath                         = $file->storeAs('pembatalan', $filename, 'public');
                $validatedData['file_pembatalan'] = $filePath;
            }

            // Add created_by
            $validatedData['created_by'] = auth()->id();

            // Create new PermohonanPembatalan
            $pembatalan = PermohonanPembatalan::create($validatedData);

            return redirect()->route('permohonan.index')->with('success', 'Pembatalan Permohonan Menunggu Approval');
        }

        public function storeAproved(Request $request, $id)
        : JsonResponse {
            $data = [];
            if (request()->ajax()) {
                try {
                    $penilaian = Penilaian::findOrFail($id);
                    $penilaian->update([
                        'authorized_status' => 1,
                    ]);

                    $permohonan = Permohonan::findOrFail($request->permohonan_id);

                    $permohonan->update([
                        'status' => 'proses-survey',
                    ]);

                    $data['status']  = 'success';
                    $data['message'] = 'Jadwal ' . $request->noReg . ' berhasil di aprove';
                } catch (Exception $e) {
                    $data['status']  = 'error';
                    $data['message'] = 'Gagal membuat jadwal: ' . $e->getMessage();
                }
            } else {
                $data['status']  = 'error';
                $data['message'] = "no ajax request";
            }

            return response()->json($data);
        }

        public function update(PermohonanRequest $request, $id)
        {
            $permohonan    = Permohonan::findOrFail($id);
            $beforeRequest = $permohonan->toArray();

            $validate = $request->validated();
            if ($validate) {
                try {
                    // Update in database

                    if ($permohonan->status == 'revisi') {
                        $validate['status'] = 'order';
                    }
                    $permohonan->update($validate);

                    $documents = DokumenJaminan::where('permohonan_id', $permohonan->id)->get();
                    if (count($documents) < 1) {
                        return redirect()->route(
                            'debitur.jaminan.create',
                            array_merge(['permohonan_id' => $permohonan->id], ['id' => $permohonan->debiture->id]),
                        )->with('success', 'Permohonan created successfully, Lengkapi data jaminan terlebih dahulu');
                    }

                    return redirect()
                        ->route('permohonan.index')->with('success', 'Permohonan updated successfully');
                } catch (Exception $e) {
                    return redirect()
                        ->route('permohonan.edit', $id)->with('error', 'Failed to update permohonan');
                }
            }
        }

        public function storeRescheduleSurvey(Request $request, $id)
        {
            try {
                $validatedData = $request->validate([
                    'permohonan_id'    => 'required|exists:permohonan,id',
                    'penilaian_id'     => 'nullable',
                    'nomor_registrasi' => 'required',
                    'reschedule_note'  => 'required',
                    'reschedule_date'  => 'required',
                    'keterangan'       => 'required',
                ]);

                DB::beginTransaction();

                $permohonan = Permohonan::findOrFail($request->permohonan_id);
                $permohonan->update([
                    'status' => 'request-reschedule',
                ]);

                $penilaian = Penilaian::findOrFail($id);

                $penilaian->update([
                    'reschedule_date' => $request->reschedule_date,
                    'reschedule_note' => $request->reschedule_note,
                ]);

                DB::commit();
                return response()->json([
                    'status'  => 'success',
                    'message' => 'Proses request reschedule permohonan Nomor registrasi ' . $request->nomor_registrasi . ' berhasil',
                ]);
            } catch (Exception $e) {
                DB::rollBack();
                return response()->json([
                    'status'  => 'error',
                    'message' => 'Gagal membuat request reschedule: ' . $e->getMessage(),
                ]);
            }
        }

    }
