#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use CGI qw(:standard);
use JSON qw(decode_json);
use List::Util qw(max sum);
use lib ".";

# Attempt to load the custom module, mock it if missing
eval { require ticketserver::helptranslations; ticketserver::helptranslations->import(qw(getTranslation)); };
if ($@) {
    *getTranslation = sub { return "TR(" . shift . ")"; };
}

# --- Configuration ---
my $json_file = 'support.json';
my $done_file = 'support.done';

# --- CGI Setup ---
my $q = CGI->new;
print $q->header(-type => 'text/html', -charset => 'utf-8');

# --- Parameters ---
my $age_sel   = $q->param('age')   || 'all';
my $view_sel  = $q->param('view')  || 'standard';
my $sel_l1    = $q->param('l1')    || '';
my $sel_l2    = $q->param('l2')    || '';
my $action    = $q->param('action')|| '';
my $mark_lines= $q->param('lines') || '';

# --- Handle Actions (Mark as Done) ---
if ($action eq 'done' && $mark_lines) {
    open(my $fh_done, '>>', $done_file) or die "Cannot open $done_file: $!";
    foreach my $ln (split(',', $mark_lines)) {
        print $fh_done "$ln\n";
    }
    close($fh_done);
    print "<div style='background:#eaffea; padding:10px; border:1px solid green;'><b>Success:</b> Marked lines $mark_lines as done.</div>";
}

# --- Load Done Lines ---
my %done_map;
if (-e $done_file) {
    open(my $fh, '<', $done_file) or die "Cannot open $done_file: $!";
    while (<$fh>) {
        chomp;
        s/^\s+|\s+$//g;
        $done_map{$_} = 1 if $_;
    }
    close($fh);
}

# --- Date Calculation ---
my $now = time();
my $cutoff = 0;
if    ($age_sel eq 'week')  { $cutoff = $now - (7 * 24 * 3600); }
elsif ($age_sel eq 'month') { $cutoff = $now - (30 * 24 * 3600); }
elsif ($age_sel eq 'half')  { $cutoff = $now - (182 * 24 * 3600); }

# --- Data Ingestion & Merging ---
my %merged_data;
my $line_counter = 0;

open(my $fh_json, '<', $json_file) or die "Cannot open $json_file: $!";
while (my $line = <$fh_json>) {
    $line_counter++;
    next if $done_map{$line_counter};

    my $obj;
    eval { $obj = decode_json($line); };
    next if $@;

    next if ($obj->{date} < $cutoff);

    # Regex captures Type ($2) for filtering later
    if ($obj->{mac} =~ /^([^\.]+)([EM])\.(.*)$/) {
        my $location = $1;
        my $type     = $2;
        my $id       = $3;
        my $helpsel  = $obj->{helpsel};
        my $data_txt = $obj->{data};
        my $date     = $obj->{date};

        # Clean trailing dot from ID
        $id =~ s/\.$//;

        my $merge_key = "$location|$id|$helpsel";

        if (exists $merged_data{$merge_key}) {
            my $entry = $merged_data{$merge_key};
            $entry->{date} = $date if $date > $entry->{date};

            if (!is_similar($entry->{data}, $data_txt, 0.8)) {
                $entry->{data} .= " <br>[New]: " . $data_txt;
            }

            $entry->{merge_count}++;
            push @{$entry->{lines}}, $line_counter;

        } else {
            $merged_data{$merge_key} = {
                location    => $location,
                type        => $type,
                id          => $id,
                helpsel     => $helpsel,
                data        => $data_txt,
                date        => $date,
                merge_count => 0,
                lines       => [$line_counter]
            };
        }
    }
}
close($fh_json);

# --- Similarity Helper ---
sub is_similar {
    my ($base, $new, $threshold) = @_;
    return 1 if index($base, $new) != -1;
    my @base_words = split(/\s+/, $base);
    my @new_words  = split(/\s+/, $new);
    return 0 unless @new_words;

    my $matches = 0;
    foreach my $w (@new_words) {
        $matches++ if (index($base, $w) != -1);
    }
    return ($matches / scalar(@new_words)) >= $threshold;
}

# --- HTML Helper ---
sub make_link {
    my ($label, $params) = @_;
    my %curr = map { $_ => $q->param($_) } $q->param;
    delete $curr{'action'};
    delete $curr{'lines'};

    foreach my $k (keys %$params) {
        if (!defined $params->{$k}) { delete $curr{$k}; }
        else { $curr{$k} = $params->{$k}; }
    }
    my $qs = join('&', map { CGI::escape($_) . "=" . CGI::escape($curr{$_}) } keys %curr);
    return "<a href='?$qs'>$label</a>";
}

# --- JS Helper for Translation ---
print <<'END_JS';
<script>
function translateText(elemId, text) {
    var el = document.getElementById(elemId);
    if (!el) return;

    // Visual feedback
    var originalContent = el.innerHTML;
    el.innerHTML = "<span style='color:orange'>Translating...</span>";

    // Use free Google Translate API endpoint (client-side)
    // Note: This strips HTML tags from input to avoid breaking translation structure
    var cleanText = text.replace(/<[^>]*>/g, " ");
    var url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=de&dt=t&q=" + encodeURIComponent(cleanText);

    fetch(url)
        .then(response => response.json())
        .then(data => {
            var translatedText = "";
            // API returns array of sentences: [[["translated", "orig", ...], ...], ...]
            if (data && data[0]) {
                data[0].forEach(function(sentence) {
                    if (sentence[0]) translatedText += sentence[0];
                });
            }

            // Update inplace with translation + Original toggle
            el.innerHTML = "<div style='background:#f0f8ff; padding:4px; border-left:3px solid #007bff;'>"
                         + "<b>DE:</b> " + translatedText
                         + "</div><div style='color:#888; font-size:0.9em; margin-top:2px;'>Orig: " + originalContent + "</div>";
        })
        .catch(error => {
            console.error('Error:', error);
            el.innerHTML = originalContent;
            alert("Translation failed. Check console/network.");
        });
}
</script>
END_JS

# --- Render Header ---
print "<h1>Support Log Viewer</h1>";

print "<p>Time Filter: ";
foreach my $a (qw(week month half all)) {
    print ($age_sel eq $a ? "<b>[$a]</b> " : make_link($a, { age => $a })." ");
}
print "</p>";

print "<p>View Mode: ";
print ($view_sel eq 'standard' ? "<b>[Location -> Helpsel]</b> " : make_link("Location -> Helpsel", { view => 'standard', l1 => undef, l2 => undef })." ");
print ($view_sel eq 'switched' ? "<b>[Helpsel -> Location]</b> " : make_link("Helpsel -> Location", { view => 'switched', l1 => undef, l2 => undef })." ");
print ($view_sel eq 'id_view'  ? "<b>[Location -> ID]</b> "      : make_link("Location -> ID", { view => 'id_view', l1 => undef, l2 => undef })." ");
print "</p><hr>";

# --- Aggregation & Filtering ---
my %tree;
my %counts_l1;          # General count
my %counts_l1_special;  # Standard: Non-4.1 | ID-View: Unique IDs
my %counts_l2;          # General count
my %counts_l2_special;  # Standard: Non-4.1 | ID-View: Total Lines
my %id_line_sums;       # Helper for ID view to sum lines across merges

# First Pass: Pre-calculation for ID View filtering
if ($view_sel eq 'id_view') {
    foreach my $key (keys %merged_data) {
        my $d = $merged_data{$key};
        next if $d->{type} ne 'E'; # Requirement: Only 'E' types
        $id_line_sums{$d->{location}}{$d->{id}} += scalar(@{$d->{lines}});
    }
}

foreach my $key (keys %merged_data) {
    my $d = $merged_data{$key};
    my ($k1, $k2);
    my $include_entry = 0;

    if ($view_sel eq 'standard') {
        $k1 = $d->{location};
        $k2 = $d->{helpsel};
        $include_entry = 1;

        # Calculate filtered counts (Not 4.1)
        my $is_relevant = ($d->{helpsel} ne '4.1') ? 1 : 0;
        $counts_l1_special{$k1} += $is_relevant;
        $counts_l2_special{$k1}{$k2} += $is_relevant;

    } elsif ($view_sel eq 'switched') {
        $k1 = $d->{helpsel};
        $k2 = $d->{location};
        $include_entry = 1;
        # No special filtering requested for switched view, fallback to normal counts

    } elsif ($view_sel eq 'id_view') {
        $k1 = $d->{location};
        $k2 = $d->{id};

        # Filter: Only Type 'E'
        if ($d->{type} eq 'E') {
            # Filter: Only if total lines for this ID > 1
            if (($id_line_sums{$k1}{$k2} || 0) > 1) {
                $include_entry = 1;
                # Special Count L2: Total lines
                $counts_l2_special{$k1}{$k2} = $id_line_sums{$k1}{$k2};
            }
        }
    }

    if ($include_entry) {
        push @{$tree{$k1}{$k2}}, $d;
        $counts_l1{$k1}++;
        $counts_l2{$k1}{$k2}++;
    }
}

# ID View: Fix L1 count to be "Number of Unique IDs", not total entries
if ($view_sel eq 'id_view') {
    foreach my $loc (keys %tree) {
        $counts_l1_special{$loc} = scalar(keys %{$tree{$loc}});
    }
}

# --- Render Tree ---
print "<ul>";

# SORTING LOGIC LEVEL 1
my @l1_sorted;
if ($view_sel eq 'standard') {
    # Sort by Special Count (Non-4.1) DESC, then Total DESC, then Name ASC
    @l1_sorted = sort {
        ($counts_l1_special{$b} // 0) <=> ($counts_l1_special{$a} // 0) ||
        $counts_l1{$b} <=> $counts_l1{$a} ||
        $a cmp $b
    } keys %counts_l1;
} elsif ($view_sel eq 'id_view') {
    # Sort by Unique ID Count DESC, then Name ASC
    @l1_sorted = sort {
        ($counts_l1_special{$b} // 0) <=> ($counts_l1_special{$a} // 0) ||
        $a cmp $b
    } keys %counts_l1_special; # Iterate over special keys for ID view
} else {
    # Default: Total Count DESC, Name ASC
    @l1_sorted = sort {
        $counts_l1{$b} <=> $counts_l1{$a} ||
        $a cmp $b
    } keys %counts_l1;
}

foreach my $l1 (@l1_sorted) {
    print "<li>";

    # DISPLAY LOGIC LEVEL 1
    my $l1_display = $l1;
    my $count_str = "";

    if ($view_sel eq 'switched') {
        $l1_display .= " (" . getTranslation($l1) . ")";
        $count_str = "($counts_l1{$l1})";
    } elsif ($view_sel eq 'standard') {
        # Show (Total / Non-4.1)
        $count_str = "(" . $counts_l1{$l1} . " / " . ($counts_l1_special{$l1} // 0) . ")";
    } elsif ($view_sel eq 'id_view') {
        # Show (Count of IDs)
        $count_str = "(" . ($counts_l1_special{$l1} // 0) . " IDs)";
    } else {
        $count_str = "($counts_l1{$l1})";
    }

    print make_link("$l1_display $count_str", { l1 => ($sel_l1 eq $l1 ? undef : $l1), l2 => undef });

    if ($sel_l1 eq $l1) {
        print "<ul>";

        # SORTING LOGIC LEVEL 2
        my @l2_sorted;
        if ($view_sel eq 'standard') {
            @l2_sorted = sort {
                ($counts_l2_special{$l1}{$b} // 0) <=> ($counts_l2_special{$l1}{$a} // 0) ||
                $counts_l2{$l1}{$b} <=> $counts_l2{$l1}{$a} ||
                $a cmp $b
            } keys %{$counts_l2{$l1}};
        } elsif ($view_sel eq 'id_view') {
             # Sort IDs by total line count DESC
             @l2_sorted = sort {
                ($counts_l2_special{$l1}{$b} // 0) <=> ($counts_l2_special{$l1}{$a} // 0) ||
                $a cmp $b
            } keys %{$counts_l2{$l1}};
        } else {
            @l2_sorted = sort {
                $counts_l2{$l1}{$b} <=> $counts_l2{$l1}{$a} ||
                $a cmp $b
            } keys %{$counts_l2{$l1}};
        }

        foreach my $l2 (@l2_sorted) {
            my $entries = $tree{$l1}{$l2};

            print "<li>";

            # DISPLAY LOGIC LEVEL 2
            my $l2_display = $l2;
            my $cnt_l2_str = "";

            if ($view_sel eq 'standard') {
                $l2_display .= " (" . getTranslation($l2) . ")";
                $cnt_l2_str = "(" . $counts_l2{$l1}{$l2} . " / " . ($counts_l2_special{$l1}{$l2} // 0) . ")";
            } elsif ($view_sel eq 'id_view') {
                # Show Total Lines for this ID
                $cnt_l2_str = "(" . ($counts_l2_special{$l1}{$l2} // 0) . " lines)";
            } else {
                $cnt_l2_str = "(" . $counts_l2{$l1}{$l2} . ")";
            }

            print make_link("$l2_display $cnt_l2_str", { l2 => ($sel_l2 eq $l2 ? undef : $l2) });

            if ($sel_l2 eq $l2) {
                print "<table border='1' cellpadding='5' cellspacing='0' width='100%'>";
                print "<tr><th>Date</th><th>ID/Loc/Help</th><th>Data</th><th>Merges</th><th>Action</th></tr>";

                my $row_idx = 0;
                foreach my $entry (sort { $b->{date} <=> $a->{date} } @$entries) {
                    $row_idx++;
                    my $line_str = join(',', @{$entry->{lines}});
                    my $time_str = localtime($entry->{date});
                    my $merge_display = $entry->{merge_count} > 0 ? $entry->{merge_count} : "-";

                    my $context_info = "";
                    if ($view_sel eq 'standard') { $context_info = $entry->{id}; }
                    if ($view_sel eq 'switched') { $context_info = $entry->{location} . " / " . $entry->{id}; }
                    if ($view_sel eq 'id_view')  { $context_info = $entry->{helpsel} . " (" . getTranslation($entry->{helpsel}) . ")"; }

                    # -- Translation Logic Preparation --
                    my $cell_id = "data_cell_" . $line_counter . "_" . $row_idx;

                    # ROBUST ESCAPING FOR JS/HTML
                    my $js_safe_text = $entry->{data};

                    # 1. Escape existing backslashes first
                    $js_safe_text =~ s/\\/\\\\/g;

                    # 2. Flatten ALL vertical whitespace (Newlines and Carriage Returns) to spaces
                    $js_safe_text =~ s/[\r\n]+/ /g;

                    # 3. Escape single quotes (for JS string '...')
                    $js_safe_text =~ s/'/\\'/g;

                    # 4. Escape double quotes (for HTML attr "...")
                    $js_safe_text =~ s/"/&quot;/g;

                    print "<tr>";
                    print "<td>$time_str</td>";
                    print "<td>$context_info</td>";

                    # -- Data Cell with Translate Button --
                    print "<td>";
                    print "<button style='float:right; font-size:0.7em; cursor:pointer;' ";
                    print "onclick=\"translateText('$cell_id', '$js_safe_text')\">[DE]</button>";
                    print "<span id='$cell_id'>$entry->{data}</span>";
                    print "</td>";

                    print "<td align='center'>$merge_display</td>";
                    print "<td>" . make_link("Mark Done", { action => 'done', lines => $line_str }) . "</td>";
                    print "</tr>";
                }
                print "</table>";
            }
            print "</li>";
        }
        print "</ul>";
    }
    print "</li>";
}
print "</ul>";
print "</body></html>";
