<?php

namespace Modules\Internal\Http\Controllers\Api;

use App\Exceptions\ImportRowException;
use App\Helpers\Helper;
use App\Http\Resources\MemberDataTableResource;
use App\Models\Corporate;
use App\Models\CorporateEmployee;
use App\Models\Member;
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Entity\Row;
use Carbon\Carbon;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Illuminate\Console\Command;
use Modules\Internal\Services\MemberEnrollmentService;
use PDF;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\File;
use Spatie\Browsershot\Browsershot;

class CorporateMemberController extends Controller
{
    public function __construct(MemberEnrollmentService $memberEnrollmentService)
    {
        $this->memberEnrollmentService = $memberEnrollmentService;
    }
    /**
     * Display a listing of the resource.
     * @return Renderable
     */
    public function index(Request $request, $corporate_id   )
    {
        $members = Member::query()
            ->joinCorporateEmployees('left')
            ->where('corporate_employees.corporate_id', $corporate_id)
            ->with([
                'employeds',
                'currentPolicy',
                // 'claims',
                'claims' => function ($claim) {
                    // return $claim->whereBetween('requested_at', [now()->startOfYear(), now()->endOfYear()]);
                    // return $claim->used(now()->startOfYear(), now()->endOfYear());
                },
                'currentPlans',
                'currentPlan',
                // 'currentPlan' => function ($currentPlan) use ($service_code){
                //     return $currentPlan->where([
                //         'plans.service_code' => $service_code
                //     ]);
                // },
                'currentPlan.benefits' => function ($benefit) use ($corporate_id){
                    return $benefit->where([
                        'corporate_benefits.active' => 1,
                        'corporate_benefits.corporate_id' => $corporate_id,
                        // 'corporate_benefits.plan_id' => $corporate_id,
                    ]);
                }
            ])
            ->when($request->input('search'), function (Builder $query, $search) {
                $query->where(function (Builder $query) use ($search) {
                    $query->orWhere('members.member_id', 'like', "%" . $search . "%")
                        ->orWhere('members.name', 'like', "%" . $search . "%");
                });
            })
            ->select('members.*')
            ->selectRaw('(SELECT GROUP_CONCAT(files_mcu.original_name SEPARATOR ", ") AS file_mcu_names from files_mcu WHERE  files_mcu.memberid = members.id) AS file_mcu_names')
            ->groupBy('corporate_employees.member_id')
            ->paginate()
            ->appends($request->all());
        return Helper::paginateResources(MemberDataTableResource::collection($members));
    }

    public function activation(Request $request, $member_id)
    {
        $request->validate([
            'active' => 'required',
            'reason' => 'required',
        ]);

        // abort(404);

        $member = Member::findOrFail($member_id);
        $member->active = $request->active;
        $member->reason = $request->reason;

        if ($member->save()) {
            return response()->json([
                'member' => $member,
                'message' => 'Status Updated Successfully'
            ]);
        }
    }

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

    /**
     * Store a newly created resource in storage.
     * @param Request $request
     * @return Renderable
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Show the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function show($id)
    {
        return view('internal::show');
    }

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

    /**
     * Update the specified resource in storage.
     * @param Request $request
     * @param int $id
     * @return Renderable
     */
    public function update(Request $request)
    {
        $member = Member::where('member_id', $request->member_id)->first();

        if ($member) {
            $member->update([
                'birth_date' => $request->birth_date,
                'gender' => $request->gender,
            ]);

            return response()->json([
                'member' => $member,
                'message' => 'Status by member id Updated Successfully'
            ]);
        } else {
            return response()->json([
                'member' => null,
                'message' => 'Gagal update, member tidak ditemukan'
            ]);
        }
    }


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


    public function import(Request $request, $corporate_id)
    {
        // setting tambahan php
        Helper::setCustomPHPIniSettings();

        $request->validate([
            'file' => 'required|file|mimes:xls,xlsx,csv,txt',
        ]);
        $corporate = Corporate::findOrFail($corporate_id)->load('currentPolicy');

        $file_name = now()->getPreciseTimestamp(3) . '-' . $request->file('file')->getClientOriginalName();
        $file = $request->file('file')->storeAs('temp', $file_name);

        $reader = ReaderEntityFactory::createXLSXReader(Storage::path('temp/' . $file_name));
        $reader->open(Storage::path('temp/' . $file_name));

        $writer = WriterEntityFactory::createXLSXWriter();
        $writer->openToFile(Storage::disk('public')->path('temp/result-' . $file_name));

        $headers_map_to_table_fields = $this->memberEnrollmentService->doc_headers_to_field_map;

        // Write Header to File with certain Format from MemberEnrollmentService::$result_doc_headers
        $result_headers = $this->memberEnrollmentService->result_doc_headers;
        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRow($result_headers));
        $writer->addRow($singleRow);

        $imported_member_data = 0;
        $failed_member_data = [];

        foreach ($reader->getSheetIterator() as $sheet) {
            $doc_headers_indexes = [];
            foreach ($sheet->getRowIterator() as $index => $row) {
                if ($index == 1) { // First Row Must be Header
                    foreach ($row->getCells() as $index => $cell) {
                        // Clear up the string and remove all spaces
                        $title = $cell->getValue();
                        $title = preg_replace("/\r|\n/", " ", $title);
                        $title = preg_replace('/\xc2\xa0/', " ", $title);
                        $title = rtrim($title);
                        $title = ltrim($title);
                        $doc_headers_indexes[$index] = $title;
                    }
                } else { // Next Row Should be Data
                    // Collecting Values from table rows and map it to correct fields
                    $new_member_data = [];
                    foreach ($row->getCells() as $header_index => $cell) {
                        if (isset($headers_map_to_table_fields[$doc_headers_indexes[$header_index]])) {
                            $new_member_data[$headers_map_to_table_fields[$doc_headers_indexes[$header_index]]] = $cell->getValue();
                        }
                    }

                    try {
                        $rowResponse = $this->memberEnrollmentService->handleImportRow($corporate, $new_member_data);
                        // Write Success Result to File
                        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($rowResponse));
                        $writer->addRow($singleRow);
                        $imported_member_data++;
                    } catch (ImportRowException $e) {
                        // Write Data Validation Error to File
                        $new_member_data = array_merge($new_member_data, [
                            'ingestion_code' => $e->getCode(),
                            'ingestion_status' => $e->getMessage(),
                        ]);
                        // try {
                            $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($new_member_data));
                            $writer->addRow($singleRow);
                        // } catch (\Exception $e) {
                            $failed_member_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $new_member_data];
                        // }
                    } catch (\Exception $e) {
                        // Write Server Error to File
                        $new_member_data = array_merge($new_member_data, [
                            'ingestion_code' => $e->getCode(),
                            'ingestion_status' => $e->getMessage(),
                        ]);
                        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($new_member_data));
                        $writer->addRow($singleRow);
                        $failed_member_data[] = ['row_number' => $index, 'error' => $e->getMessage()];
                    }
                }
            }

            break; //only read first sheet
        }

        $reader->close();
        $writer->close();
        Storage::delete('temp/' . $file_name);
        // throw(404);
        return [
            'total_success_row' => $imported_member_data,
            'total_failed_row' => count($failed_member_data),
            'failed_row' => $failed_member_data,
            'result_file' => [
                'url' => Storage::disk('public')->url('temp/result-' . $file_name),
                'name' => 'result-' . $file_name,
            ]
        ];
    }


    public function generateLog(Request $request, $member_id)
    {
        $corporate_id = CorporateEmployee::where('member_id', $member_id)->value('corporate_id');
        // $member = Member::findOrFail($member_id)
        //         ->load([
        //             'currentPlan',
        //             'currentPolicy',
        //             'currentPlan.corporateBenefits' => function ($benefit) use ($request) {
        //                 return $benefit->when($request->benefit_ids, function ($q, $ids) {

        //                     $q->whereIn('benefit_id', $ids)
        //                         ->where([
        //                             'corporate_benefits.active' => 1,
        //                             'corporate_benefits.corporate_id' => $corporate_id,
        //                         ]);
        //                 });
        //             },
        //             // 'currentPlan.corporateBenefits.benefit'
        //         ]);
        $member = Member::with([
            'currentPlan',
            'currentPolicy',
            'currentPlan.corporateBenefits' => function ($query) use ($request, $corporate_id) {
                $query->when($request->benefit_ids, function ($q, $ids) use ($corporate_id) {
                    $q->whereIn('benefit_id', $ids)
                        ->where('active', 1)
                        ->where('corporate_id', $corporate_id);
                });
            },
            //  'currentPlan.corporateBenefits.benefit'
        ])->findOrFail($member_id);

        $dateOfAdmission = $request->date_of_admission ? Carbon::parse($request->date_of_admission) : now();

        // return view('pdf.guaranted_leter', compact('member'));
        $pdf = PDF::loadView('pdf.guaranted_leter', compact(['member', 'dateOfAdmission']));
        return $pdf->download('Guaranted Letter - '.$member->full_name.'.pdf');
    }

    public function generateMemberList(Request $request, $corporate_id){
         // Mendapatkan data yang akan diekspor (misalnya, dari database)
        $data = Member::with(['currentPlan', 'currentCorporate', 'division', 'employeds', 'currentPolicy'])
        // ->filter($request->all())
        // ->where('corporate_id', $corporate_id)
        ->whereHas('employeds', function ($employeds) use ($corporate_id) {
            $employeds->where('corporate_id', $corporate_id);
        })->get()->toArray();
        // Membuat penulis entitas Spout
        $writer = WriterEntityFactory::createXLSXWriter();

        // Membuka penulis untuk menulis ke file
        $writer->openToFile(public_path('files/CorporateMembershipList.xlsx'));
        // Menulis header kolom
        $headers_map_to_table_fields = $this->memberEnrollmentService->listing_doc_headers;
        $headerRow = WriterEntityFactory::createRowFromArray($headers_map_to_table_fields);

        $writer->addRow($headerRow);
        // dd('test');
        // Menulis data
        if (!empty($data)) {
            foreach ($data as $item) {
                $rowData = [    $item['record_mode'], // Recode Mode
                                $item['record_type'], // Recode Type
                                $item['payor_id'], // Payor ID
                                $item['member_id'], // Member ID
                                $item['principal_id'], // Mapping ID
                                NULL, // Link Medis Member ID
                                $item['current_corporate']['code'] ?? null, // Corporate ID
                                $item['employeds'][0]['nik'] ?? null, // NIK
                                $item['division']['code'] ?? null, // Devision
                                $item['employeds'][0]['branch_code'] ?? null, // Branch Code
                                $item['bank_info'], // Bank Info
                                $item['language'], // Language
                                null, // Type of Work
                                $item['race'], // Race
                                $item['current_policy']['code'] ?? null, // Policy Number
                                $item['marital_status'], // Marital Status
                                $item['relation_with_principal'], // Relationship
                                str_replace('-', '',$item['members_effective_date']), // Member effective date
                                str_replace('-', '',$item['members_expire_date']), // Member expiry date
                                NULL, // Faskes FKTP  (First Level Provider) or Individual preferred provider
                                NULL, // Faskes FKRTL (Next Level Provider) or Individual group preferred provider
                                $item['bpjs_class'], // The Right Classes Room of  BPJS Participants
                                NULL, // Name of Faskes
                                NULL, // Rule BPJSK
                                NULL, // Internal Use
                                $item['full_name'], // Member Name
                                $item['address1'], // Address1
                                $item['address2'], // Address2
                                $item['address3'], // Address3
                                $item['address4'], // Address4
                                $item['city'], // City
                                NULL, // State
                                $item['postal_code'], // Post Code
                                NULL, // Telephone - Mobile
                                NULL, // Telephone - Res
                                NULL, // Telephone - Office
                                $item['nric'], // NRIC
                                $item['passport_no'], // Passport No
                                $item['passport_country'], // Passport Country
                                $item['email'], // Email
                                $item['identification_code'], // Identification Code
                                $item['birth_date'], // Date of Birth
                                $item['gender_code'], // Sex
                                NULL, // Internal Use
                                $item['current_plan']['code'] ?? null, // Plan-ID
                                NULL, // Employment-Status
                                NULL, // Internal Use
                                NULL, // Internal Use
                                NULL,// Internal Use
                                str_replace('-', '',$item['terminated_date']), // Date Terminated
                                $item['pre_existing'], // Pre Existing
                                $item['bpjs_id'], // BPJS ID
                                $item['endorsement_date'], // Endorsement Date
                                $item['remarks'], // Remarks
                                NULL, // Internal Use
                                NULL,// Member Since
                                NULL,// Internal Use
                                $item['policy_in_force'], // Policy Inforce
                                NULL, // Member Suspended
                                str_replace('-', '',$item['activation_date']), // Activation Date
                                NULL, // Internal Use
                                $item['start_no_claim'], // StartNoClaim
                                $item['end_no_claim'], // EndNoClaim
                                NULL, // Option Mode
                            ];
                $row = WriterEntityFactory::createRowFromArray($rowData);
                $writer->addRow($row);
            }
        }

        // Menutup penulis
        $writer->close();
        // dd('test');
        // Mengembalikan response untuk mengunduh file
        $filePath = public_path('files/CorporateMembershipList.xlsx');
        // dd($filePath);
        // Mengembalikan response untuk mengunduh file
        return Helper::responseJson([
            'file_name' => "Corporate Plan & Benefit List " . date('Y-m-d h:i:s'),
            "file_url" => url('files/CorporateMembershipList.xlsx')
        ]);
    }

    public function sendAllECard(Request $request, $corporate_id){
        $members = Member::with([
            'currentPlan',
            'currentPolicy',
            'currentCorporate',
            //  'currentPlan.corporateBenefits.benefit'
        ])->whereHas('currentCorporate', function ($query) use ($corporate_id) {
            $query->where('corporate_id', $corporate_id);
        })->get();
        $data = [];
        $countSuccesSend = 0;
        foreach($members as $member){
            // Simpan file PDF ke direktori yang diinginkan
            $pdfPath = storage_path('app/pdf/ecards/E-card-' . $member->name. '.pdf');
            // Cek apakah file sudah ada
            if (!File::exists($pdfPath)) {
                $pdf = PDF::loadView('pdf.ecard', compact('member'))->setPaper('A5', 'portrait');
                $pdf->save($pdfPath);
            }

            $dataEmail = [
                // 'email' => $member->email,
                'email' => 'tbfajri',
                'name' => $member->name,
                'subject' => 'Digital E Card '. $member->name,
                'body' =>  '<h1>Hi ' . $member->name . '</h1> <br> ini adalah uji coba kirim e-card'  ,
                'attach' =>  $pdfPath,
            ];
            $sendEmail = Helper::sendEmailattachData($dataEmail);

            if ($sendEmail === true){
                $countSuccesSend ++;

                File::delete($pdfPath);
            } else {
                $dataFaild = [
                    'email' => $member->email,
                    'name' => $member->name,
                    'message' => $sendEmail
                ];
                array_push($data, $dataFaild);
            }
        }
        $response = [
            'data_fail_send' => count($data),
            'message' => $data,
            'data_succes_send' => $countSuccesSend,
        ];

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

    public function viewECard(Request $request, $member_id){
        $member = Member::with([
            'currentPlan',
            'currentPolicy',
            'currentCorporate',
            'currentCorporate.files',
            //  'currentPlan.corporateBenefits.benefit'
        ])->find($member_id);

        if ($member->currentCorporate->id == 5){ // Vale
            $pdf = PDF::loadView('pdf.ecard', compact('member'))->setPaper('A5', 'portrait');
        } else {
            $pdf = PDF::loadView('pdf.ecard-lms', compact('member'))->setPaper('A5', 'portrait');
        }
        return $pdf->download('Ecard - '.$member->full_name.'.pdf');

    }

}
