<?php
/**
 * Demo-data seeder. Generates plausible visit + session rows so a fresh
 * install can show off the dashboard before any real traffic hits.
 *
 * @package Brainwerk SEO Suite
 */

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

class Seoforge_Demo {

    private static $sources = array(
        array( 'search', 'Google',     'https://www.google.com/' ),
        array( 'search', 'Google',     'https://www.google.com/' ),
        array( 'search', 'Bing',       'https://www.bing.com/' ),
        array( 'search', 'DuckDuckGo', 'https://duckduckgo.com/' ),
        array( 'social', 'X / Twitter','https://twitter.com/' ),
        array( 'social', 'LinkedIn',   'https://www.linkedin.com/' ),
        array( 'social', 'Facebook',   'https://www.facebook.com/' ),
        array( 'referral', 'news.example.com', 'https://news.example.com/article' ),
        array( 'direct', 'Direct',     '' ),
        array( 'direct', 'Direct',     '' ),
    );

    private static $devices = array(
        array( 'desktop', 'Chrome',  'Windows' ),
        array( 'desktop', 'Firefox', 'macOS' ),
        array( 'desktop', 'Safari',  'macOS' ),
        array( 'mobile',  'Safari',  'iOS' ),
        array( 'mobile',  'Chrome',  'Android' ),
        array( 'mobile',  'Chrome',  'Android' ),
        array( 'tablet',  'Safari',  'iOS' ),
    );

    // Country => list of [ region, city ] pairs, so the Pro region/city
    // drill-down has realistic, internally-consistent demo data.
    private static $geo = array(
        'AT' => array( array( 'Vienna', 'Vienna' ), array( 'Lower Austria', 'Sankt Pölten' ), array( 'Styria', 'Graz' ), array( 'Upper Austria', 'Linz' ), array( 'Tyrol', 'Innsbruck' ), array( 'Salzburg', 'Salzburg' ) ),
        'DE' => array( array( 'Bavaria', 'Munich' ), array( 'Berlin', 'Berlin' ), array( 'Hesse', 'Frankfurt' ), array( 'Hamburg', 'Hamburg' ), array( 'North Rhine-Westphalia', 'Cologne' ) ),
        'CH' => array( array( 'Zurich', 'Zürich' ), array( 'Geneva', 'Geneva' ), array( 'Bern', 'Bern' ) ),
        'US' => array( array( 'California', 'San Francisco' ), array( 'New York', 'New York' ), array( 'Texas', 'Austin' ) ),
        'GB' => array( array( 'England', 'London' ), array( 'Scotland', 'Edinburgh' ) ),
        'FR' => array( array( 'Île-de-France', 'Paris' ), array( 'Auvergne-Rhône-Alpes', 'Lyon' ) ),
        'IT' => array( array( 'Lazio', 'Rome' ), array( 'Lombardy', 'Milan' ) ),
        'NL' => array( array( 'North Holland', 'Amsterdam' ), array( 'South Holland', 'Rotterdam' ) ),
        'PL' => array( array( 'Masovia', 'Warsaw' ) ),
        'CZ' => array( array( 'Prague', 'Prague' ) ),
    );

    // Weighted country picks (AT/DE dominate, matching a DACH-region audience).
    private static $country_weights = array( 'AT', 'AT', 'AT', 'DE', 'DE', 'CH', 'US', 'GB', 'FR', 'IT', 'NL', 'PL', 'CZ' );

    private static $sample_paths = array(
        array( '/', 'Home' ),
        array( '/about/', 'About us' ),
        array( '/blog/', 'Blog' ),
        array( '/blog/seo-tips-2026/', '10 SEO tips for 2026' ),
        array( '/blog/wordpress-privacy/', 'WordPress + privacy' ),
        array( '/contact/', 'Contact' ),
        array( '/pricing/', 'Pricing' ),
        array( '/docs/getting-started/', 'Getting started' ),
        array( '/docs/multisite/', 'Multisite setup' ),
    );

    public static function seed( $days = 14, $per_day = 200 ) {
        global $wpdb;
        $tbl  = Seoforge_Utils::table( 'visits' );
        $blog = Seoforge_Utils::current_blog_id();
        $count = 0;

        for ( $d = $days - 1; $d >= 0; $d-- ) {
            // Slight day-of-week curve: weekends ~70% of weekdays.
            $base = $per_day;
            $dow  = (int) gmdate( 'N', time() - DAY_IN_SECONDS * $d );
            if ( $dow >= 6 ) { $base = (int) ( $base * 0.7 ); }
            $target = max( 5, $base + random_int( -20, 20 ) ); // pageviews to emit this day

            $day_anchor = strtotime( gmdate( 'Y-m-d 00:00:00', time() - DAY_IN_SECONDS * $d ) );
            // For "today" we cap the random second at the current second so
            // demo visits never end up with future timestamps (which would
            // pollute the live-visitors counter and other recent-window stats).
            $upper = ( 0 === $d ) ? max( 60, time() - $day_anchor - 60 ) : DAY_IN_SECONDS - 1;

            // Emit whole SESSIONS (a visitor landing, then browsing a few pages)
            // rather than independent pageviews, so bounce rate, pages/session
            // and unique-visitor counts come out realistic instead of every
            // session looking like a single-page bounce.
            $emitted = 0;
            while ( $emitted < $target ) {
                // Pages in this session: ~42% bounce (1 page), most 2-3, a tail of 4-6.
                $r  = random_int( 1, 100 );
                $pv = $r <= 42 ? 1 : ( $r <= 78 ? random_int( 2, 3 ) : random_int( 4, 6 ) );
                $pv = max( 1, min( $pv, $target - $emitted ) ); // never overshoot the day target

                // Session-level attributes (constant across its pageviews).
                $src    = self::$sources[ array_rand( self::$sources ) ];
                $dev    = self::$devices[ array_rand( self::$devices ) ];
                $cty    = self::$country_weights[ array_rand( self::$country_weights ) ];
                $place  = self::$geo[ $cty ][ array_rand( self::$geo[ $cty ] ) ];
                $region = $place[0];
                $city   = $place[1];
                $is_bot = random_int( 1, 100 ) <= 9 ? 1 : 0;
                $is_new = random_int( 1, 100 ) <= 58 ? 1 : 0;
                $term   = 'search' === $src[0] ? self::demo_search_term() : '';
                $sid    = md5( 'demo-' . $blog . '-' . $d . '-' . $emitted . '-' . random_int( 1, 0x7fffffff ) );
                // New visitors get a unique hash; returning ones reuse a small
                // pool so uniques < sessions (people coming back).
                $vhash  = $is_new
                    ? sha1( 'demo-new-' . $blog . '-' . $d . '-' . $emitted )
                    : sha1( 'demo-ret-' . $blog . '-' . random_int( 0, 400 ) );

                $t = random_int( 0, max( 1, $upper - 1 ) ); // session start second
                for ( $k = 0; $k < $pv; $k++ ) {
                    if ( $k > 0 ) {
                        $t = min( $upper, $t + random_int( 5, 180 ) ); // time spent on previous page
                    }
                    $when = gmdate( 'Y-m-d H:i:s', $day_anchor + $t );
                    $page = self::$sample_paths[ array_rand( self::$sample_paths ) ];
                    $dur  = $is_bot ? random_int( 0, 4 ) : random_int( 8, 240 );
                    // Engaged = human session that is non-trivial (multi-page or dwelled).
                    $is_engaged = ( ! $is_bot && ( $pv > 1 || $dur >= 15 ) ) ? 1 : 0;
                    // Core Web Vitals only for human hits (bots don't run the JS beacon).
                    $lcp = $is_bot ? null : random_int( 900, 3600 );
                    $cls = $is_bot ? null : random_int( 0, 180 );
                    $inp = $is_bot ? null : random_int( 40, 420 );
                    // The referrer applies to the entry (landing) pageview; deeper
                    // pages in the session are internal navigation.
                    $is_entry = ( 0 === $k );
                    $ref_url  = $is_entry ? $src[2] : '';

                    $row = array(
                        'blog_id'        => $blog,
                        'session_id'     => $sid,
                        'visitor_hash'   => $vhash,
                        'post_id'        => 0,
                        'url'            => 'https://demo.local' . $page[0],
                        'url_path'       => $page[0],
                        'title'          => $page[1],
                        'referrer_url'   => $ref_url,
                        'referrer_host'  => $ref_url ? wp_parse_url( $ref_url, PHP_URL_HOST ) : '',
                        'source_type'    => $src[0],
                        'source_name'    => $src[1],
                        'search_term'    => $is_entry ? $term : '',
                        'utm_source'     => null,
                        'utm_medium'     => null,
                        'utm_campaign'   => null,
                        'utm_term'       => null,
                        'utm_content'    => null,
                        'ip_anon'        => '203.0.113.0',
                        'country'        => $cty,
                        'region'         => $region,
                        'city'           => $city,
                        'user_agent'     => 'demo',
                        'device_type'    => $dev[0],
                        'browser'        => $dev[1],
                        'os'             => $dev[2],
                        'is_bot'         => $is_bot,
                        'duration_sec'   => $dur,
                        'is_new_visitor' => ( $is_entry ? $is_new : 0 ),
                        'is_engaged'     => $is_engaged,
                        'lcp_ms'         => $lcp,
                        'cls_x1000'      => $cls,
                        'inp_ms'         => $inp,
                        'status_code'    => 200,
                        'created_at'     => $when,
                    );
                    $wpdb->insert( $tbl, $row );
                    $count++;
                    $emitted++;
                }
            }
        }
        return $count;
    }

    public static function purge() {
        global $wpdb;
        $tbl = Seoforge_Utils::table( 'visits' );
        return (int) $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE user_agent = %s", $tbl, 'demo' ) );
    }

    private static function demo_search_term() {
        $terms = array( 'wordpress seo', 'gdpr analytics', 'plugin sitemap', 'redirect manager', 'open graph schema', 'multisite seo' );
        return $terms[ array_rand( $terms ) ];
    }
}
