<?php
declare(strict_types=1);
// ==================================================
// Nuclear Fancy Pants Edition™ -- NUCLEAR+++
// File: /home/ploi/automarketer-ai.com/public/wp-content/plugins/automarketer-ai/includes/class-review-fetcher.php
// Description: Polls Google Business Profile Reviews API hourly and stores new reviews - NUCLEAR+++
// Last Edited: 2026-05-17
// ==================================================

namespace AutoMarketerAI;

defined('ABSPATH') || exit;

final class ReviewFetcher
{
    // Google Business Profile reviews endpoint (v4)
    private const REVIEWS_API = 'https://mybusiness.googleapis.com/v4';

    // Cron hook
    public const CRON_HOOK = 'amai_review_fetch';

    // Number of reviews to fetch per poll
    private const PAGE_SIZE = 50;

    // --------------------------------------------------
    // Public: register cron interval and hook
    // --------------------------------------------------
    public static function init(): void
    {
        add_action(self::CRON_HOOK, [self::class, 'fetch']);
    }

    // --------------------------------------------------
    // Public: schedule the cron if not already scheduled
    // --------------------------------------------------
    public static function maybeSchedule(): void
    {
        add_filter('cron_schedules', static function (array $schedules): array {
            if (!isset($schedules['amai_hourly'])) {
                $schedules['amai_hourly'] = [
                    'interval' => 3600,
                    'display'  => 'Once Hourly (AutoMarketer AI)',
                ];
            }
            return $schedules;
        });

        if (!wp_next_scheduled(self::CRON_HOOK)) {
            wp_schedule_event(time(), 'amai_hourly', self::CRON_HOOK);
        }
    }

    // --------------------------------------------------
    // Public: unschedule the cron
    // --------------------------------------------------
    public static function unschedule(): void
    {
        $ts = wp_next_scheduled(self::CRON_HOOK);
        if ($ts !== false) {
            wp_unschedule_event($ts, self::CRON_HOOK);
        }
    }

    // --------------------------------------------------
    // Public: fetch reviews from Google and store new ones
    // --------------------------------------------------
    public static function fetch(): void
    {
        if (!GoogleAuth::isConnected()) {
            return;
        }

        $accessToken = GoogleAuth::getAccessToken();
        if ($accessToken === null) {
            return;
        }

        $locationId = GoogleAuth::getLocationId();
        if ($locationId === null || $locationId === '') {
            return;
        }

        $reviews = self::fetchFromApi($accessToken, $locationId);
        if ($reviews === null) {
            return;
        }

        foreach ($reviews as $review) {
            self::storeReview($review);
        }

        // Auto-draft AI responses for new reviews if mode is ai_assisted or autopilot
        $mode = (string) get_option('amai_review_reply_mode', 'ai_assisted');
        if (in_array($mode, ['ai_assisted', 'autopilot'], true)) {
            self::processNewReviews($accessToken, $locationId);
        }
    }

    // --------------------------------------------------
    // Private: call the Google Reviews API
    // --------------------------------------------------
    private static function fetchFromApi(string $accessToken, string $locationId): ?array
    {
        $url = self::REVIEWS_API . '/' . $locationId . '/reviews?pageSize=' . self::PAGE_SIZE . '&orderBy=updateTime+desc';

        $response = wp_remote_get($url, [
            'timeout' => 20,
            'headers' => [
                'Authorization' => 'Bearer ' . $accessToken,
                'Accept'        => 'application/json',
            ],
        ]);

        if (is_wp_error($response)) {
            return null;
        }

        $httpCode = (int) wp_remote_retrieve_response_code($response);
        if ($httpCode !== 200) {
            return null;
        }

        $json = json_decode(wp_remote_retrieve_body($response), true);
        if (!is_array($json) || empty($json['reviews'])) {
            return null;
        }

        return $json['reviews'];
    }

    // --------------------------------------------------
    // Private: store a single review row (upsert)
    // --------------------------------------------------
    private static function storeReview(array $review): void
    {
        global $wpdb;

        $table    = $wpdb->prefix . 'amai_reviews';
        $tenantId = self::getTenantId();

        $reviewId     = (string) ($review['reviewId'] ?? '');
        $reviewerName = (string) ($review['reviewer']['displayName'] ?? '');
        $comment      = isset($review['comment']) && $review['comment'] !== '' ? (string) $review['comment'] : null;
        $starRating   = self::starToInt((string) ($review['starRating'] ?? 'ZERO'));
        $reviewDate   = self::parseDate((string) ($review['createTime'] ?? ''));

        if ($reviewId === '' || $reviewDate === null) {
            return;
        }

        // Skip if already stored
        $exists = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT id FROM {$table} WHERE tenant_id = %s AND review_id = %s LIMIT 1",
                $tenantId,
                $reviewId
            )
        );

        if ($exists !== null) {
            return;
        }

        $wpdb->insert(
            $table,
            [
                'tenant_id'     => $tenantId,
                'review_id'     => $reviewId,
                'reviewer_name' => $reviewerName,
                'star_rating'   => $starRating,
                'comment'       => $comment,
                'review_date'   => $reviewDate,
                'status'        => 'new',
            ],
            ['%s', '%s', '%s', '%d', ($comment !== null ? '%s' : 'NULL'), '%s', '%s']
        );
    }

    // --------------------------------------------------
    // Private: generate AI drafts and autopilot-post for new reviews
    // --------------------------------------------------
    private static function processNewReviews(string $accessToken, string $locationId): void
    {
        global $wpdb;

        $table    = $wpdb->prefix . 'amai_reviews';
        $tenantId = self::getTenantId();
        $mode     = (string) get_option('amai_review_reply_mode', 'ai_assisted');

        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$table} WHERE tenant_id = %s AND status = 'new' AND ai_draft IS NULL ORDER BY review_date DESC LIMIT 20",
                $tenantId
            ),
            ARRAY_A
        );

        if (empty($rows)) {
            return;
        }

        foreach ($rows as $row) {
            $draft = ReviewResponder::generateDraft((int) $row['id']);
            if ($draft === null) {
                continue;
            }

            if ($mode === 'autopilot') {
                ReviewResponder::postReply((int) $row['id'], $draft, $accessToken, $locationId);
            } else {
                // ai_assisted -- draft saved, status -> pending_review, human approves
                $wpdb->update(
                    $table,
                    ['status' => 'pending_review'],
                    ['id' => (int) $row['id']],
                    ['%s'],
                    ['%d']
                );
            }
        }
    }

    // --------------------------------------------------
    // Private: convert Google star rating string to int
    // --------------------------------------------------
    private static function starToInt(string $rating): int
    {
        $map = [
            'ONE'   => 1,
            'TWO'   => 2,
            'THREE' => 3,
            'FOUR'  => 4,
            'FIVE'  => 5,
        ];
        return $map[$rating] ?? 0;
    }

    // --------------------------------------------------
    // Private: parse ISO 8601 date to MySQL DATETIME
    // --------------------------------------------------
    private static function parseDate(string $date): ?string
    {
        if ($date === '') {
            return null;
        }
        $ts = strtotime($date);
        if ($ts === false) {
            return null;
        }
        return gmdate('Y-m-d H:i:s', $ts);
    }

    // --------------------------------------------------
    // Private: tenant ID
    // --------------------------------------------------
    private static function getTenantId(): string
    {
        return (string) get_option('amai_tenant_id', 'default');
    }
}