<?php

namespace Modules\HospitalPortal\Http\Controllers\Api;

use App\Events\ClaimRequested;
use App\Helpers\Helper;
use App\Models\ClaimRequest;
use App\Models\File;
use App\Models\Member;
use App\Services\ClaimRequestService;
use App\Services\ClaimService;
use Exception;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\HospitalPortal\Transformers\ClaimRequestResource;
use Modules\HospitalPortal\Transformers\ClaimRequestShowResource;
use PDF;
use Illuminate\Support\Facades\DB;
use Modules\HospitalPortal\Helpers\ApiResponse;
use Illuminate\Support\Facades\Validator;

class ClaimRequestController extends Controller
{
    /**
     * Display a listing of the resource.
     * @return Renderable
     */
    private static $code_prefix = 'CRQ-H';
    public function index(request $request)
    {
        $claimRequests = ClaimRequest::query()
                                ->when($request->search, function ($q, $search) {
                                    $q->where('code', 'LIKE', "%".$search."%");
                                })
                                ->when($request->orderBy, function ($q, $orderBy) use ($request) {
                                    if (in_array($orderBy, ['submission_date', 'code'])) {
                                        $q->orderBy($orderBy, $request->order);
                                    }
                                })
                                ->when($request->status, function($q, $status) {
                                    $q->where('status', $status);
                                })
                                ->with(['member'])
                                ->orderBy('created_at', 'DESC')
                                ->paginate();

        return Helper::responseJson($claimRequests);
    }

    /**
     * Show the form for creating a new resource.
     * @return Renderable
     */
    public function create()
    {
        return view('hospitalportal::create');
    }

    /**
     * Store a newly created resource in storage.
     * @param Request $request
     * @return Renderable
     */
    public function store(Request $request)
    {
        $data = [
            'request_logs_id' => $request->request_logs_id,
            'member_id' => $request->member_id,
            'service_code' => $request->service_code
        ];
        $validator = Validator::make($request->all(), [
            'request_logs_id' => 'required',
            'member_id' => 'required',
            'service_code' => 'required'
        ], [
            'request_logs_id.required' => trans('Validation.required',['attribute' => 'Request Log ID']),
            'member_id.required' => trans('Validation.required',['attribute' => 'Member ID']),
            'service_code.required' => trans('Validation.required',['attribute' => 'Service Code'])
        ]);
        if ($validator->fails())
        {
            return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
        }
        else
        {
            $check_claim_requests = DB::table('claim_requests')
            ->where('claim_requests.request_log_id', '=', $request->request_logs_id)
            ->first();
            if(!$check_claim_requests)
            {
                try {
                    DB::beginTransaction();
                    $code = $this->getNextCode();
                    $member = Member::find($request->member_id);
                    $newClaimRequest = ClaimRequestService::storeClaimRequest(
                        row: [], 
                        code: $code, 
                        member: $member, 
                        paymentType: 'reimbursement', 
                        serviceCode: $request->service_code,
                        requestLogID: $request->request_logs_id,
                    );
                    // Log History
                    $newClaimRequest->histories()->create([
                        'title' => 'New Claim Requested',
                        'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})",
                        'type' => 'info',
                        'system_origin' => 'hospital-portal'
                    ]);
    
                    // Claim Log
                    DB::table('claim_logs')
                    ->insert([
                        'claim_request_id' => $newClaimRequest->id,
                        'status' => 'requested',
                        'date' => date('Y-m-d H:i:s'),
                        'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})",
                        'system_origin' => 'hospital-portal',
                        'created_by' => auth()->user()->id,
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at'=> date('Y-m-d H:i:s'),
                    ]);
    
    
                    if ($request->hasFile('additional_files')) {
                        foreach ($request->additional_files as $file) {
                            $pathFile = File::storeFile('additional-files', $newClaimRequest->id, $file);
                            $newClaimRequest->files()->updateOrCreate([
                                'type' => 'additional-files',
                                'name' => File::getFileName('additional-files', $newClaimRequest->id, $file),
                                'original_name' => $file->getClientOriginalName(),
                                'extension' => $file->getClientOriginalExtension(),
                                'path' => $pathFile,
                                'created_by' => auth()->user()->id,
                                'updated_by' => auth()->user()->id,
                            ]);
                        }
                    }
                    DB::commit();
                    return ApiResponse::apiResponse('Success', $data, trans('Message.success'), 200);
                }
                catch (\Exception $e) {
                    DB::rollback();
                    return ApiResponse::apiResponse("Error", $data, $e->getMessage(), 500);
                }
            }
            else
            {
                return ApiResponse::apiResponse("Error", $data, trans('Message.already_exists'), 409);
            }
            
        }
    }

    /**
     * Show the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function show($id)
    {
        $claimRequest = ClaimRequest::findOrFail($id);
        $claimRequest->load([
            'histories' => function ($history) {
                $history->latest();
            },
            'files',
        ]);

        return Helper::responseJson(data: ClaimRequestShowResource::make($claimRequest));
    }

    /**
     * Show the form for editing the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function edit($id)
    {
        return view('hospitalportal::edit');
    }

    /**
     * Update the specified resource in storage.
     * @param Request $request
     * @param int $id
     * @return Renderable
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Renderable
     */
    public function destroy($id)
    {
        //
    }

    public function generateLog($claim_request_id)
    {
        $claimRequest = ClaimRequest::findOrFail($claim_request_id);

        $service_code = $claimRequest->service_code;
        if ($claimRequest->status != 'approved') {
            throw new Exception("Belum Teverifikasi", 1);
        }

        $member = Member::findOrFail($claimRequest->member_id)
                ->load([
                        // 'currentPlan',
                        'currentPlan' => function ($plan) use ($claim_request_id, $service_code) {
                            $plan->where('plans.service_code', $service_code);
                        }, 
                        'currentPolicy', 
                        'currentPlan.corporateBenefits', 
                        'currentPlan.corporateBenefits.benefit'
                ]);

        $pdf = PDF::loadView('pdf.guaranted_leter', compact('member', 'claimRequest'));
        return $pdf->download('Guaranted Letter - '.$member->full_name.'.pdf');
        
        return $claimRequest;
    }

    public static function getNextCode()
    {
        $last_number = ClaimRequest::withTrashed()->max('code');
        $last_number_parts = explode('-', $last_number);
        $next_number = count($last_number_parts) < 3 ? 1 : ((int) $last_number_parts[2] + 1);
        return self::makeCode($next_number);
    }

    public static function makeCode($next_number)
    {
        // Pastikan $next_number adalah integer positif
        $next_number = max(1, (int) $next_number);

        // Menghasilkan kode dengan format yang diinginkan
        return self::$code_prefix . '-' . str_pad($next_number, 5, '0', STR_PAD_LEFT);
    }

    public function get_claim_requests(Request $request)
    {

        $limit = $request->has('per_page') ? $request->input('per_page') : 10;

        $results = DB::table('claim_requests')
                    ->leftJoin('claims', 'claim_requests.id', '=', 'claims.claim_request_id')
                    ->leftJoin('members', 'claim_requests.member_id', '=', 'members.id')
                    ->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id')
                    ->leftJoin('corporate_divisions', 'corporate_employees.division_id', '=', 'corporate_divisions.id')
                    ->when($request->input('search'), function ($query, $search) {
                        $query->where(function ($query) use ($search) {
                            $query->orWhere('claim_requests.code', 'like', "%" . ($search == 'outpatient' || $search == 'Outpatient' ? 'OP' : 'IP') . "%")
                                ->orWhere('members.member_id', 'like', "%" . $search . "%")
                                ->orWhere('members.name', 'like', "%" . $search . "%")
                                ->orWhere('corporate_divisions.name', 'like', "%" . $search . "%")
                                ->orWhere('claim_requests.status', 'like', "%" . $search . "%")
                                ->orWhere('claim_requests.submission_date', 'like', "%" . $search . "%")
                                ->orWhere('claims.status', 'like', "%" . $search . "%");
                        });
                    })
                    ->when($request->has('orderBy'), function ($query) use ($request) {
                        $orderBy = $request->orderBy;
                        $direction = $request->order ?? 'asc';

                        $query->orderBy($orderBy, $direction);
                    })
                    ->when($request->input('start_date') && !$request->input('end_date'), function ($query, $start_date) {
                        $query->where(function ($query) use ($start_date) {
                            $query->where('claim_requests.submission_date', '<', $start_date);
                        });
                    })
                    ->when($request->input('status'), function ($query, $status) {
                        $query->where(function ($query) use ($status) {
                            
                            if ($status === 'requested') {
                                $query->where('claim_requests.status', '=', 'requested');
                            }
                    
                            if ($status === 'reviewed') {
                                $query->where('claim_requests.status', '=', 'approved');
                                $query->where('claims.status', '=', 'received');
                            }

                            if ($status === 'approved') {
                                $query->where('claim_requests.status', '=', 'approved');
                                $query->where('claims.status', '=', 'approved');
                            }

                            if ($status === 'declined') {
                                $query->where('claim_requests.status', '=', 'approved');
                                $query->where('claims.status', '=', 'declined');
                            }
                    
                        });
                    })
                    ->select(
                        'members.id', 
                        'claim_requests.code',
                        'members.member_id', 
                        'members.name as full_name', 
                        'corporate_divisions.name AS division_name', 
                        DB::raw('
                            CASE 
                                WHEN claim_requests.status = "requested" THEN "requested"
                                WHEN claim_requests.status = "approved" AND claims.status = "approved" THEN "approved"
                                WHEN claim_requests.status = "approved" AND claims.status = "declined" THEN "declined"
                                WHEN claim_requests.status = "approved" AND claims.status = "disbrusmented" THEN "disbrusmented"
                                /*WHEN claim_requests.status = "approved" AND claims.status = "received" THEN "pending"*/
                                WHEN claim_requests.status = "approved" AND claims.status = "received" THEN "reviewed"
                                ELSE "" 
                            END AS status
                        '), 
                        'claim_requests.id AS claim_request_id', 
                        'claim_requests.submission_date',
                        DB::raw('
                            CASE 
                                WHEN service_code = "OP" THEN "Outpatient"
                                WHEN service_code = "IP" THEN "Inpatient"
                                ELSE "" 
                            END AS service_type
                        ')
                        )
                    ->paginate($limit);
        return response()->json(Helper::paginateResources($results));
    }

    public function detail_claim_requests($claimRequestId)
    {

        $status = DB::table('claim_requests')
                    ->leftJoin('claims', 'claim_requests.id', '=', 'claims.claim_request_id')
                    ->leftJoin('members', 'claim_requests.member_id', '=', 'members.id')
                    ->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id')
                    ->leftJoin('corporate_divisions', 'corporate_employees.division_id', '=', 'corporate_divisions.id')
                    ->where('claim_requests.id', '=', $claimRequestId)
                    ->select(
                        'claim_requests.submission_date', 
                        DB::raw('
                            CASE 
                                WHEN claim_requests.status = "requested" THEN "requested"
                                WHEN claim_requests.status = "approved" AND claims.status = "approved" THEN "approved"
                                WHEN claim_requests.status = "approved" AND claims.status = "declined" THEN "declined"
                                WHEN claim_requests.status = "approved" AND claims.status = "disbrusmented" THEN "disbrusmented"
                                /*WHEN claim_requests.status = "approved" AND claims.status = "received" THEN "pending"*/
                                WHEN claim_requests.status = "approved" AND claims.status = "received" THEN "reviewed"
                                ELSE "" 
                            END AS status
                        ')
                    )
                    ->first();
        $results['status'] = $status;
        $timeline = DB::table('claim_logs')
                        ->where('claim_logs.claim_request_id', '=', $claimRequestId)
                        ->select(
                            DB::raw('
                                CASE
                                    WHEN claim_logs.status = "requested" THEN "Request"
                                    WHEN claim_logs.status = "reviewed" THEN "Review"
                                    WHEN claim_logs.status = "approved" THEN "Approval"
                                    WHEN claim_logs.status = "declined" THEN "Decline"
                                    ELSE "-"
                                END AS txt_status
                            '),
                            DB::raw('
                                CASE
                                    WHEN claim_logs.status = "requested" THEN "#159C9C"
                                    WHEN claim_logs.status = "reviewed" THEN "#0C53B7"
                                    WHEN claim_logs.status = "approved" THEN "#229A16"
                                    WHEN claim_logs.status = "declined" THEN "#FF4842"
                                    ELSE "-"
                                END AS txt_status_color
                            '),
                            DB::raw('
                                CASE
                                    WHEN claim_logs.status = "requested" THEN "#00AB5529"
                                    WHEN claim_logs.status = "reviewed" THEN "#1890FF29"
                                    WHEN claim_logs.status = "approved" THEN "#54D62C29"
                                    WHEN claim_logs.status = "declined" THEN "#FF48427A"
                                    ELSE "-"
                                END AS txt_status_backgroundColor
                            '),
                            'claim_logs.date',
                            'claim_logs.description',
                            'claim_logs.status'
                        )
                        ->orderBy('claim_logs.id', 'desc')
                        ->get();
        $results['timeline'] = $timeline;
        $request_files = DB::table('claim_request_files')
                        ->where('claim_request_files.claim_request_id', '=', $claimRequestId)
                        ->select(
                            'claim_request_files.*',
                            DB::raw('(SELECT files.fileable_id FROM files WHERE files.fileable_id = claim_request_files.claim_request_id AND files.type = claim_request_files.type LIMIT 1) AS check_files'),
                        )
                        ->get();
        $results['request_files'] = $request_files;

        return Helper::responseJson($results);
    }

    public function requestFiles(Request $request, $claim_id)
    {

        if ($request->hasFile('fileDiagnosis')) {
            foreach ($request->fileDiagnosis as $file) {
                $pathFile = File::storeFile('claim-diagnosis', $claim_id, $file);
                File::updateOrCreate([
                    'fileable_type'=>'App\Models\ClaimRequest',
                    'fileable_id' => $claim_id,
                    'type' => 'claim-diagnosis',
                    'name' => File::getFileName('claim-diagnosis', $claim_id, $file),
                    'original_name' => $file->getClientOriginalName(),
                    'extension' => $file->getClientOriginalExtension(),
                    'path' => $pathFile,
                    'created_by' => auth()->user()->id,
                    'updated_by' => auth()->user()->id,
                ]);
            }
        }

        if ($request->hasFile('fileKondisis')) {
            foreach ($request->fileKondisis as $file) {
                $pathFile = File::storeFile('claim-kondisi', $claim_id, $file);
                File::updateOrCreate([
                    'fileable_type'=>'App\Models\ClaimRequest',
                    'fileable_id' => $claim_id,
                    'type' => 'claim-kondisi',
                    'name' => File::getFileName('claim-kondisi', $claim_id, $file),
                    'original_name' => $file->getClientOriginalName(),
                    'extension' => $file->getClientOriginalExtension(),
                    'path' => $pathFile,
                    'created_by' => auth()->user()->id,
                    'updated_by' => auth()->user()->id,
                ]);
            }
        }

        if ($request->hasFile('fileResults')) {
            foreach ($request->fileResults as $file) {
                $pathFile = File::storeFile('claim-result', $claim_id, $file);
                File::updateOrCreate([
                    'fileable_type'=>'App\Models\ClaimRequest',
                    'fileable_id' => $claim_id,
                    'type' => 'claim-result',
                    'name' => File::getFileName('claim-result', $claim_id, $file),
                    'original_name' => $file->getClientOriginalName(),
                    'extension' => $file->getClientOriginalExtension(),
                    'path' => $pathFile,
                    'created_by' => auth()->user()->id,
                    'updated_by' => auth()->user()->id,
                ]);
            }
        }

        return Helper::responseJson(data: $request->toArray(), message: 'Invoice Success Uploaded');
    }
}
