<?php
/**
 * Dashboard widget: Brainwerk SEO Suite at-a-glance.
 *
 * Designed for the WP Dashboard so a site owner sees the most relevant
 * SEO + analytics signal in 5 seconds without opening the plugin pages.
 *
 * @package Brainwerk SEO Suite
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Seoforge_Dashboard_Widget {

    public static function register( Seoforge_Loader $loader ) {
        $loader->add_action( 'wp_dashboard_setup',         __CLASS__, 'add_widget' );
        $loader->add_action( 'wp_network_dashboard_setup', __CLASS__, 'add_widget' );
    }

    public static function add_widget() {
        // Editors should see the analytics; only admins can take Pro/settings actions.
        if ( ! current_user_can( 'edit_posts' ) ) {
            return;
        }
        wp_add_dashboard_widget(
            'seoforge_overview',
            self::widget_title(),
            array( __CLASS__, 'render' )
        );
    }

    private static function widget_title() {
        $logo = SEOFORGE_URL . 'assets/images/icon-32.png';
        return '<img src="' . esc_url( $logo ) . '" alt="" width="20" height="20" style="vertical-align:middle;margin-right:6px;border-radius:4px;"> '
             . esc_html__( 'Brainwerk SEO Suite — last 7 days', 'brainwerk-seo-suite' );
    }

    public static function render() {
        $scope    = Seoforge_Utils::stats_scope();
        $sum_now  = Seoforge_Stats::summary( 24 * 7, $scope );
        $sum_prev = self::previous_summary( 24 * 7, $scope );
        $live     = Seoforge_Stats::live_visitors( $scope );
        $sources  = Seoforge_Stats::top_sources( 24 * 7, 5, $scope );
        $top      = Seoforge_Stats::top_pages( 24 * 7, 5, $scope );
        $daily    = Seoforge_Stats::visits_daily( 7, $scope );
        $health   = Seoforge_Health::check();
        $score_class = $health['score'] >= 80 ? 'good' : ( $health['score'] >= 50 ? 'ok' : 'bad' );
        $can_admin = current_user_can( 'manage_options' ) || current_user_can( 'manage_network_options' );
        ?>
        <div class="seoforge-widget">
            <div class="seoforge-widget-row seoforge-widget-live">
                <span class="seoforge-pulse"></span>
                <strong><?php echo (int) $live['visitors']; ?></strong>
                <small><?php esc_html_e( 'visitors right now', 'brainwerk-seo-suite' ); ?></small>
                <?php if ( $can_admin ) : ?>
                    <a class="seoforge-widget-pill seoforge-pill-<?php echo esc_attr( $score_class ); ?>"
                       href="<?php echo esc_url( admin_url( 'admin.php?page=brainwerk-seo-suite' ) ); ?>"
                       title="<?php esc_attr_e( 'Setup health', 'brainwerk-seo-suite' ); ?>">
                        <?php echo (int) $health['score']; ?>/100
                    </a>
                <?php endif; ?>
            </div>

            <ul class="seoforge-widget-kpis">
                <?php
                self::kpi_li( __( 'Pageviews', 'brainwerk-seo-suite' ),       (int) $sum_now['visits'],          (int) $sum_prev['visits'] );
                self::kpi_li( __( 'Unique visitors', 'brainwerk-seo-suite' ), (int) $sum_now['unique_visitors'], (int) $sum_prev['unique_visitors'] );
                self::kpi_li( __( 'Sessions', 'brainwerk-seo-suite' ),        (int) $sum_now['sessions'],        (int) $sum_prev['sessions'] );
                self::kpi_li( __( 'Bounce', 'brainwerk-seo-suite' ),          (float) $sum_now['bounce_rate'],   (float) $sum_prev['bounce_rate'], '%', /*invert=*/true );
                ?>
            </ul>

            <?php self::sparkline_with_tooltip( $scope ); ?>

            <div class="seoforge-widget-cols">
                <div>
                    <h4><?php esc_html_e( 'Top pages', 'brainwerk-seo-suite' ); ?></h4>
                    <ol class="seoforge-widget-list">
                        <?php if ( empty( $top ) ) : ?>
                            <li class="seoforge-widget-empty"><?php esc_html_e( 'No traffic yet — share your site!', 'brainwerk-seo-suite' ); ?></li>
                        <?php else : foreach ( $top as $r ) : ?>
                            <li>
                                <a href="<?php echo esc_url( home_url( $r['url_path'] ) ); ?>" target="_blank" rel="noopener">
                                    <?php echo esc_html( wp_html_excerpt( $r['title'] ?: $r['url_path'], 36, '…' ) ); ?>
                                </a>
                                <span class="seoforge-widget-num"><?php echo esc_html( number_format_i18n( (int) $r['hits'] ) ); ?></span>
                            </li>
                        <?php endforeach; endif; ?>
                    </ol>
                </div>
                <div>
                    <h4><?php esc_html_e( 'Top sources', 'brainwerk-seo-suite' ); ?></h4>
                    <ol class="seoforge-widget-list">
                        <?php if ( empty( $sources ) ) : ?>
                            <li class="seoforge-widget-empty"><?php esc_html_e( '—', 'brainwerk-seo-suite' ); ?></li>
                        <?php else : foreach ( $sources as $s ) : ?>
                            <li>
                                <span class="seoforge-pill seoforge-pill-<?php echo esc_attr( $s['source_type'] ); ?>">
                                    <?php echo esc_html( $s['source_type'] ); ?>
                                </span>
                                <?php echo esc_html( wp_html_excerpt( $s['source_name'] ?: '—', 22, '…' ) ); ?>
                                <span class="seoforge-widget-num"><?php echo esc_html( number_format_i18n( (int) $s['hits'] ) ); ?></span>
                            </li>
                        <?php endforeach; endif; ?>
                    </ol>
                </div>
            </div>

            <div class="seoforge-widget-actions">
                <a href="<?php echo esc_url( admin_url( 'admin.php?page=brainwerk-seo-suite' ) ); ?>"><?php esc_html_e( 'Open dashboard', 'brainwerk-seo-suite' ); ?></a>
                <a href="<?php echo esc_url( admin_url( 'admin.php?page=brainwerk-seo-suite&tab=seo' ) ); ?>"><?php esc_html_e( 'SEO analyzer', 'brainwerk-seo-suite' ); ?></a>
                <?php if ( $can_admin ) : ?>
                    <a href="<?php echo esc_url( admin_url( 'admin.php?page=brainwerk-seo-suite&tab=not-found' ) ); ?>"><?php esc_html_e( '404 log', 'brainwerk-seo-suite' ); ?></a>
                    <a href="<?php echo esc_url( admin_url( 'admin.php?page=brainwerk-seo-suite&tab=ai' ) ); ?>">✨ AI</a>
                <?php endif; ?>
            </div>
        </div>
        <?php
    }

    private static function kpi_li( $label, $now, $prev, $suffix = '', $invert = false ) {
        $delta = $prev > 0 ? round( ( $now - $prev ) / $prev * 100 ) : ( $now > 0 ? 100 : 0 );
        $up    = $delta > 0;
        $down  = $delta < 0;
        // For "bounce" higher is worse — invert the colour cue.
        $good  = $invert ? $down : $up;
        $bad   = $invert ? $up   : $down;
        $cls   = $good ? 'seoforge-trend-good' : ( $bad ? 'seoforge-trend-bad' : 'seoforge-trend-flat' );
        $arrow = $up ? '↑' : ( $down ? '↓' : '·' );
        $val   = is_float( $now ) ? round( $now, 1 ) : (int) $now;
        ?>
        <li>
            <strong><?php echo esc_html( number_format_i18n( $val ) . $suffix ); ?></strong>
            <span><?php echo esc_html( $label ); ?></span>
            <em class="<?php echo esc_attr( $cls ); ?>"><?php echo esc_html( $arrow . ' ' . abs( $delta ) ); ?>%</em>
        </li>
        <?php
    }

    private static function previous_summary( $hours, $scope = null ) {
        // The Stats class only supports "last N hours" not arbitrary ranges,
        // so we hand-roll the previous-period query against the daily table.
        global $wpdb;
        $days  = max( 1, (int) ceil( $hours / 24 ) );
        $start = gmdate( 'Y-m-d', time() - DAY_IN_SECONDS * ( $days * 2 - 1 ) );
        $end   = gmdate( 'Y-m-d', time() - DAY_IN_SECONDS * $days );
        $tbl   = Seoforge_Utils::table( 'daily' );
        // Keep each prepare() a string literal: per-site vs network-wide branch.
        if ( null !== $scope ) {
            $row = $wpdb->get_row( $wpdb->prepare(
                "SELECT COALESCE(SUM(visits),0) AS visits,
                        COALESCE(SUM(uniques),0) AS uniques,
                        COALESCE(SUM(sessions),0) AS sessions,
                        COALESCE(SUM(bounces),0) AS bounces,
                        COALESCE(SUM(duration_sum),0) AS duration_sum
                 FROM %i WHERE blog_id = %d AND day >= %s AND day < %s",
                $tbl, (int) $scope, $start, $end
            ), ARRAY_A );
        } else {
            $row = $wpdb->get_row( $wpdb->prepare(
                "SELECT COALESCE(SUM(visits),0) AS visits,
                        COALESCE(SUM(uniques),0) AS uniques,
                        COALESCE(SUM(sessions),0) AS sessions,
                        COALESCE(SUM(bounces),0) AS bounces,
                        COALESCE(SUM(duration_sum),0) AS duration_sum
                 FROM %i WHERE day >= %s AND day < %s",
                $tbl, $start, $end
            ), ARRAY_A );
        }
        $sessions = (int) ( $row['sessions'] ?? 0 );
        $bounces  = (int) ( $row['bounces'] ?? 0 );
        return array(
            'visits'          => (int) ( $row['visits'] ?? 0 ),
            'unique_visitors' => (int) ( $row['uniques'] ?? 0 ),
            'sessions'        => $sessions,
            'bounce_rate'     => $sessions > 0 ? round( ( $bounces / $sessions ) * 100, 1 ) : 0.0,
        );
    }

    /**
     * Interactive 7-day sparkline with hoverable tooltip per day.
     * The tooltip shows the date, total visits, and the breakdown by source-type.
     * Pure SVG + a tiny jQuery handler in admin.js. No charting library.
     */
    private static function sparkline_with_tooltip( $scope = null ) {
        $data = Seoforge_Stats::visits_daily_by_source( 7, $scope );
        if ( count( $data ) < 2 ) {
            return;
        }
        $values = wp_list_pluck( $data, 'total' );
        $max    = max( max( $values ), 1 );
        // viewBox ratio matches typical widget width (~360 wide × 110 tall),
        // and the SVG keeps that aspect with preserveAspectRatio (no stretch).
        $w      = 360;
        $h      = 110;
        $pad_x  = 14;
        $top    = 10;
        $axis_h = 22;
        $chart_h = $h - $axis_h;
        $step   = count( $values ) > 1 ? ( $w - 2 * $pad_x ) / ( count( $values ) - 1 ) : 0;

        $points    = array();
        $point_xy  = array();
        foreach ( $values as $i => $v ) {
            $x = $pad_x + ( $i * $step );
            $y = $top + ( ( $chart_h - $top - 4 ) * ( 1 - ( $v / $max ) ) );
            $point_xy[] = array( round( $x, 1 ), round( $y, 1 ) );
            $points[]   = round( $x, 1 ) . ',' . round( $y, 1 );
        }
        $line = implode( ' ', $points );
        $area = $point_xy[0][0] . ',' . $chart_h . ' ' . $line . ' ' . end( $point_xy )[0] . ',' . $chart_h;
        $tooltip_data = wp_json_encode( $data );
        ?>
        <div class="seoforge-spark-wrap" data-days="<?php echo esc_attr( $tooltip_data ); ?>">
            <svg class="seoforge-widget-sparkline" viewBox="0 0 <?php echo (int) $w; ?> <?php echo (int) $h; ?>"
                 preserveAspectRatio="xMidYMid meet" role="img" aria-label="<?php esc_attr_e( '7-day visits', 'brainwerk-seo-suite' ); ?>">
                <defs>
                    <linearGradient id="sf-spark-fill" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stop-color="#2563eb" stop-opacity="0.35"/>
                        <stop offset="100%" stop-color="#2563eb" stop-opacity="0"/>
                    </linearGradient>
                </defs>
                <polygon points="<?php echo esc_attr( $area ); ?>" fill="url(#sf-spark-fill)"/>
                <polyline points="<?php echo esc_attr( $line ); ?>" fill="none" stroke="#2563eb"
                          stroke-width="2" stroke-linejoin="round" stroke-linecap="round"/>
                <?php
                foreach ( $point_xy as $i => $p ) {
                    $label = mysql2date( 'd.m.', $data[ $i ]['day'] );
                    ?>
                    <circle class="sf-spark-dot" cx="<?php echo esc_attr( $p[0] ); ?>" cy="<?php echo esc_attr( $p[1] ); ?>"
                            r="3.5" fill="#2563eb" data-i="<?php echo (int) $i; ?>"/>
                    <text x="<?php echo esc_attr( $p[0] ); ?>" y="<?php echo (int) ( $h - 6 ); ?>"
                          text-anchor="middle" font-size="11" fill="#6b7280" font-family="sans-serif">
                        <?php echo esc_html( $label ); ?>
                    </text>
                    <?php
                    // Wide invisible hover target — covers half-step on either side
                    $tx = max( 0, $p[0] - ( $step / 2 ) );
                    $tw = $step;
                    if ( 0 === $i ) { $tx = 0; $tw = $p[0] + ( $step / 2 ); }
                    if ( $i === count( $point_xy ) - 1 ) { $tw = $w - $tx; }
                    ?>
                    <rect class="sf-spark-hover" x="<?php echo esc_attr( $tx ); ?>" y="0"
                          width="<?php echo esc_attr( $tw ); ?>" height="<?php echo (int) $chart_h; ?>"
                          fill="transparent" data-i="<?php echo (int) $i; ?>"/>
                    <?php
                }
                ?>
            </svg>
            <div class="seoforge-spark-tooltip" style="display:none"></div>
        </div>
        <?php
    }
}
