<?_code
{
    use strict;
    use vars qw($title $body %GET %POST);

    $title = "Spam Reports";
    $body = "";
    
    my $error = sub { 
        $title = "Error";
        $body = join '', @_;
        return undef;
    };
    my $makelink = sub {
        my ($by, $what, $state, $reporttime, $etext) = @_;
        $by = LJ::eurl($by);
        $what = LJ::eurl($what);
        $state = LJ::eurl($state);
        $reporttime = LJ::mysql_time($reporttime);
        $reporttime = $etext if $etext;
        return "<a href=\"spamreports.bml?mode=view&amp;by=$by&amp;what=$what&amp;state=$state\">$reporttime</a>";
    };
    my $dellink = sub {
        my ($by, $what, $text) = @_;
        return "<form method=\"post\" action=\"spamreports.bml\">" .
               LJ::html_hidden('mode', $by) .
               LJ::html_hidden('what', $what) .
               LJ::html_hidden('ret', "spamreports.bml?" . join('&amp;', map { "$_=" . LJ::eurl($GET{$_}) } keys %GET)) .
               LJ::html_submit('submit', $text) .
               "</form>";
    };
    
    # login check
    my $remote = LJ::get_remote();
    return $error->("You must be logged in to be here.")
        unless $remote;
    
    # priv check
    return $error->("You do not have the necessary privilege to be here.")
        unless LJ::check_priv($remote, 'siteadmin', 'spamreports');

    # show the top 10 spam reports by IP
    my $mode = lc($GET{mode} || $POST{mode});
    $mode = '' if $mode =~ /^del/ && !LJ::did_post() && !LJ::check_referer('/admin/spamreports.bml');

    # combined/user/anon viewing?
    my $view = $mode =~ /_([cua])$/ ? $1 : 'c';
    my ($extrawhere, $extratitle);
    if    ($view eq 'c') { $extrawhere = '1'; }
    elsif ($view eq 'u') { $extrawhere = 'posterid > 0'; $extratitle = " - Users Only"; }
    elsif ($view eq 'a') { $extrawhere = 'posterid = 0'; $extratitle = " - Anonymous Only"; }
    $mode =~ s/_[cua]$//; # strip out viewing option

    my $dbr = LJ::get_db_reader();
    return $error->("Unable to get database reader handle.") unless $dbr;
    my @rows;
    my @headers;
    if ($mode eq 'top10ip') {
        # top 10 by ip
        $title = "Spam Reports - Top 10 by IP Address";
        @headers = ('Number of Reports', 'IP Address', 'Most Recent Report');
        my $res = $dbr->selectall_arrayref('SELECT COUNT(ip) AS num, ip, MAX(reporttime) FROM spamreports ' .
                                           "WHERE state = 'open' AND ip IS NOT NULL " .
                                           'GROUP BY ip ORDER BY num DESC LIMIT 10');
        foreach (@$res) {
            push @rows, [ $_->[0], $_->[1], $makelink->('ip', $_->[1], 'open', $_->[2]) ];
        }
 
    } elsif ($mode eq 'top10user') {
        # top 10 by user
        $title = "Spam Reports - Top 10 by User";
        @headers = ('Number of Reports', 'Posted By User', 'Most Recent Report');
        my $res = $dbr->selectall_arrayref('SELECT COUNT(posterid) AS num, posterid, MAX(reporttime) FROM spamreports ' .
                                           "WHERE state = 'open' AND posterid > 0 " .
                                           'GROUP BY posterid ORDER BY num DESC LIMIT 10');
        foreach (@$res) {
            my $u = LJ::load_userid($_->[1]);
            push @rows, [ $_->[0], LJ::ljuser($u), $makelink->('posterid', $_->[1], 'open', $_->[2]) ];
        }
 
    } elsif ($mode eq 'tlast10') {
        # most recent 10 reports
        $title = "Spam Reports - Last 10$extratitle";
        @headers = ('Posted By', 'Posted In', 'Report Time');
        my $res = $dbr->selectall_arrayref('SELECT posterid, ip, journalid, reporttime FROM spamreports ' .
                                           "WHERE state = 'open' AND $extrawhere ORDER BY reporttime DESC LIMIT 10");
        foreach (@$res) {
            my $u2 = LJ::load_userid($_->[2]);
            if ($_->[0] > 0) {
                my $u = LJ::load_userid($_->[0]);
                push @rows, [ LJ::ljuser($u), LJ::ljuser($u2), $makelink->('posterid', $_->[0], 'open', $_->[3]) ];
            } else {
                push @rows, [ "$_->[1]", LJ::ljuser($u2), $makelink->('ip', $_->[1], 'open', $_->[3]) ];
            }
        }

    } elsif ($mode =~ /^last(\d+)hr$/) {
        # reports in last X hours
        my $hours = $1+0;
        my $secs = $hours * 3600; # seconds in an hour
        $title = "Spam Reports - Last $hours Hour" . ($hours == 1 ? '' : 's') . $extratitle;
        @headers = ('Number of Reports', 'Posted By', 'Report Time');
        my $res = $dbr->selectall_arrayref('SELECT journalid, ip, posterid, reporttime FROM spamreports ' .
                                           "WHERE $extrawhere AND reporttime > (UNIX_TIMESTAMP() - $secs) LIMIT 1000");

        # count up items and their most recent report
        my %hits;
        my %times;
        foreach (@$res) {
            my $key;
            if ($_->[2] > 0) {
                my $u = LJ::load_userid($_->[2]);
                next unless $u;
                $key = $u->{userid};
            } else {
                next unless $_->[1];
                $key = $_->[1];
            }
            $hits{$key}++;
            $times{$key} = $_->[3] unless $times{$key} gt $_->[3];
        }
        
        # now reverse to number => item list
        my %revhits;
        foreach (keys %hits) {
            if ($revhits{$hits{$_}}) {
                push @{$revhits{$hits{$_}}}, $_;
            } else {
                $revhits{$hits{$_}} = [ $_ ];
            }
        }

        # now push them onto @rows
        foreach (sort { $b <=> $a } keys %revhits) {
            my $r = $revhits{$_};
            foreach (@$r) {
                my $isip = $_ =~ /\./ ? 1 : 0;
                push @rows, [ $hits{$_}, $isip ? $_ : LJ::ljuser(LJ::load_userid($_)), 
                              $makelink->($isip ? 'ip' : 'posterid', $_, 'open', $times{$_}) ];
            }
        }

    } elsif ($mode eq 'view') {
        # view a particular report
        my ($by, $what, $state) = (lc($GET{by}), $GET{what}, lc($GET{state}));
        $by = '' unless $by =~ /^(?:ip|poster(?:id)?)$/;
        $state = 'open' unless $state =~ /^(?:open|closed)$/;
        $body .= "<?p [ <a href=\"spamreports.bml\">&lt;&lt; Front Page</a> ] ";
        
        # open/closed links
        my $eargs = LJ::eurl("?by=$by&what=$what&state");
        if ($state eq 'open') {
            $body .= " [ " . $makelink->($by, $what, 'closed', undef, "View Closed Reports") . " ]";
        } else {
            $body .= " [ " . $makelink->($by, $what, 'open', undef, "View Open Reports") . " ]";
        }
        $body .= " p?>\n";

        # setup title and verify that the data is right
        if ($by eq 'posterid') {
            $what += 0;
            my $u = LJ::load_userid($what);
            return $error->('No such posterid.') unless $u;
            $title = "Spam Reports - By $u->{user} ($state)";
        } elsif ($by eq 'poster') {
            my $u = LJ::load_user($what);
            return $error->('No such user.') unless $u;
            $title = "Spam Reports - Comments By $u->{user}";

            # Now just pretend that user used 'posterid'
            $by = 'posterid';
            $what = $u->{userid};
        } elsif ($by eq 'ip') {
            # check for right format x.x.x.x, not necessarily a valid IP
            return $error->('No such IP.') if $what !~ /^\d+\.\d+\.\d+\.\d+$/ or length $what > 15;
            $title = "Spam Reports - By IP $what ($state)";
        }

        # see if we should call a hook for extra actions?
        $body .= LJ::run_hook('spamreport_notification', $remote, { $by => $what })
            if $state eq 'open' && $by eq 'posterid';

        # now the general info gathering
        my $res = $dbr->selectall_arrayref('SELECT reporttime, journalid, subject, body, ip, posttime, report_type ' .
                                           "FROM spamreports WHERE state=? AND $by=? ORDER BY reporttime DESC LIMIT 1000",
                                            undef, $state, $what);
        unless ($res && @$res) {
            $body .= "No reports found.";
            return undef;
        }
        $body .= '<table>';
        foreach (@$res) {
            my $u2 = LJ::load_userid($_->[1]);
            my $x = $by eq 'ip' ? 4 : 1;
            my $comment_body = $_->[3];
            LJ::text_uncompress(\$comment_body);
            my $spamlocation = ($_->[6] eq 'entry') ? 'Entry' : 'Comment';
            $body .= '<tr><td>' .  ($state eq 'open' ? $dellink->("del$by", "$_->[0]:$_->[$x]", 'Close') : '') . '</td><td>' .
                     "<strong>$spamlocation in:</strong> " . LJ::ljuser($u2) . '<br />' .
                     '<strong>Report Time:</strong> ' . LJ::mysql_time($_->[0]) . '<br />' .
                     "<strong>$spamlocation Time:</strong> " . ($_->[5] ? LJ::mysql_time($_->[5]) : 'not recorded') . '<br />' .
                     '<strong>Subject:</strong> ' . LJ::ehtml($_->[2] || 'no subject') . '<br />' .
                     '<strong>Body:</strong> ' . LJ::ehtml($comment_body || 'no body') . '<br />' .
                     '</td></tr><tr><td>&nbsp;</td></tr>';
        }
        $body .= "</table><br />" . ($state eq 'open' ? $dellink->("delby$by", $what, 'Close All') : '');
        
    } elsif ($mode =~ /^del/) {
        # figure out our combination
        my $dbh = LJ::get_db_writer();
        return $error->("Unable to get database writer handle.") unless $dbh;
        my ($sql, $count, $backlink);
        if ($mode =~ /^delby/) {
            # enmasse deletion
            my $where = $mode =~ /ip$/ ? 'ip' : 'posterid';
            $sql = "UPDATE spamreports SET state='closed' WHERE $where=?";
            $count = $dbh->do($sql, undef, $POST{what});
            return $error->($dbh->errstr) if $dbh->err;
        } else {
            # single item deletion
            my $where = $mode =~ /ip$/ ? 'ip' : 'journalid';
            my ($time, $data) = ($1, $2)
               if $POST{what} =~ /^(\d+):(.+)$/;
            $data ||= $POST{what};
            $count = $dbh->do("UPDATE spamreports SET state='closed' WHERE reporttime=? AND $where=? AND state='open'", undef, $time, $data);
            return $error->($dbh->errstr) if $dbh->err;
            $backlink = "[ <a href='$POST{ret}'>&lt;&lt; Go Back</a> ]";
        }
        $title = "Close Reports";
        $body .= "<?p [ <a href=\"spamreports.bml\">&lt;&lt; Front Page</a> ] $backlink p?>\n";
        my $s = $count == 1 ? '' : 's';
        $body .= "Closed $count report$s.\n";

    } else {
        # standard
        my %modes = (top10user => 'Top 10 by User', top10ip => 'Top 10 by IP Address', tlast10 => 'Last 10 Reports',
                     last01hr => 'Last 1 Hour', last06hr => 'Last 6 Hours', last24hr => 'Last 24 Hours');
        $body .= "<?p Available reports: p?>\n<ul>";
        foreach (sort keys %modes) {
            $body .= "<li><a href=\"spamreports.bml?mode=$_\">$modes{$_}</a>";
            if ($_ =~ /last/) {
                # this is a last view, so we have other options
                $body .= " [<a href=\"spamreports.bml?mode=${_}_u\">users</a>, ";
                $body .= "<a href=\"spamreports.bml?mode=${_}_a\">anonymous</a>]";
            }
            $body .= "</li>";
        }
        $body .= qq{<li><form method="GET" action="spamreports.bml" style="display: inline; margin: 0;">
            <label for="repu">Reports for user:
                <input type="text" name="what" size="15" maxlength="15" id="repu" />
                <input type="hidden" name="by" value="poster" />
                <input type="hidden" name="mode" value="view" />
            </label></form></li>
        };
        $body .= "</ul>\n<?p Please select one of the above reports to view.  Actions can be taken when viewing a report. p?>";
    }

    # now spit out the requested table
    return unless @headers;
    $body .= "<?p [ <a href=\"spamreports.bml\">&lt;&lt; Front Page</a> ] p?>";
    $body .= "<table width=\"50%\">\n<tr>";
    $body .= "<th align=\"center\">$_</th>" foreach @headers;
    $body .= "</tr>\n";
    foreach (@rows) {
        $body .= "<tr>";
        $body .= "<td align=\"center\">$_</td>" foreach @$_;
        $body .= "</tr>\n";
    }
    $body .= "</table>\n";

    return;
}
_code?><?page
title=><?_code return $title; _code?>
body=><?_code return $body; _code?>
page?>
