<?php

namespace Modules\Internal\Http\Controllers\Api;

use App\Exceptions\ImportRowException;
use App\Helpers\Helper;
use App\Models\Corporate;
use App\Models\CorporateService;
use App\Models\Exclusion;
use App\Models\ExclusionImport;
use App\Models\Icd;
use App\Models\ImportLog;
use App\Services\ImportService;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Modules\Internal\Services\ExclusionService;
use Modules\Internal\Transformers\DiagnosisExclusionResource;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

class DiagnosisExclusionController extends Controller
{
    /**
     * Display a listing of the resource.
     * @return Renderable
     */
    public function index(Request $request, $corporate_id)
    {
        $exclusions = Exclusion::query()
            ->where('corporate_id', $corporate_id)
            ->where('type', 'diagnosis')
            ->where('deleted_at', null)
            ->with(['exclusionable', 'rules'])
            ->filter($request->toArray())
            ->paginate();
        // return $exclusions;
        return Helper::paginateResources(DiagnosisExclusionResource::collection($exclusions));
    }

    public function listDiagnosis(Request $request, $corporate_id){
        $exclusion = Exclusion::query()
            ->where('corporate_id', $corporate_id)
            ->where('type', 'diagnosis')
            ->where('deleted_at', null)
            // ->with(['rules'])
            ->get('exclusionable_id')->toArray();

        $icd = Icd::query()
                ->whereNotIn('id', $exclusion)
                ->limit(100)
                ->get()
                ->toArray();
        return Helper::responseJson($icd);
    }

    /**
     * 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, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Renderable
     */
    public function destroy($id)
    {
        $exclusion = Exclusion::findOrFail($id);

        $exclusion->rules()->delete();
        $exclusion->delete();
        return response()->json([
            'message' => 'Exclusion deleted successfully'
        ]);
    }

    public function import(Request $request, $corporate_id)
    {
        $request->validate([
            'file' => 'required|file|mimes:xls,xlsx,csv,txt',
        ]);
        // dd($request->toArray());
        $file_name = now()->getPreciseTimestamp(3) . '-' . $request->file('file')->getClientOriginalName();
        $file = $request->file('file')->storeAs('temp', $file_name);
        $corporate = Corporate::findOrFail($corporate_id);

        // $importLog = $corporate->importLogs()->create([
        //     'type' => 'diagnosis-exclusions',
        //     'file_path' => $file,
        //     'status' => 'pending',
        //     'progress' => 0,
        // ]);

        $import = new ImportService();
        $import->read(Storage::path('temp/' . $file_name));
        $import->write(Storage::disk('public')->path('temp/result-' . $file_name), 'xsls');

        foreach ($import->sheetsIterator() as $sheetIndex => $sheet) {
            $doc_headers_indexes = [];
            foreach ($sheet->getRowIterator() as $index => $row) {
                if ($index == 1) { // First Row Must be Header
                    foreach ($row->getCells() as $index => $cell) {
                        $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;
                    }

                    // Write Header to File
                    $result_headers = array_merge($doc_headers_indexes, ['Ingest Code', 'Ingest Note']);
                    $import->addArrayToRow($result_headers);

                    // TODO Validate if First Row not Header
                } else { // Next Row Should be Data
                    $row_data = [];
                    $row_map = [
                        0 => 'code',
                        1 => 'description',
                        2 => 'ip_exclusion',
                        3 => 'op_exclusion',
                        4 => 'de_exclusion',
                        5 => 'ma_exclusion',
                        6 => 'sp_exclusion',
                        7 => 'pre_exist_exclusion',
                        8 => 'op_de_exclusion',
                        9 => 'keterangan',
                        10 => 'maternity_waiting'
                    ];

                    foreach ($row->getCells() as $header_index => $cell) {
                        if (isset($row_map[$header_index])) {
                            $value = $cell->getValue();
                            $value = preg_replace("/\r|\n/", " ", $value);
                            $value = preg_replace('/\xc2\xa0/', " ", $value);
                            $value = rtrim($value);
                            $value = ltrim($value);
                            $row_data[$row_map[$header_index]] = $cell->getValue();
                        }
                    }

                    try { // Process the Row Data
                        if (
                            // empty($row_data['code']) &&
                            // empty($row_data['description']) &&
                            empty($row_data['ip_exclusion']) &&
                            empty($row_data['op_exclusion']) &&
                            empty($row_data['de_exclusion']) &&
                            empty($row_data['ma_exclusion']) &&
                            empty($row_data['sp_exclusion']) &&
                            empty($row_data['pre_exis_exclusion']) &&
                            empty($row_data['op_de_exclusion']) &&
                            empty($row_data['maternity_waiting'])
                        ) {
                            continue;
                        }

                        // Save the Row
                        $exclusionService = new ExclusionService();
                        $exclusionService->handleDiagnosisExclusionRow($corporate, $row_data);

                        // Write Success Result to File
                        $import->addArrayToRow(array_merge($row_data, [
                            'Ingest Code' => 200,
                            'Ingest Note' => 'Success',
                        ]), $sheet->getName());
                    } catch (ImportRowException $e) {
                        // Write Data Validation Error to File
                        $import->addArrayToRow(array_merge($row_data, [
                            'Ingest Code' => $e->getCode(),
                            'Ingest Note' => $e->getMessage(),
                        ]), $sheet->getName());
                    } catch (\Exception $e) {
                        throw new \Exception($e);
                        // Write Server Error to File
                        $import->addArrayToRow(array_merge($row_data, [
                            'Ingest Code' => 500,
                            'Ingest Note' => env('APP_DEBUG') ? $e->getMessage() : 'Server Error',
                        ]), $sheet->getName());
                    }
                }
            }

            break; // Only Read First Row
        }
        $import->reader->close();
        Storage::delete('temp/' . $file_name);
        $import->writer->close();
        ExclusionImport::updateOrCreate([
            'corporate_id' => $corporate_id
        ],[
            'file_name' => $file_name,
            'file_path' => 'temp/result-' . $file_name,

        ]);
        return [
            // 'total_successed_row' => $imported_plan_data,
            // 'total_failed_row' => count($failed_plan_data),
            // 'failed_row' => $failed_plan_data,
            'result_file' => [
                'url' => Storage::disk('public')->url('temp/result-' . $file_name),
                'name' => 'result-' . $file_name,
            ]
        ];
    }

    public function storeExclusion(Request $request, $corporate_id)
    {
        $exclusion = Exclusion::where('corporate_id', $corporate_id)
            ->where('id', $request->icd_id)
            ->where('type', 'diagnosis')
            ->first();


        if ($request->type == "one_row") {
            $data = $request->one_row;

            foreach ($data['msc'] as $key => $value) {
                if ($key == 'm' && $value == "1") {
                    $msc[] = $key;
                } elseif ($key == 's' && $value == "1") {
                    $msc[] = $key;
                } elseif ($key == 'c' && $value == "1") {
                    $msc[] = $key;
                } else {
                    $msc[] = "";
                }
            }

            $msc = implode(",", $msc);
            $msc = trim($msc, ",");
            $msc = str_replace(",,", ",", $msc);

            foreach ($data['gender'] as $key => $value) {
                if ($key == 'male' && $value == "1") {
                    $gender[] = $key;
                } elseif ($key == 'female' && $value == "1") {
                    $gender[] = $key;
                } else {
                    $gender[] = "";
                }
            }

            $gender = implode(",", $gender);
            $gender = trim($gender, ",");

            $exclusion->rules()->corporate_id = $corporate_id;

            $exclusion->rules()->updateOrCreate([
                'exclusion_id' => $exclusion->id,
                'name' => 'msc',
            ], [
                'name' => 'msc',
                'values' => $msc ?? '',
            ]);

            $exclusion->rules()->updateOrCreate([
                'exclusion_id' => $exclusion->id,
                'name' => 'gender',
            ], [
                'name' => 'gender',
                'values' => $gender ?? '',
            ]);

            $exclusion->rules()->updateOrCreate([
                'exclusion_id' => $exclusion->id,
                'name' => 'min_age',
            ], [
                'name' => 'min_age',
                'values' => $data['min_age'] ?? '',
            ]);

            $exclusion->rules()->updateOrCreate([
                'exclusion_id' => $exclusion->id,
                'name' => 'max_age',
            ], [
                'name' => 'max_age',
                'values' => $data['max_age'] ?? '',
            ]);

            $exclusion->rules()->updateOrCreate([
                'exclusion_id' => $exclusion->id,
                'name' => 'plan',
            ], [
                'name' => 'plan',
                'values' => $data['plan'] ?? '',
            ]);
        }

        $exclusions = Exclusion::query()
            ->where('corporate_id', $corporate_id)
            ->where('type', 'diagnosis')
            ->with(['exclusionable', 'rules'])
            ->filter($request->toArray())
            ->paginate();
        // return $exclusions;
        return Helper::paginateResources(DiagnosisExclusionResource::collection($exclusions));
    }

    /**
     * Bagaskoro BSD 20-10-2023
     *
     * Fungsi untuk get detil exclusion
     */
    public function detilExclusion(Request $request, $corporate_id, $id_exclusion)
    {
        $corporate = Corporate::query()
            ->with(['currentPolicy', 'plans'])
            ->withCount('corporatePlans')
            ->withCount('employees')
            ->findOrFail($corporate_id);

        $plans  = $corporate['plans']->map(function ($plan) {
                    return $plan['code'];
                });

        $exclusions = Exclusion::query()
            ->where('id', $id_exclusion)
            ->where('type', 'diagnosis')
            ->where('deleted_at', null)
            ->with(['rules'])
            ->get();

        $exclusion  = DiagnosisExclusionResource::collection($exclusions);

        return response()->json([
            'error'    => false,
            'messages' => "success",
            'data'     => [
                'exclusion' => empty($exclusion) ? [] : $exclusion[0],
                'plans'     => $plans,
            ]
        ],200);
    }

    /**
     * Bagaskoro BSD 19-10-2023
     *
     * Fungsi untuk update status active
     */
    protected function messages()
    {
        return [
            'required'      => ':attribute harus diisi',
            'integer'       => ':attribute harus angka',
            'unique'        => ':attribute (:input) sudah ada',
            'max'           => ':attribute maximal :max karakter',
            'exists'        => ':attribute (:input) tidak ditemukan',
            'digits_between'=> ':attribute maximal :max digit minimal :min digit'
        ];
    }

    public function updateActivation(Request $request)
    {
        // validation rule
        $validator = Validator::make($request->all(),[
            'id'     => 'required|exists:exclusions',
            'active' => 'required|in:0,1',
        ],$this->messages());

        // validation error
        if ($validator->fails()) {
            return response()->json([
                'error'    => true,
                'messages' => $validator->getMessageBag()
            ],400);
        }

        Exclusion::where('id', $request->id)->update([
            'active' => $request->active == 1 ? 0 : 1,
            'reason' => $request->reason
        ]);

        return response()->json([
            'error'    => false,
            'messages' => "status berhasil diupdate",
            'data'     => []
        ],200);
    }
}
