<?php

namespace App\Http\Controllers\API\v1;

use App\Http\Controllers\Controller;
use App\Models\Employee;
use App\Models\EmployeeLoan;
use App\Models\Loan;
use App\Models\LoanAdvancePayment;
use App\Models\LoanPausedHistory;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Throwable;

class EmployeeLoanController extends Controller
{
    public function index(Request $request)
    {
        //
        $keyword = $request->input('keyword', null);
        $perPage = $request->input('per_page',PHP_INT_MAX);
        $sortBy = $request->input('sortBy', '');
        $sortType = $request->input('sortType', '');
        $data = EmployeeLoan::with(
            'employee:id,employee_id,firstname,lastname',
            'loan:id,name'
            )
        ->when($keyword, function($q) use ($keyword) {
            $keyword = str_replace([';',','], ' ',$keyword);
            $keyword = str_replace('  ',' ',$keyword);
            $keywords = explode(" ",$keyword);
            foreach($keywords as $word) {
                $q->where(fn($q2) => $q2->where('employee_id','like',"{$word}%")
                    ->orWhereHas('employee', fn($q3) =>
                        $q3->where('lastname', 'like',"%{$word}%")
                        ->orWhere('middlename', 'like',"%{$word}%")
                        ->orWhere('firstname', 'like',"%{$word}%"))
                    ->orWhereHas('loan', fn($q3) =>
                        $q3->where('name', 'like',"%{$word}%")));
            };
        });

        if (!empty($sortBy) && !empty($sortType)) {
            $data = $data->orderBy($sortBy, $sortType);
        }

        $data = $data->paginate($perPage);
        return response()->json($data);
    }

    public function show(string $id)
    {
        $data = Loan::where('employee_loan_id', '=', $id)->get();

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

    public function fullPaymentList(Request $request,string $id)
    {
        $data = LoanAdvancePayment::where('employee_id', $request->employee_id)->where('employee_loan_id', '=', $id)->get();

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

    public function getRecordByEmployee(Request $request)
    {
        $employee = Auth::user();

        //
        $keyword = $request->input('keyword', '');
        $perPage = $request->input('per_page',PHP_INT_MAX);
        $sortBy = $request->input('sortBy', '');
        $sortType = $request->input('sortType', '');

        $data = EmployeeLoan::with(
            'employee:id,employee_id,firstname,lastname',
            'loan:id,name'
            )->where(function ($query) use ($keyword) {
                $keyword = str_replace(" ", "%", $keyword);
                $query->where('employee_id', 'like', '%' . $keyword . '%');
            });

        if (!empty($sortBy) && !empty($sortType)) {
            $data = $data->orderBy($sortBy, $sortType);
        }

        $data = $data->where('employee_id', $employee->employee_id);
        $data = $data->get();

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

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'employee_id' => "required",
        ]);

        if ($validator->fails()) {
            return $this->validationErrorResponse($validator);
        }

        $user = Employee::where('employee_id', $request->employee_id)->first();

        DB::beginTransaction();

        try {
            $attachment_name = $this->handleFileUpload($request->file('attachment'), 'employee-loans');

            $status = EmployeeLoan::create([
                'employee_id' => $request->employee_id,
                'company_id' => $user->company_id,
                'dealer_id' => $user->dealer_id,
                'loan_id' => $request->loan_id,
                'amount' => $request->amount,
                'frequency' => $request->frequency,
                'term' => $request->term,
                'monthly' => $request->monthly,
                'effectivity_date' => $request->effectivity_date,
                'attachment' => $attachment_name,
                'balance' => $request->balance,
                'remarks' => $request->remarks,
            ]);

            DB::commit();

            for($term = 1; $term <= $request->term; $term++)
            {
                $addMonthly = Loan::create([
                    'employee_loan_id' => $status->id,
                    'amount' => $status->monthly,
                ]);
            }

            return response()->json([
                'status'  => true,
                'message' => 'Saved successfully!',
                'data'    => $status
            ], 201);

        } catch (Exception $e) {
            DB::rollBack();
            return response()->json([
                'status' => false,
                'message' => 'An error occurred!',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function update(Request $request)
    {
        $id = $request->id;

        $data = EmployeeLoan::where('id', $id)->first();

        // dd($request->all());
        $validator = Validator::make($request->all(), [
            'employee_id' => "required",
        ]);

        /** If validation fails return with error message */
        if ($validator->fails()) {
            $errors = $validator->errors();
            $first = $errors->getMessages();
            return response()->json([
                'status'  => false,
                'message' => (reset($first))[0],
                'errors'  => $errors
            ], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        $attachment_name = $request->attachment;

        if($data->attachment != $request->attachment)
        {
            $attachment_file_path = 'employee-loans/' . $data->attachment;
            if(Storage::exists($attachment_file_path))
            {
                Storage::delete($attachment_file_path);
            }

            if($request->hasFile('attachment')) {
                $image      = $request->file('attachment');
                $attachment_name  = time().'_'.$image->getClientOriginalName();
                $path       = "employee-loans/".$attachment_name;
                if(!Storage::disk('local')->put($path, file_get_contents($image)))
                {
                    return response()->json(['message'=> "Failed to upload attachment"],304);
                }
            }
            else
            {
                $attachment_name = null;
            }
        }

        DB::connection()->beginTransaction();

        if($data->monthly != $request->monthly || $data->term != $request->term || $data->frequency != $request->frequency){
            $loanRecord = Loan::where('employee_loan_id', $id)->whereNull('date_paid')->delete();

            DB::connection()->commit();
        }

        try {
            $data->employee_id = $request->employee_id;
            $data->loan_id = $request->loan_id;
            $data->amount = $request->amount;
            $data->frequency = $request->frequency;
            $data->term = $request->term;
            $data->monthly = $request->monthly;
            $data->effectivity_date = $request->effectivity_date;
            $data->attachment = $attachment_name;
            $data->balance = $request->balance;
            $data->remarks = $request->remarks;

            if($request->frequency == 3){
                $request['term'] = $request->term * 2;
            }

            for($term = 1; $term <= $request->term; $term++)
            {
                $addMonthly = Loan::create([
                    'employee_loan_id' => $data->id,
                    'amount' => $request->frequency == 3 ? $data->monthly / 2 : $data->monthly,
                ]);
            }

            $data->save();

            DB::connection()->commit();

            return response()->json([
                'status'  => true,
                'message' => 'Saved successfully!',
                'data'    => $data
            ],201);

        } catch (Throwable $e) {

            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    private function validationErrorResponse($validator)
    {
        return response()->json([
            'status' => false,
            'message' => 'Validation failed!',
            'error' => $validator->errors()
        ], 422);
    }

    private function handleFileUpload($file, $path)
    {
        if ($file) {
            $attachment_name = time() . '_' . $file->getClientOriginalName();
            $storagePath = "$path/$attachment_name";
            Storage::disk('local')->put($storagePath, file_get_contents($file));
            return $attachment_name;
        }
        return '';
    }

    private function prepareMrfData($request, $attachment_name)
    {
        return [
            'company_id' => $request->company_id,
            'nature_of_request' => $request->nature_of_request,
            'classification' => $request->classification,
            'job_title' => $request->job_title,
            'salary_grade' => $request->salary_grade,
            'salary' => $request->salary,
            'replacement_position_number' => $request->replacement_position_number,
            'employee_name_to_be_replaced1' => $request->employee_name_to_be_replaced1,
            'nature_of_seperation1' => $request->nature_of_seperation1,
            'date_of_seperation1' => $request->date_of_seperation1,
            'new_position_number' => $request->new_position_number,
            'date_needed' => $request->date_needed,
            'employment_status' => $request->employment_status,
            'supporting_document' => $attachment_name,
            'document_type' => $request->document_type,
            'working_position_title' => $request->working_position_title,
            'inclusive_period' => $request->inclusive_period,
            'justification' => $request->justification,
            'job_design' => $request->job_design,
            'requested_by' => $request->requested_by,
            'recommended_by' => $request->recommended_by,
            'endorsed_by' => $request->endorsed_by,
            'approved_by' => $request->approved_by,
            'status' => $request->status
        ];
    }

    // private function sendNotification($request, $status)
    // {
    //     $email_to = match ($request->status) {
    //         2 => $this->getEmployeeEmailData($request->approved_by),
    //         1 => $this->getEmployeeEmailData($request->endorsed_by),
    //         default => $this->getEmployeeEmailData($request->recommended_by),
    //     };

    //     if ($email_to) {
    //         Notification::send($email_to, new MrfNotification($status));
    //     }
    // }

    public function activation(Request $request, int $id)
    {
        $data = EmployeeLoan::find($id);

        DB::connection()->beginTransaction();

        try {
                $loan_paused_history = LoanPausedHistory::create([
                    'employee_loan_id' => $data->id,
                    'date_pause' => $request->formType == 'pause' ? date('Y-m-d H:i:s') : null,
                    'date_resume' => $request->formType != 'pause' ? date('Y-m-d H:i:s') : null
                ]);

            DB::connection()->commit();

        } catch (Throwable $e) {

            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }

        try {
            $data->paused = $request->formType == 'pause' ? 1 : 0;
            $data->resume_date = $request->formType == 'pause' ? $request->resume_date : null;

            $data->save();

            DB::connection()->commit();

            return response()->json([
                'status'  => true,
                'message' => 'Saved successfully!',
                'data'    => $data
            ],201);

        } catch (Throwable $e) {

            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    public function fullPayment(Request $request, int $id)
    {
        $loan_advance_payment = EmployeeLoan::find($id);
        $loanTotal = Loan::where('employee_loan_id', $id)->whereNotNull('date_paid')->pluck('amount')->sum();
        // $employee_loan = loan_advance_payment::where('id', $id)->pluck('amount')->first();

        DB::connection()->beginTransaction();

        try {
            // dd($request->amount);
                $loan_payment = LoanAdvancePayment::create([
                    'employee_id' => $loan_advance_payment->employee_id,
                    'employee_loan_id' => $loan_advance_payment->id,
                    // 'amount' => $loan_advance_payment->amount - $loanTotal,
                    'amount' => $request->amount,
                    'paid_date' => $request->paid_date
                ]);
                

            DB::connection()->commit();

        } catch (Throwable $e) {

            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }

        try {
            $loan_advance_payment->paid =  1;

            $loan_advance_payment->save();

            DB::connection()->commit();

            return response()->json([
                'status'  => true,
                'message' => 'Saved successfully!',
                'data'    => $loan_advance_payment
            ],201);

        } catch (Throwable $e) {

            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    public function destroy(int $id)
    {
        $data = EmployeeLoan::find($id);

        DB::connection()->beginTransaction();

        $data->delete();

        DB::connection()->commit();

        return response()->json(['message' => "Record successfully deleted!"],201);
    }
}
