<?php

namespace Modules\Internal\Services;

use App\Exceptions\ImportRowException;
use App\Models\Member;
use App\Models\Benefit;
use App\Models\RequestLog;
use App\Models\RequestLogBenefit;
use App\Models\Corporate;
use App\Models\Service;
use App\Models\Plan;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Entity\Row;
use Carbon\Carbon;
use DateTime;
use DB;

class RequestLogService
{
    private static $code_prefix = 'LOG';

    public $doc_headers_to_field_map = [
        "Record Mode" => "record_mode",
        "Date Addmission" => "submission_date",
        "Date Discharge" => "discharge_date",
        "Member ID Peserta" => "member_id",
        "Service" => "service",
        "Type of Member" => "type_of_member",
        "Provider Code" => "organization_id",
        "End Of Claim Numbers" => "code",
        "Diagnosis" => "diagnosis",
        "Tgl Billing dari RS" => "approved_final_log_at",
        "Total Billing" => "total_billing",
        "Benefit Item" => "benefit_id",
        "Amount Approval" => "amount_approval",
        "Amount Not Approval" => "amount_not_approval",
        "Total COB" => "total_cob",
        "Keterangan IGL" => "keterangan",
        "Catatan FGL" => "catatan",
        "QC 1" => "status_final_log",
        "Ingestion Code" => "ingestion_code", // TODO I think this should not be here because if user uploading result then ingestion code and status will be filled
        "Ingestion Status" => "ingestion_status",

    ];

    public $field_to_doc_headers_map = [
        "record_mode" => "Record Mode",
        "submission_date" => "Date Addmission",
        "discharge_date" => "Date Discharge",
        "member_id" => "Member ID Peserta",
        "service" => "Service",
        "type_of_member" => "Type of Member",
        "organization_id" => "Provider Code",
        "code" => "End Of Claim Numbers",
        "diagnosis" => "Diagnosis",
        "approved_final_log_at" => "Tgl Billing dari RS",
        "total_billing" => "Total Billing",
        "benefit_id" => "Benefit Item",
        "amount_approval" => "Amount Approval",
        "amount_not_approval" => "Amount Not Approval",
        "total_cob" => "Total COB",
        "keterangan" => "Keterangan IGL",
        "catatan" => "Catatan FGL",
        "status_final_log" => "QC 1"  ,
        "ingestion_code" => "Ingestion Code",
        "ingestion_status" => "Ingestion Status",
    ];

    public $result_doc_headers = [
        "Record Mode",
        "Date Addmission",
        "Date Discharge",
        "Member ID Peserta",
        "Service",
        "Type of Member",
        "Provider Code",
        "End Of Claim Numbers",
        "Diagnosis",
        "Tgl Billing dari RS",
        "Total Billing",
        "Benefit Item",
        "Amount Approval",
        "Amount Not Approval",
        "Total COB",
        "Keterangan IGL",
        "Catatan FGL",
        "QC 1",
        "Ingestion Code",
        "Ingestion Status",
    ];

    public $listing_doc_headers = [
        "Record Mode",
        "Date Addmission",
        "Date Discharge",
        "Member ID Peserta",
        "Service",
        "Type of Member",
        "Provider Code",
        "End Of Claim Numbers",
        "Diagnosis",
        "Tgl Billing dari RS",
        "Total Billing",
        "Benefit Item",
        "Amount Approval",
        "Amount Not Approval",
        "Total COB",
        "Keterangan IGL",
        "Catatan FGL",
        "QC 1",
        "Ingestion Code",
        "Ingestion Status",
    ];

    public function dateParser($date_from_row) {

        if ($date_from_row instanceof DateTime) {
            return $date_from_row->format('Y-m-d');
        } else if ($date_from_row != null) {
            if (strtotime($date_from_row)){
                return date('Y-m-d', strtotime($date_from_row));
            } else {
                return null;
            }
        } else {
            return null;
        }

    }

    public function dateParserCode($date_from_row) {

        if ($date_from_row instanceof DateTime) {
            return $date_from_row->format('ymd');
        } else if ($date_from_row != null) {
            return date('ymd', strtotime($date_from_row));
        } else {
            return null;
        }

    }

    public function handleImportRow($row)
    {
        try {
            // Memulai transaksi
            DB::beginTransaction();
            $member = Member::with('currentCorporate')->where(['member_id' => $row['member_id']])->first();

                    // // Validate If Exist Member
            if (!$member) {
                throw new ImportRowException(__('MEMBER_NOT_FOUND', [
                    'member_id' => $row['member_id'],
                ]), 0, null, $row);
            }

            $dateSubmission = $this->dateParser($row['submission_date']);
            if (!$dateSubmission){
                throw new ImportRowException(__('Format Date Invalid'), 0, null, $row);
            }

            if (!$row['organization_id']){
                throw new ImportRowException(__('Provider Required'), 0, null, $row);
            }

            // Membuat singkatan dari nama rumah sakit
            // $singkatan = "";
            // $words = explode(' ', $row['organization_id']);

            // foreach ($words as $word) {
            //     $singkatan .= strtoupper(substr($word, 0, 1));
            // }

            // Membuat kode organisasi
            // $kodeOrganisasi = "ORG000" . $singkatan;
            // Insert data ke tabel organizations
            $organization = DB::table('organizations')->where('code', $row['organization_id'])->first();
           
            if (!$organization){
                throw new ImportRowException(__('Provider Not Found'), 0, null, $row);
            }

            // if ($organization) {
            $organization_id = $organization->id;
            // } else {
            //     $organization_id = DB::table('organizations')
            //         ->insertGetId([
            //             'name' => $row['organization_id'],
            //             'code' => $kodeOrganisasi,
            //             'type' => 'hospital',
            //             'created_at' => now(),
            //             'created_by' => auth()->user()->id
            //         ]);
            // }

            $data = [
              'source' => 'H',
            //   'provideCode'  => $kodeOrganisasi ,
              'provideCode'  => $organization->code ,
              'date' => $this->dateParserCode($row['submission_date']),
              'policy' => $member->currentPolicy->code,
              'member_code' => $row['member_id']
            ];

            $code = $this->makeCode($row['code'], $data);
            if ($row['status_final_log'] == 'Y'){
                $status = 'approved';
            } else if ($row['status_final_log'] == 'C'){
                $status = 'canceled';
            } else {
                $status = 'requested';
            }
            
            $service = Service::where('name', $row['service'])->first();
            if ($service){
                $serviceCode = $service->code;
            } else {
                $serviceCode = 'Unk';
            }

            $benefit = Benefit::where('code', $row['benefit_id'])->first();

            if (!$benefit){
                $statusFinalLog = 'requested';
                $final_log = 0;
            } else {
                $statusFinalLog = $status;
                $final_log = 1;
            }

            if ($row['diagnosis']){
                $data = [
                    'code' => $code,
                    'member_id' => $member->id,
                    'submission_date' => $row['submission_date'],
                    'discharge_date' => $row['discharge_date'],
                    'payment_type' => 'cashless',
                    'status' => $status,
                    'status_final_log' => $statusFinalLog,
                    'final_log' =>$final_log,
                    'import_system' =>TRUE,
                    'catatan' => $row['catatan'],
                    'type_of_member' => $row['type_of_member'],
                    'total_cob' => $row['total_cob'],
                    'keterangan' => $row['keterangan'],
                    'policy_id' => $member->currentPolicy->id ?? null,
                    'organization_id' => $organization_id,
                    'diagnosis' => $row['diagnosis'],
                    'service_code' => $serviceCode,
                    'approved_final_log_at' => $row['approved_final_log_at'],
                ];
            } else {
                $data = [
                    'code' => $code,
                    'member_id' => $member->id,
                    'submission_date' => $row['submission_date'],
                    'discharge_date' => $row['discharge_date'],
                    'payment_type' => 'cashless',
                    'status' => $status,
                    'status_final_log' => $statusFinalLog,
                    'final_log' =>$final_log,
                    'import_system' =>TRUE,
                    'catatan' => $row['catatan'],
                    'type_of_member' => $row['type_of_member'],
                    'total_cob' => $row['total_cob'],
                    'diagnosis' => $row['diagnosis'],
                    'keterangan' => $row['keterangan'],
                    'policy_id' => $member->currentPolicy->id ?? null,
                    'organization_id' => $organization_id,
                    'service_code' => $serviceCode,
                    'approved_final_log_at' => $row['approved_final_log_at'],
                ];
            }

            if ($row['record_mode'] == 1){
                $requestLog = RequestLog::updateOrCreate(["code" => $code], $data);
            } else if ($row['record_mode'] == 2) {
                $requestLog = RequestLog::updateOrCreate(
                    [
                        'member_id' => $member->id,
                        'submission_date' => $row['submission_date'],
                        'organization_id' => $organization_id,
                    ],
                    $data
                );
            }

            if ($benefit) { // jika tidak ada benefit nya maka belum ngisi benefit nya
                // Delete item 
                if ($row['total_billing']){
                    RequestLogBenefit::where('request_log_id', '=', $requestLog->id)->delete();
                }
                // Insert Item
                RequestLogBenefit::create(
                [
                    'request_log_id' => $requestLog->id,
                    'benefit_id' => $benefit->id,
                    // 'amount_incurred' => ($row['amount_approval'] ? $row['amount_approval'] : 0) + ($row['amount_not_approval'] ? $row['amount_not_approval'] : 0) ,
                    'amount_incurred' => $row['total_billing'] ,
                    'amount_approved' => $row['amount_approval'] ?? 0,
                    'amount_not_approved' => $row['amount_not_approval'] ?? 0,
                    'excess_paid' => $row['amount_not_approval'] ?? 0,
                    'created_by' => auth()->user()->id,

                ]);
            }
            // Commit transaksi
            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
            throw new ImportRowException($e->getMessage(), $e->getCode(), $e, $row);
        }

        $row['ingestion_code'] = "200";
        $row['ingestion_status'] = "SUCCESS";

        return $row;
    }

    // This returning row with format or order as it is
    public function makeResultRow($row_data)
    {
        $cells = [];
        foreach ($row_data as $cellValue) {
            $cells[] = WriterEntityFactory::createCell($cellValue);
        }

        return $cells;
    }

    // This returning row with format or order following $result_doc_headers
    public function makeResultRowWithResultFormat($row_data)
    {
        $cells = [];
        foreach ($this->result_doc_headers as $header) {
            $value = $row_data[$this->doc_headers_to_field_map[$header]] ?? null;
            if (is_string($value)) {
                $cells[] = WriterEntityFactory::createCell($value);
            }
            else if ($value instanceof DateTime) {
                $cells[] = WriterEntityFactory::createCell(Carbon::parse($value)->format('Ymd'));
            }
            else {
                $cells[] = WriterEntityFactory::createCell($value);
            }
        }

        return $cells;
    }


    public function makeCode($next_number, $data)
    {
        $sparator = '.';
        // Pastikan $next_number adalah integer positif
        $next_number = max(1, (int) $next_number);
        // Menghasilkan kode dengan format yang diinginkan
        return self::$code_prefix . $sparator. $data['source'] . $sparator. $data['provideCode'] . $sparator. $data['date'] . $sparator . $data['policy'] . $sparator. $data['member_code'] . $sparator. str_pad($next_number, 6, '0', STR_PAD_LEFT);
    }

}
