<?php

namespace App;

use App\Models\OrdersInvoices;

class Helper
{
    const EARTH_RADIUS_M = 6371000;
    const EARTH_RADIUS_KM = 6371;
    const EARTH_RADIUS_MILES = 3959; // 3958.756 || 3959 || 3963
	const TIMEFIX = 25200;

    /**
     * Calculates the great-circle distance between two points, with
     * the Haversine formula.
     * @param float $latitudeFrom Latitude of start point in [deg decimal]
     * @param float $longitudeFrom Longitude of start point in [deg decimal]
     * @param float $latitudeTo Latitude of target point in [deg decimal]
     * @param float $longitudeTo Longitude of target point in [deg decimal]
     * @param float $earthRadius Mean earth radius in [m]
     * @return float Distance between points in [m] (same as earthRadius)
     * reference: https://stackoverflow.com/questions/14750275/haversine-formula-with-php
     * tolak ukur: tarik garis lurus
     * miles: 3958.756 || 3959
     * km: 6371
     * meters: 6371000
     * more accurate using km/meters than miles i think
     */
    public static function haversineGreatCircleDistance(
        $latitudeFrom,
        $longitudeFrom,
        $latitudeTo,
        $longitudeTo,
        $earthRadius = self::EARTH_RADIUS_M
    ) {
        // convert from degrees to radians
        $latFrom = deg2rad($latitudeFrom);
        $lonFrom = deg2rad($longitudeFrom);
        $latTo = deg2rad($latitudeTo);
        $lonTo = deg2rad($longitudeTo);

        $latDelta = $latTo - $latFrom;
        $lonDelta = $lonTo - $lonFrom;

        $angle =
            2 *
            asin(sqrt(pow(sin($latDelta / 2), 2) + cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
        $distance = $angle * $earthRadius;

        return $distance;
    }

    public static function arccosineGreatCircleDistance(
        $latitudeFrom,
        $longitudeFrom,
        $latitudeTo,
        $longitudeTo,
        $earthRadius = 6371000
    ) {
        return $earthRadius *
            acos(
                cos(deg2rad($latitudeFrom)) *
                    cos(deg2rad($latitudeTo)) *
                    cos(deg2rad($longitudeTo) - deg2rad($longitudeFrom)) +
                    sin(deg2rad($latitudeFrom)) * sin(deg2rad($latitudeTo))
            );
    }

    public static function createPayload($array)
    {
        $string = "";

        foreach ($array as $key => $val) {
            if (is_array($val)) {
                self::createPayload($val);
                continue;
            }
            $string .= $key . "=" . $val . "&";
        }

        return $string;
    }

    static function req_post($url, $headers, $payload)
    {
        $ch = curl_init();

        $options = [
            CURLOPT_URL => $url,
            CURLOPT_HEADER => false,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => $payload,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_RETURNTRANSFER => true,
            // CURLOPT_FAILONERROR => true,
        ];
        curl_setopt_array($ch, $options);

        $resp = curl_exec($ch);

        if (curl_errno($ch)) {
            $result = [
                "type" => "error",
                "message" => curl_error($ch),
            ];
            return $result;
        } else {
            $result = ["type" => "success"];
            try {
                $data = json_decode($resp);

                if (json_last_error() == JSON_ERROR_NONE) {
                    $result["data"] = $data;
                } else {
                    $result["data"] = $resp;
                }

                return $result;
            } catch (\Exception $e) {
                $result["data"] = $resp;
                return $result;
            }
        }
    }

    static function req_get($url, $headers)
    {
        $ch = curl_init();

        $options = [
            CURLOPT_URL => $url,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_RETURNTRANSFER => true,
            // CURLOPT_FAILONERROR => true,
        ];
        curl_setopt_array($ch, $options);

        $resp = curl_exec($ch);

        if (curl_errno($ch)) {
            $result = [
                "type" => "error",
                "message" => curl_error($ch),
            ];
            return $result;
        } else {
            $result = ["type" => "success"];
            try {
                $data = json_decode($resp);

                if (json_last_error() == JSON_ERROR_NONE) {
                    $result["data"] = $data;
                } else {
                    $result["data"] = $resp;
                }

                return $result;
            } catch (\Exception $e) {
                $result["data"] = $resp;
                return $result;
            }
        }
    }

    public static function listBloods()
    {
        return [
            [
                "id" => "A",
                "name" => "A",
            ],
            [
                "id" => "A+",
                "name" => "A+",
            ],
            [
                "id" => "B",
                "name" => "B",
            ],
            [
                "id" => "B+",
                "name" => "B+",
            ],
            [
                "id" => "O",
                "name" => "O",
            ],
            [
                "id" => "O+",
                "name" => "O+",
            ],
            [
                "id" => "AB",
                "name" => "AB",
            ],
            [
                "id" => "AB+",
                "name" => "AB+",
            ],
        ];
    }

    public static function countAge($date_ymd)
    {
        $then = date("Ymd", strtotime($date_ymd));
        $diff = date("Ymd") - $then;
        return (int) substr($diff, 0, -4);
    }

    public static function terbilang($nilai)
    {
        function penyebut($nilai)
        {
            $nilai = abs($nilai);
            $huruf = [
                "",
                "satu",
                "dua",
                "tiga",
                "empat",
                "lima",
                "enam",
                "tujuh",
                "delapan",
                "sembilan",
                "sepuluh",
                "sebelas",
            ];
            $temp = "";
            if ($nilai < 12) {
                $temp = " " . $huruf[$nilai];
            } elseif ($nilai < 20) {
                $temp = penyebut($nilai - 10) . " belas";
            } elseif ($nilai < 100) {
                $temp = penyebut($nilai / 10) . " puluh" . penyebut($nilai % 10);
            } elseif ($nilai < 200) {
                $temp = " seratus" . penyebut($nilai - 100);
            } elseif ($nilai < 1000) {
                $temp = penyebut($nilai / 100) . " ratus" . penyebut($nilai % 100);
            } elseif ($nilai < 2000) {
                $temp = " seribu" . penyebut($nilai - 1000);
            } elseif ($nilai < 1000000) {
                $temp = penyebut($nilai / 1000) . " ribu" . penyebut($nilai % 1000);
            } elseif ($nilai < 1000000000) {
                $temp = penyebut($nilai / 1000000) . " juta" . penyebut($nilai % 1000000);
            } elseif ($nilai < 1000000000000) {
                $temp = penyebut($nilai / 1000000000) . " milyar" . penyebut(fmod($nilai, 1000000000));
            } elseif ($nilai < 1000000000000000) {
                $temp = penyebut($nilai / 1000000000000) . " trilyun" . penyebut(fmod($nilai, 1000000000000));
            }
            return $temp;
        }

        if ($nilai < 0) {
            $hasil = "minus " . trim(penyebut($nilai));
        } else {
            $hasil = trim(penyebut($nilai));
        }
        return $hasil;
    }

    public static function lastDigitYear()
    {
        // 2023 => 3
        return substr(date("Y"), -1);
    }

    public static function weekNumOfYear()
    {
        // 27 jul 2022 => 30
        return date("W");
    }

    public static function dayOfWeek()
    {
        // monday => 01, sunday => 07
        return date("N");
    }

    public static function gnrtOrdCode($type)
    {
        $ord_code = "";
        $ord_code .= $type;
        $ord_code .= Helper::lastDigitYear() . Helper::weekNumOfYear() . Helper::dayOfWeek();
        // above before running number
        $likeCode = \App\Models\Orders::getOrderLikeCode($ord_code);
        // below after running number
        if (count($likeCode) < 1 || $likeCode === false) {
            $ord_code .= "001";
        } else {
            if ($likeCode[0]->total < 1) {
                $ord_code .= "001";
            } else {
                $ord_code .= str_pad($likeCode[0]->total + 1, 3, "0", STR_PAD_LEFT);
            }
        }
        return $ord_code;
    }

    public static function gnrtInvcCode($ord_code)
    {
        $invc_code = "";
        $type = substr($ord_code, 0, 1);
        $invc_code .= Helper::lastDigitYear() . Helper::weekNumOfYear() . $type;
        $first_invc_code = $invc_code;
        // above before running number
        $likeCode = \App\Models\OrdersInvoices::getLikeCode($invc_code);
        // below after running number
        if (count($likeCode) < 1 || $likeCode === false) {
            $invc_code .= "001";
        } else {
            if ($likeCode[0]->total < 1) {
                $invc_code .= "001";
            } else {
                $invc_code .= str_pad($likeCode[0]->total + 1, 3, "0", STR_PAD_LEFT);
                $checkCode = OrdersInvoices::getByCode($invc_code);
                if (count($checkCode) > 0) {
                    $invc_code = $first_invc_code;
                    $lastRN = OrdersInvoices::getLikeCodeLastRunningNumber($invc_code);
                    $newRN = (int) substr($lastRN[0]->code, -3);
                    $invc_code .= str_pad($newRN + 1, 3, "0", STR_PAD_LEFT);
                }
            }
        }
        return $invc_code;
    }

    public static function viewBillFncIsEnableBtn($prev_termin, $curr_termin)
    {
        if ($curr_termin->termin_ddln_type === \App\Models\OrdersTermins::DDLN_TERMIN_TYPE_ORD_FINISH) {
            if ($curr_termin->drop_chk_at === 0) {
                // Menunggu Pengantaran Selesai
                // return 0;
                if ($prev_termin->termin_is_paid === \App\Models\OrdersTermins::IS_PAID_YES) {
                    // Termin sebelumnya selesai dan show btn invoice
                    return 1;
                } else {
                    // Menunggu Pengantaran Selesai
                    return 0;
                }
            } else {
                if ($curr_termin->termin_is_paid === \App\Models\OrdersTermins::IS_PAID_YES) {
                    // invoice close
                    return 4;
                } else {
                    if (
                        $prev_termin !== 0 &&
                        $prev_termin->termin_is_paid === \App\Models\OrdersTermins::IS_PAID_NO
                    ) {
                        // Termin sebelumnya belum terkonfirmasi selesai
                        return 3;
                    }
                    // Pengantaran Selesai pada and show btn invoice
                    return 2;
                }
            }
        } else {
            if ($curr_termin->termin_is_paid === \App\Models\OrdersTermins::IS_PAID_YES) {
                // invoice close
                return 4;
            } else {
                if (
                    $prev_termin !== 0 &&
                    $prev_termin->termin_is_paid === \App\Models\OrdersTermins::IS_PAID_NO
                ) {
                    // Termin sebelumnya belum terkonfirmasi selesai
                    return 3;
                }
                // show btn invoice
                return 1;
            }
        }
    }

    public static function changeIpToDomain($fullurl)
    {
        $replace = $fullurl;
        if (!strpos($fullurl, env("ORI_IP")) === false) {
            $replace = str_replace(env("ORI_IP"), env("ORI_DOMAIN"), $replace);
        }
        return $replace;
    }
}
