# Pomocné funkce pro vyhledávač a zobrazení výsledků
# Copyright © 2025 Martin Zeman <martin.zemekoule@gmail.com>
# Licence: GNU GPL

package hledat;
use utf8;
use lib '/s/w/lib/dan';
use lib '/s/w/lib/cgi/hry';
use Encode;
use dzsql;
use mysql;
use csort;
use pomoc;
use katalog;
use CGI::Carp qw(fatalsToBrowser);



#------------------------------------------------------------------------------
# Zobrazí stránku s výsledky
#------------------------------------------------------------------------------
sub zobraz_vysledky_vyhledavace
{
    my $databaze = shift;
    my $odd = shift; # kód oddělení obchodu; zajímá nás zejména, zda jde o hry, nebo o něco jiného
    my $retezec = shift; # Hledaný výraz
    my $filtr = shift; # Hash s hodnotami filtru (počet hráčů, délka hry, věk apod.)
    my $page = shift; # Číslo stránky výsledků
    my $kosik = shift; # Pro zobrazení tlačítka "Přidat do košíku"
    $page = $page ? $page : 1; # Defaultně první stránka
    my $html;
    
    my @zbozi = hledat_nazev($databaze, $odd, $retezec);
    if($filtr) {@zbozi = filtr($filtr, @zbozi);}
    # Seřadit
    my @zbozi = sort {$a->{'zbozi.nazev'} <=> $b->{'zbozi.nazev'}} @zbozi;
    my @zbozi = sort {$a->{relevance} <=> $b->{relevance}} @zbozi;
    
    my $pocet_vysledku = scalar @zbozi;
    my $vysledku_na_stranku = 25; # Lze změnit, ale pouze zde
    my $pocet_stranek = int(($pocet_vysledku-1) / $vysledku_na_stranku) + 1;
    my $zacatek = $vysledku_na_stranku*($page-1);
    my $konec = $zacatek + $vysledku_na_stranku - 1;
    $konec = $konec >= $pocet_vysledku ? $pocet_vysledku - 1 : $konec;
    # Začátek html
    $html .= filtr_formular($retezec, $filtr);
    $html .= "<div class=\"filtr-vysledky\">\n";
    $html .= "  <hr noshade style=\"margin: 0px;\"/>\n";
    if($pocet_vysledku)
    {
        $html .= "  <h2>Nalezeno $pocet_vysledku výsledků:</h2>\n";
        # Odkaz na další stránky výsledků
        if($pocet_stranek > 1)
        {
            $html .= "  <p style=\"padding-left: 20px;\"><b>Stránky:";
            for ((1..$pocet_stranek)) {
                if($_ ~~ [1, $page - 1, $page, $page + 1, $pocet_stranek])
                {$html .= $_ == $page ? " <em><u>$_</u></em> " : filtr_odkazpar($retezec, $filtr, " $_ ", "p=$_");}
                elsif($_ ~~ [2, $pocet_stranek - 1])
                { if($_ ~~ [$page - 2, $page + 2]) # Pokud je celkově málo stránek, nepotřebujeme tečkovat, když to nahrazuje jeden odkaz
                    {$html .= $_ == $page ? " <em><u>$_</u></em> " : filtr_odkazpar($retezec, $filtr, " $_ ", "p=$_");}
                  else {$html .= "...";}
                }
            }
            $html .= "</b></p>\n";
        }
        # Vypsat dané zboží
        $html .= "  <table border=0 bgcolor=white align=center>\n";
        foreach my $z (@zbozi[$zacatek..$konec])
        {
            $html .= "    <tr><td colspan=4><hr noshade /></td></tr>\n";
            $html .= sestavit_radek_tabulky_o_zbozi_vyhledavac($odd, $z, $kosik, $retezec, $filtr);
        }
        $html .= "    <tr><td colspan=4><hr noshade /></td></tr>\n";
        # Odkaz na následující stránku
        if($page < $pocet_stranek)
        {
            $new_page = $page + 1;
            $html .= "    <tr class=\"next-page\"><td colspan=4 align=center><br>".filtr_odkazpar($retezec, $filtr, " Další stránka ", "p=$new_page")."</td></tr>\n";
        }
        $html .= "  </table>\n";
    }
    else
    {
        $html .= "  <h2 class=\"nenalezeno\">Nebyly nalezeny žádné hry, jejichž název by obsahoval daný řetězec znaků a vyhovoval filtrům</h2>\n";
    }
    $html .= "</div>\n";
    $html .= "<img id=\"trp_08\" src=\"https://obchod.hrejsi.cz/ondra_2012/trpaslici/08_trp.png\">\n";
    $html .= "<img id=\"trp_01\" src=\"https://obchod.hrejsi.cz/ondra_2012/trpaslici/01_trp.png\">\n";
    return $html;
}



#------------------------------------------------------------------------------
# Vytáhne z databáze seznam zboží.
#------------------------------------------------------------------------------
sub databazezbozi
{
    my $databaze = shift;
    my $odd = shift; # kód oddělení obchodu; zajímá nás zejména, zda jde o hry, nebo o něco jiného
    # Získat z databáze údaje o hrách.
    my $tabulka;
    my @nazvy;
    if($odd eq 'hry')
    {
        $tabulka = 'zbozi INNER JOIN hry ON hry.kod=zbozi.kod_hry';
        @nazvy = qw(kod_hry zbozi.kod hry.kod zbozi.nazev hry.nazev prodejni_cena bezna_cena cena_na_akci nelze_koupit slozka_hrejsi novinka sleva popis_zbozi zbozi.poznamka lokalizace paluba cerny_most deti zbozi.rodina experti mejdan logicka postreh vedomostni karetni pro_2 rozsireni poradi ean pocet_hracu min_delka max_delka min_vek upoutavka autor rok_vydani);
    }
    else
    {
        $tabulka = 'zbozi INNER JOIN skupiny ON skupiny.kod=zbozi.kod_skupiny';
        @nazvy = qw(kod_skupiny zbozi.kod skupiny.kod zbozi.nazev skupiny.nazev prodejni_cena bezna_cena cena_na_akci nelze_koupit slozka_hrejsi novinka sleva popis_zbozi zbozi.poznamka lokalizace paluba cerny_most deti zbozi.rodina experti mejdan logicka postreh vedomostni karetni pro_2 rozsireni poradi ean pocet_hracu min_delka max_delka min_vek upoutavka autor rok_vydani);
    }
    my $zbozi = dzsql::dotaz($databaze, @nazvy, "$tabulka ORDER BY zbozi.nazev");
    return $zbozi;
}



#------------------------------------------------------------------------------
# Prohledá databázi na základě hledaného výrazu a vrátí seznam s odpovídajícím
# zbožím. (hash zboží)
#------------------------------------------------------------------------------
sub hledat_nazev
{
    my $databaze = shift;
    my $odd = shift;
    my $retezec = shift; # Hledaný výraz
    my @retezicky = grep { $_ ne '' } split(/\s+/, $retezec); # Rozsekaný na slova
    my $zbozi = databazezbozi($databaze, $odd);
    #if(!$retezec) {return @{$zbozi};} # Pokud je řetězec prázdný, vrátíme všechno zboží
    my @final; # Sem budu dávat výsledky obsahující řetězec
    # Udělat výběr podle alternativních názvů hry.
    my $althra = mysql::dotaz($databaze, "kod", "hry.nazev AS nazev", "slozka_hrejsi", "hry INNER JOIN nazvy ON hry.kod = nazvy.kod_hry WHERE nazvy.nazev LIKE '%$retezec%'");
    my %altkody = map { $_->{kod} => $_ } @{$althra};
    foreach my $z (@{$zbozi})
    {
        # Nejdřív zkontrolovat, jestli nesedí s EANem
        if($z->{ean} eq $retezec)
        {
            $z->{relevance} = 0; # Chceme ukazovat navrchu
            push(@final, $z);
        }
        # S názvem zboží
        elsif($z->{'zbozi.nazev'} =~ /$retezec/i)
        {
            $z->{relevance} = 1;
            push(@final, $z);
        }
        # S názvem hry
        elsif($z->{'hry.nazev'} =~ /$retezec/i)
        {
            $z->{relevance} = 2;
            push(@final, $z);
        }
        # Alternativní názvy
        elsif($altkody{$z->{hry.kod}}) # Už to bylo vyfiltrováno podle řetězce při výtahu z databáze
        {
            $z->{relevance} = 3;
            push(@final, $z);
        }
        # Porovnáme název zboží s každým slovem řetězce, které je alespoň 3 písmena dlouhé (abychom se vyhnuli běžným spojkám)
        else{
            foreach my $r (@retezicky)
            {
                if(length($r) >= 3)
                {
                    if($z->{'zbozi.nazev'} =~ /$r/i)
                    {
                        $z->{relevance} = 4;
                        push(@final, $z);
                        last;
                    }
                }
            }
        }
        # Pokud nelze koupit, chceme ukazovat až nakonec
        $z->{relevance} = $z->{relevance}+5 if($z->{nelze_koupit});
    }
    return @final;
}



#------------------------------------------------------------------------------
# Profiltruje zboží podle parametrů filtru (počet hráčů, věk, délka apod.)
#------------------------------------------------------------------------------
sub filtr
{
    my $filtr = shift; # Odkaz na hash s filtrovacími údaji
    my @zbozi = @_; # Zboží, které chci profiltrovat
    my @final;
    foreach my $z (@zbozi)
    {
        # Počet hráčů ----------------------------------------------------------
        my $ph = 1;
        $filtr->{minp} = $filtr->{minp} ? $filtr->{minp} : 1; # Nastavíme, pokud nejsou
        $filtr->{maxp} = $filtr->{maxp} ? $filtr->{maxp} : 20;
        # Rozdělíme na hodnoty
        my @pocet_hracu = split(/\s*,\s*/, $z->{pocet_hracu});
        # Ořežeme stringy pouze na čísla, prázdné vyhodíme
        @pocet_hracu = grep { /^[0-9]+$/ && $_ >= $filtr->{minp} && $_ <= $filtr->{maxp} } @pocet_hracu;
        next unless(scalar(@pocet_hracu)>0);
        # Délka hry ------------------------------------------------------------
        if($filtr->{mind}) {
            next if($filtr->{mind} > $z->{min_delka});
        }
        if($filtr->{maxd}) {
            next if($filtr->{maxd} < $z->{max_delka});
            next if($filtr->{maxd} < $z->{min_delka})
        }
        # Minimální věk --------------------------------------------------------
        if($filtr->{minv}) {
            next if($filtr->{minv} > $z->{min_vek});
        }
        if($filtr->{maxv}) {
            next if($filtr->{maxv} < $z->{min_vek});
        }
        # Rok vydání -----------------------------------------------------------
        if($filtr->{minr}) {
            next if($filtr->{minr} > $z->{rok_vydani});
        }
        if($filtr->{maxr}) {
            next if($filtr->{maxr} < $z->{rok_vydani});
        }
        # Autor hry ------------------------------------------------------------
        if($filtr->{autor}) {
            next unless($z->{autor} =~ /$filtr->{autor}/i);
        }
        push(@final, $z);
    }
    return @final;
}



#------------------------------------------------------------------------------
# Sestaví html form s inputy pro filtr
#------------------------------------------------------------------------------
sub filtr_formular
{
    my $retezec = shift; # Poslední hledaný výraz
    my $filtr = shift; # Hash s hodnotami filtru (počet hráčů, délka hry, věk apod.) posledního vyhledávání
    my $html;
    $html .= "<form method=get action=\"prodej.pl\" class=\"filtr\">\n";
    $html .= odsadit(formpar(), 2);
    # Vynulovat pole, která by mohla způsobit, že se místo výsledků hledání zobrazí něco jiného.
    $html .= "  <input type=hidden name=odd value=hry>\n";
    $html .= "  <input type=hidden name=pohled value=\"hledat\">\n";
    $html .= "  <input type=hidden name=hra value=\"\">\n";
    $html .= "  <input type=hidden name=zbozi value=\"\">\n";
    $html .= "  <input type=hidden name=p value=\"1\">\n";
    $html .= "  <h1>Filtr her</h1>\n";
    $html .= "  <table>\n";
    $html .= "    <tr><td colspan=\"4\"><h3>Název:</h3></td><td colspan=\"4\" style=\"padding-left: 75px;\"><h3>Autor hry:</h3></td></tr>\n";
    $html .= "    <tr><td colspan=\"4\"><input type='text' name='hledat' placeholder='Název hry' value=\"$retezec\"></td>";
    $html .= "        <td colspan=\"4\" style=\"padding-left: 75px;\"><input type='text' name='autor' placeholder='Autor hry' value=\"$filtr->{autor}\"></td></tr>\n";
    $html .= "    <tr>\n";
    $html .= "      <td colspan=\"2\"><h3>Počet hráčů:</h3></td>\n";
    $html .= "      <td colspan=\"2\" style=\"padding-left: 75px;\"><h3>Délka hry:</h3></td>\n";
    $html .= "      <td colspan=\"2\" style=\"padding-left: 75px;\"><h3>Minimální věk:</h3></td>\n";
    $html .= "      <td colspan=\"2\" style=\"padding-left: 75px;\"><h3>Rok vydání:</h3></td>\n";
    $html .= "    </tr>\n";
    $html .= "    <tr class=\"filtr-udaje\">\n";
    $html .= "      <td><input type='number' name='minp' placeholder='min' value=\"$filtr->{minp}\" size=5> &nbsp;&nbsp;&nbsp;-</td>\n";
    $html .= "      <td><input type='number' name='maxp' placeholder='max' value=\"$filtr->{maxp}\" size=5></td>\n";
    $html .= "      <td style=\"padding-left: 75px;\"><input type='number' name='mind' placeholder='min' value=\"$filtr->{mind}\" size=5> &nbsp;&nbsp;&nbsp;-</td>\n";
    $html .= "      <td><input type='number' name='maxd' placeholder='max' value=\"$filtr->{maxd}\" size=5> minut</td>\n";
    $html .= "      <td style=\"padding-left: 75px;\"><input type='number' name='minv' placeholder='min' value=\"$filtr->{minv}\" size=5> &nbsp;&nbsp;&nbsp;-</td>\n";
    $html .= "      <td><input type='number' name='maxv' placeholder='max' value=\"$filtr->{maxv}\" size=5> let</td>\n";
    $html .= "      <td style=\"padding-left: 75px;\"><input type='number' name='minr' placeholder='min' value=\"$filtr->{minr}\" size=5> &nbsp;&nbsp;&nbsp;-</td>\n";
    $html .= "      <td><input type='number' name='maxr' placeholder='max' value=\"$filtr->{maxr}\" size=5></td>\n";
    $html .= "    </tr>\n";
    $html .= "    <tr><td colspan=\"5\"></td><td></td></tr>\n";
    $html .= "  </table>\n";
    $html .= "  <button type=submit><b>Hledat</b>&nbsp;&nbsp;<img src='https://obchod.hrejsi.cz/ondra_2012/grafika/search.png' width=15px></button>\n";
    $html .= "</form>\n";
    return $html;
}



#------------------------------------------------------------------------------
# Vyrobí HTML řádek tabulky o jednom zboží, např. v tabulce novinek nebo akcí.
#------------------------------------------------------------------------------
sub sestavit_radek_tabulky_o_zbozi_vyhledavac
{
    my $odd = shift; # kód oddělení obchodu; zajímá nás zejména, zda jde o hry, nebo o něco jiného
    my $zbozi = shift; # odkaz na hash o druhu zboží
    my $kosik = shift; # Pro tlačítko přidat do košíku musíme znát obsah
    my $retezec = shift; # Kvůli odkazům je to třeba i zde
    my $filtr = shift;
    my $html;
    my $hnazev = ($odd eq 'hry') ? 'hry' : 'skupiny';
    $html .= "    <tr>\n";
    # Vložit fotku zboží, pokud je k dispozici.
    $html .= "      <td valign=\"top\">\n";
    $html .= "        ".katalog::foto($zbozi->{slozka_hrejsi}, $zbozi->{$hnazev.'.kod'}, $zbozi->{'zbozi.kod'}, 100)."\n";
    $html .= "      </td>\n";
    $html .= "      <td valign=\"top\" width='20%'>\n";
    # Přidat štítky kategorií
    $html .= katalog::stitky_kategorii($zbozi, '17.5px', 2, 'hledat');
    $html .= "        <b>".odkazpar($zbozi->{'zbozi.nazev'}, 'pohled=zbozi', "hra=$zbozi->{kod_hry}", "zbozi=$zbozi->{\"zbozi.kod\"}")."</b><br/>\n";
    # Uvést cenu a srovnat ji s běžnou cenou tohoto zboží na trhu.
    if($zbozi->{nelze_koupit})
    {
        $html .= "        <b>Litujeme, ale hra momentálně <span style='color: red;'>NENÍ v nabídce.</span></b><br/>\n";
    }
    elsif($zbozi->{sleva})
    {
        if($zbozi->{prodejni_cena} == $zbozi->{cena_na_akci})
        {
            $html .= "        <b>Trvale nízká cena: <span style='color: red;'>$zbozi->{cena_na_akci}&nbsp;Kč</span></b><br/>\n";
        }
        else
        {
            $html .= "        Cena před 30 dny: <span style='text-decoration-line: line-through;'>$zbozi->{prodejni_cena}&nbsp;Kč</span><br/>\n";
            $sleva_prc = int(($zbozi->{prodejni_cena}-$zbozi->{cena_na_akci})/$zbozi->{prodejni_cena}*100);
            $html .= "        <b>Akční cena: <span style='color: red;'>$zbozi->{cena_na_akci}&nbsp;Kč</span></b> (<span style='color: red;'>-$sleva_prc%</span>)<br/>\n";
        }
        if($zbozi->{bezna_cena}>0)
        {
            $html .= "        Běžná cena: $zbozi->{bezna_cena}&nbsp;Kč\n";
        }
        else
        {
            $html .= "        Běžně se v&nbsp;Česku neprodává.\n";
        }
    }
    else
    {
        $html .= "        <b>Naše cena: $zbozi->{prodejni_cena}&nbsp;Kč</b><br/>\n";
        if($zbozi->{bezna_cena}>0)
        {
            $html .= "        Běžná cena: $zbozi->{bezna_cena}&nbsp;Kč\n";
            if($zbozi->{bezna_cena}>$zbozi->{prodejni_cena})
            {
                my $uspora_kc = $zbozi->{bezna_cena}-$zbozi->{prodejni_cena};
                my $uspora_prc = $uspora_kc/$zbozi->{bezna_cena}*100;
                if($uspora_prc>=4)
                {
                    $html .= sprintf("        <br/>(ušetříte %d&nbsp;%%)\n", $uspora_prc);
                }
            }
        }
        else
        {
            $html .= "        Běžně se v&nbsp;Česku neprodává.\n";
        }
    }
    $html .= "      </td>\n";
    # Sestavit informaci o aktuální zásobě tohoto zboží na skladě.
    # Z historických důvodů je distribuční sklad v databázi veden ve sloupci "cerny_most".
    # Nyní je tento sklad samozřejmě v Jenštejně a je to náš jediný sklad.
    $html .= "      <td valign=\"top\">\n";
    if(!$zbozi->{nelze_koupit}) {
        my $sklad = $zbozi->{cerny_most};
        my $prah = 2;
        if($sklad>=$prah)
        {
            $html .= "        Skladem <b>alespoň $prah&nbsp;ks.</b>\n";
        }
        elsif($sklad>0)
        {
            $html .= "        Skladem <b>$sklad&nbsp;ks.</b>\n";
        }
        else
        {
            $html .= "        Tato položka momentálně <b>není skladem</b>.\n";
        }
        
        my $novy_kosik = kosik::upravit_pocet($kosik, $odd, $zbozi->{'zbozi.kod'}, +1, 1);
        $html .= filtr_button_odkazpar($retezec, $filtr, "<br/><br/><img src=https://obchod.hrejsi.cz/ondra_2012/grafika/kosik-add.png height=40px class=enlarge />", "", "kosik=$novy_kosik");
    }
    $html .= "      </td>\n";
    # Přidat info o počtu hráčů, délky hry a min věku
    $html .= "      <td valign=\"top\">\n";
    $html .= "        <table class=\"zbozi_info\"><tr>\n";
    my $pocet_hracu = katalog::zjistit_pocet_hracu($zbozi->{pocet_hracu});
    $html .= "          <td><img src=https://obchod.hrejsi.cz/ondra_2012/grafika/players.png height=30px></td>\n" if($pocet_hracu);
    $html .= "          <td valign=\"center\">$pocet_hracu</td>\n" if($pocet_hracu);
    my $delka;
    if($zbozi->{min_delka}!=0)
    {
        if($zbozi->{min_delka}>=60*24)
        {
             my $dnymin = sprintf("%d", ($zbozi->{min_delka}/60/24)+0.5);
             my $dnymax = sprintf("%d", ($zbozi->{max_delka}/60/24)+0.5);
             $delka = sprintf("%s %s.\n", $dnymax==$dnymin ? $dnymax : "$dnymin - $dnymax", $dnymax==1 ? "den" : $dnymax>=2 && $dnymax<=4 ? "dny" : "dnů");
        }
        elsif($zbozi->{min_delka}>=100)
        {
             my $hodmin = sprintf("%.1f", ($zbozi->{min_delka}/60)+0.05);
             my $hodmax = sprintf("%.1f", ($zbozi->{max_delka}/60)+0.05);
             $delka = $hodmin == $hodmax ? "$hodmin hod\n" : "$hodmin - $hodmax hod\n";
        }
        else
        {
            $delka = $zbozi->{min_delka} == $zbozi->{max_delka} ? "$zbozi->{min_delka} min\n" : "$zbozi->{min_delka} - $zbozi->{max_delka} min\n";
        }
    }
    $html .= "          <td><img src=https://obchod.hrejsi.cz/ondra_2012/grafika/time.png height=30px></td>\n" if($delka);
    $html .= "          <td valign=\"center\">$delka</td>\n" if($delka);
    $html .= "          <td><img src=https://obchod.hrejsi.cz/ondra_2012/grafika/age.png height=30px></td>\n" if($zbozi->{min_vek});
    $html .= "          <td valign=\"center\">$zbozi->{min_vek}+</td>\n" if($zbozi->{min_vek});
    $html .= "        </tr></table>\n";
    $html .= "        <br/>\n";
    # Doplnit další poznámky o této položce.
    my @poznamky;
    push(@poznamky, "<b>$zbozi->{'zbozi.poznamka'}</b>") if($zbozi->{'zbozi.poznamka'} ne '');
    push(@poznamky, "<div class='zbozi_popis'><p>$zbozi->{upoutavka}</p></div>") if($zbozi->{upoutavka} ne '');
    push(@poznamky, $zbozi->{popis_zbozi}) if($zbozi->{popis_zbozi} ne '');
    #push(@poznamky, $zbozi->{lokalizace}) if($zbozi->{lokalizace} ne '');
    my $poznamky = join("<br/>\n            ", @poznamky);
    $html .= "        $poznamky\n";
    $html .= "      </td>\n";
    $html .= "    </tr>\n";
    # Dodatečné info:
    if($zbozi->{rok_vydani} or $zbozi->{autor})
    {
        my $pomlcka = " - " if($zbozi->{rok_vydani} and $zbozi->{autor});
        $html .= "    <tr>\n";
        $html .= "      <td colspan=4>$zbozi->{rok_vydani}$pomlcka$zbozi->{autor}</td>\n";
        $html .= "    </tr>\n";
    }
    return $html;
}



#------------------------------------------------------------------------------
# odkazpar(), který zachová všechny informace filtrů
#------------------------------------------------------------------------------
sub filtr_odkazpar
{
    my $retezec = shift;
    my $filtr = shift;
    return odkazpar(@_, "hledat=$retezec", "minp=$filtr->{minp}", "maxp=$filtr->{maxp}", "mind=$filtr->{mind}", "maxd=$filtr->{maxd}", "minv=$filtr->{minv}", "maxv=$filtr->{maxv}", "minr=$filtr->{minr}", "maxr=$filtr->{maxr}", "autor=$filtr->{autor}");
}



#------------------------------------------------------------------------------
# button_odkazpar(), který zachová všechny informace filtrů
#------------------------------------------------------------------------------
sub filtr_button_odkazpar
{
    my $retezec = shift;
    my $filtr = shift;
    return button_odkazpar(@_, "hledat=$retezec", "minp=$filtr->{minp}", "maxp=$filtr->{maxp}", "mind=$filtr->{mind}", "maxd=$filtr->{maxd}", "minv=$filtr->{minv}", "maxv=$filtr->{maxv}", "minr=$filtr->{minr}", "maxr=$filtr->{maxr}", "autor=$filtr->{autor}");
}





1;
