<?php

use Intervention\Image\Image;

abstract class Nalog
{
    public string $uplatilac = '';
    public string $svrha = '';
    public string $primalac = '';
    public string $telefon = '';
    public string $sifra = '';
    public string $valuta = 'RSD';
    public string $iznos = '';
    public string $racun = '';
    public string $model = '';
    public string $poziv_na_broj = '';

    public function uplatilac(string $uplatilac): self
    {
        $this->uplatilac = $uplatilac;
        return $this;
    }

    public function getUplatilac(): array
    {
        $parts = preg_split("/(\r\n|\n|\r)/", $this->uplatilac);
        $ime   = array_shift($parts);
        return [
            'ime'    => $ime,
            'adresa' => $parts,
        ];
    }

    public function svrha(string $svrha): self
    {
        $this->svrha = $svrha;
        return $this;
    }

    public function primalac(string $primalac): self
    {
        $this->primalac = $primalac;
        return $this;
    }

    public function telefon(string $tel): self
    {
        $this->telefon = $tel;
        return $this;
    }

    public function getPrimalac(): array
    {
        $parts = preg_split("/(\r\n|\n|\r)/", $this->primalac);
        $ime   = array_shift($parts);
        return [
            'ime'    => $ime,
            'adresa' => $parts,
        ];
    }

    public function sifra(string $sifra): self
    {
        $this->sifra = $sifra;
        return $this;
    }

    public function valuta(string $valuta): self
    {
        $this->valuta = $valuta;
        return $this;
    }

    public function iznos(string $iznos): self
    {
        $this->iznos = $iznos;
        return $this;
    }

    public function formatirajIznos(int $decimale = 2, string $decimalSeparator = ',', string $hiljadeSeparator = '.'): string
    {
        return number_format((float)$this->iznos, $decimale, $decimalSeparator, $hiljadeSeparator);
    }

    public function racun(string $racun): self
    {
        $this->racun = $racun;
        return $this;
    }

    public function model(string $model): self
    {
        $this->model = $model;
        return $this;
    }

    public function pozivNaBroj(string $poziv_na_broj): self
    {
        $this->poziv_na_broj = ($this->model == '97') ? $this->model97($poziv_na_broj) : $poziv_na_broj;
        return $this;
    }

    public function model97(string $poziv): string
    {
        $slova = [
            'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17,
            'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25,
            'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33,
            'Y' => 34, 'Z' => 35
        ];

        $pozivClean = str_replace([' ', '-'], '', strtoupper($poziv));

        $pozivBrojevi = preg_replace_callback('/[A-Z]/', function ($matches) use ($slova) {
          return $slova[$matches[0]];
        }, $pozivClean);

        $numerickiPoziv = (float)$pozivBrojevi;
        $kontrolniBroj = (98 - ($numerickiPoziv * 100 % 97)) % 97;
        $kontrolniBroj = str_pad($kontrolniBroj, 2, '0', STR_PAD_LEFT);

        return $kontrolniBroj . $pozivClean;
    }

    public function model97Validan($poziv): bool
    {
        $poziv = str_replace([' ', '-'], '', strtoupper($poziv));

        if (strlen($poziv) < 2) {
            return false;
        }

        $kontrolniBroj = substr($poziv, 0, 2);
        $pozivBezKontrolnogBroja = substr($poziv, 2);

        $slova = [
            'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17,
            'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25,
            'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33,
            'Y' => 34, 'Z' => 35
        ];

        $pozivBezKontrolnogBroja = preg_replace_callback('/[A-Z]/', function ($matches) use ($slova) {
            return $slova[$matches[0]];
        }, $pozivBezKontrolnogBroja);

        $numerickiPoziv = (float)$pozivBezKontrolnogBroja;
        $calculatedKontrolniBroj = (98 - ($numerickiPoziv * 100 % 97)) % 97;
        $calculatedKontrolniBroj = str_pad($calculatedKontrolniBroj, 2, '0', STR_PAD_LEFT);

        return $kontrolniBroj === $calculatedKontrolniBroj;
    }

    public static function napravi(?Nalog $from = null): self
    {
        if (!$from)
            return new static();

        return (new static())
            ->uplatilac($from->uplatilac)
            ->primalac($from->primalac)
            ->svrha($from->svrha)
            ->sifra($from->sifra)
            ->valuta($from->valuta)
            ->iznos($from->iznos)
            ->racun($from->racun)
            ->model($from->model)
            ->pozivNaBroj($from->poziv_na_broj);
    }

    abstract public function generisi(): Image;

}