<?php
/**
 * PMM Cloud Client — Calls our central Supabase proxy
 *
 * This client acts as an intermediary, routing requests to our central
 * server which then calls AI providers like OpenRouter.
 *
 * @package PackshotPhotoAI
 */

namespace PackshotPhotoAI\API;

use PackshotPhotoAI\Core\Logger;
use PackshotPhotoAI\Core\Encryption;

defined('ABSPATH') || exit;

/**
 * Handles communication with the Pro Media Manager cloud service
 */
class CloudClient implements ClientInterface {

    /**
     * Supabase Edge Function URL — SEO generation (vision)
     */
    private const CLOUD_URL = 'https://duubkqjowabuevqudtbk.supabase.co/functions/v1/generate-seo';

    /**
     * Request timeout in seconds
     */
    private const TIMEOUT = 60;

    /**
     * @var string License / API Key
     */
    private string $api_key;

    /**
     * Constructor
     * 
     * @param string $api_key Optional API key for testing
     */
    public function __construct(string $api_key = '') {
        $this->api_key = !empty($api_key) ? $api_key : Encryption::decrypt(get_option('packshotphoto_api_key', ''));
    }

    /**
     * Test API connection — validates key directly against Supabase
     *
     * @return array{success: bool, message: string}
     */
    public function test_connection(): array {
        if ( empty( $this->api_key ) ) {
            return [
                'success' => false,
                'message' => __( 'Please connect to our service in the Credits & Billing section first.', 'packshotphoto-ai' ),
            ];
        }

        $validate_url = 'https://duubkqjowabuevqudtbk.supabase.co/functions/v1/license-validate';
        $response = wp_remote_post( $validate_url, [
            'timeout'   => 10,
            'headers'   => [ 'Content-Type' => 'application/json' ],
            'sslverify' => false,
            'body'      => wp_json_encode( [
                'api_key'  => $this->api_key,
                'site_url' => home_url(),
            ] ),
        ] );

        if ( is_wp_error( $response ) ) {
            return [
                'success' => false,
                'message' => __( 'Cannot reach PackshotPhoto AI servers: ', 'packshotphoto-ai' ) . $response->get_error_message(),
            ];
        }

        $code = wp_remote_retrieve_response_code( $response );
        $body = json_decode( wp_remote_retrieve_body( $response ), true );

        if ( ! empty( $body['valid'] ) ) {
            $balance = (int) ( $body['credits_balance'] ?? 0 );
            // Cache locally
            update_option( 'packshotphoto_credits_balance', $balance );
            return [
                'success' => true,
                'message' => sprintf(
                    /* translators: %d: credit balance */
                    __( 'Connection successful! Balance: %d credits.', 'packshotphoto-ai' ),
                    $balance
                ),
            ];
        }

        $error = $body['error'] ?? ( $body['message'] ?? __( 'Invalid API key or server error.', 'packshotphoto-ai' ) );
        return [
            'success' => false,
            'message' => $error,
        ];
    }

    /**
     * Generate SEO description for media file
     *
     * @param string $file_path Absolute path to file
     * @param string $mime_type MIME type
     * @param int    $post_id   Optional attachment ID
     * @param string $language  Optional target language override
     * @return array{success: bool, message?: string, data?: array}
     */
    public function generate_seo_description(string $file_path, string $mime_type, int $post_id = 0, string $language = '', string $image_context = ''): array {
        if (empty($this->api_key)) {
            // Auto-provision a free API key inline if not saved yet
            $sync = \PackshotPhotoAI\Core\CreditManager::force_sync();
            if ($sync['success']) {
                $this->api_key = \PackshotPhotoAI\Core\Encryption::decrypt(get_option('packshotphoto_api_key', ''));
            }
        }

        if (empty($this->api_key)) {
            return [
                'success' => false,
                'message' => __('Missing Connection to PackshotPhoto AI. Please connect to our service in the Credits & Billing section.', 'packshotphoto-ai'),
                'connection_error' => true,
            ];
        }

        $file_data = @file_get_contents($file_path);
        if (false === $file_data) {
            return ['success' => false, 'message' => __('Cannot read file', 'packshotphoto-ai')];
        }

        $base64_data = base64_encode($file_data);
        $language    = (!empty($language) && 'auto' !== $language) ? $language : $this->get_language();
        $lang_name   = $this->map_language_name($language);
        $prompt      = $this->build_seo_prompt($lang_name, $image_context);

        $payload = [
            'api_key'     => $this->api_key,
            'site_url'    => home_url(),
            'image_data'  => $base64_data,
            'mime_type'   => $mime_type,
            'prompt'      => $prompt,
            'model'       => 'google/gemma-4-26b-a4b-it',
            'temperature' => 0.9,
        ];

        Logger::debug('CloudClient: Sending request to PMM Cloud', ['url' => self::CLOUD_URL]);

        $response = wp_remote_post(self::CLOUD_URL, [
            'headers'   => [
                'Content-Type' => 'application/json',
            ],
            'body'      => wp_json_encode($payload),
            'timeout'   => self::TIMEOUT,
            'sslverify' => false,
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => $response->get_error_message(),
                'connection_error' => true,
            ];
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        if ($code !== 200) {
            $error = $body['error'] ?? __('Cloud API Error', 'packshotphoto-ai');
            $is_credits = ($code === 402 || strpos(strtolower($error), 'credit') !== false || strpos(strtolower($error), 'kredyt') !== false);
            return [
                'success' => false,
                'message' => $error,
                'credit_error' => $is_credits,
                'connection_error' => !$is_credits,
            ];
        }

        return [
            'success' => true,
            'message' => __('SEO metadata generated via PackshotPhoto AI Cloud.', 'packshotphoto-ai'),
            'data'    => is_array($body['data'] ?? null) ? $body['data'] : [],
        ];
    }

    /**
     * Summarize site context
     *
     * @param string $text
     * @param string $language Optional target language override
     * @return array
     */
    public function summarize_site_context(string $text, string $language = ''): array {
        if (empty($this->api_key)) {
            // Auto-provision a free API key inline if not saved yet
            $sync = \PackshotPhotoAI\Core\CreditManager::force_sync();
            if ($sync['success']) {
                $this->api_key = \PackshotPhotoAI\Core\Encryption::decrypt(get_option('packshotphoto_api_key', ''));
            }
        }

        if (empty($this->api_key)) {
            return [
                'success' => false,
                'message' => __('Missing Connection to PackshotPhoto AI. Please connect to our service in the Credits & Billing section.', 'packshotphoto-ai'),
            ];
        }

        $language  = (!empty($language) && 'auto' !== $language) ? $language : $this->get_language();
        $lang_name = $this->map_language_name($language);

        $prompt = sprintf(
            '### STRICT LANGUAGE MANDATE:
- You MUST reply ONLY in %1$s.
- This is a critical requirement.
- Even if the website content below is in another language, your summary MUST be in %1$s.

Analyze the following website content and write a SHORT description (2-3 sentences) explaining what this company/website does.
This description will be used as SEO context.

Website content:
%2$s',
            $lang_name,
            mb_substr($text, 0, 3000)
        );

        $payload = [
            'api_key'   => $this->api_key,
            'site_url'  => home_url(),
            'mode'      => 'text',
            'prompt'    => $prompt,
            'model'     => 'google/gemma-3-12b-it',
        ];

        Logger::debug('CloudClient: Sending summarize_site_context request', ['url' => self::CLOUD_URL]);

        $response = wp_remote_post(self::CLOUD_URL, [
            'headers'   => ['Content-Type' => 'application/json'],
            'body'      => wp_json_encode($payload),
            'timeout'   => 30,
            'sslverify' => false,
        ]);

        if (is_wp_error($response)) {
            Logger::error('CloudClient: summarize_site_context WP error', ['error' => $response->get_error_message()]);
            return ['success' => false, 'message' => $response->get_error_message()];
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        Logger::debug('CloudClient: summarize_site_context response', ['code' => $code, 'body' => $body]);

        if ($code !== 200) {
            $error = $body['error'] ?? __('Cloud API Error', 'packshotphoto-ai');
            return ['success' => false, 'message' => $error];
        }

        // Edge function returns data as parsed JSON or plain string depending on model output
        $result = '';
        if (!empty($body['data'])) {
            $result = is_string($body['data']) ? $body['data'] : (json_encode($body['data']) ?: '');
        } elseif (!empty($body['text'])) {
            $result = $body['text'];
        } elseif (!empty($body['success']) && is_string($body['message'] ?? null)) {
            $result = $body['message'];
        }

        if (empty($result)) {
            return ['success' => false, 'message' => __('Empty response from AI.', 'packshotphoto-ai')];
        }

        return [
            'success' => true,
            'message' => __('Site context summarized successfully.', 'packshotphoto-ai'),
            'data'    => trim($result),
        ];
    }

    /**
     * Get target language
     */
    private function get_language(): string {
        $settings = get_option('packshotphoto_settings', []);
        $lang     = $settings['language'] ?? 'auto';
        return ($lang === 'auto') ? get_locale() : $lang;
    }

    /**
     * Build the standard SEO prompt
     */
    private function build_seo_prompt(string $language, string $image_context = ''): string {
        $lang_instruction = "### LANGUAGE MANDATE (CRITICAL):
- All generated fields ('slug', 'alt', 'caption', 'desc') MUST be written in: {$language}
- You must write natively and naturally in that target language. Even if the website context or prompts below are in English, your entire JSON response fields must be in {$language}. Do not translate field names (keys), only the values.";

        $site_context     = get_option('packshotphoto_site_context', '');
        $context_keywords = '';
        if (!empty($site_context)) {
            $context_keywords = '
 
### INDUSTRY CONTEXT (use as inspiration for tone, style, and terminology):
' . $site_context;
        }

        $image_context_section = '';
        if (!empty($image_context)) {
            $image_context_section = '
 
### SPECIFIC IMAGE CONTEXT (user-provided — you MUST incorporate these facts or style directions in the generated metadata):
' . $image_context;
        }

        // Editorial angle rotation — forces model to vary perspective per image
        $angles = [
            'materials, finish and craftsmanship',
            'setting, backdrop and overall atmosphere',
            'practical use and placement in everyday life',
            'design style and what it pairs with',
            'color palette, lighting and composition',
            'proportions, scale and form',
        ];
        $angle_block = sprintf(
            "\n### EDITORIAL ANGLE FOR THIS IMAGE:\nEmphasize: %s. Build the caption and desc around this angle, staying truthful to what is visible.\n",
            $angles[array_rand($angles)]
        );

        // Recent openers memory — prevent repetitive openings
        $recent       = (array) get_option('packshotphoto_recent_openers', []);
        $recent_block = '';
        if (!empty($recent)) {
            $recent_block = "\n### RECENTLY USED OPENINGS — do NOT reuse or closely paraphrase any of them:\n";
            foreach (array_slice($recent, -30) as $opener) {
                $recent_block .= '- ' . $opener . "\n";
            }
        }

        return $lang_instruction . '
 
You are an Image Metadata Specialist. Your task is to perform a detailed visual analysis of the provided image and generate factual, search-optimized metadata.
' . $context_keywords . $image_context_section . $angle_block . $recent_block . '
 
⚠️ BANNED PATTERNS (NEVER use — in ANY language):
- Imperative/promotional phrases: "Elevate your…", "Transform your…", "Enhance your…", "Discover…", "Experience…", "Add a touch of…"
- Template phrases: "featuring…", "with this…", "perfect for…", "ideal for…"
- Photo-referencing phrases: "professional photography", "studio photo", "presents", "shows", "the photo depicts", "the image shows", "product photography"
- Any second-person address ("your", "you") or calls to action
- Any references to the process of taking the photo or the studio
 
⚠️ BALANCED CONTEXT ALIGNMENT (CRITICAL):
- Your absolute priority is to describe the visual elements and objects actually present in the image. Do not invent or force industry terms if they have no visual connection to the image.
- Use the INDUSTRY CONTEXT as a guide for tone, vocabulary style, and to resolve ambiguous visual scenes.
- If the image shows a neutral or unrelated subject (e.g., a cup of coffee, a flower, a book), describe that subject naturally. Do NOT force-feed industry keywords.
- Ensure each image gets unique, natural metadata.
 
### FIELD-SPECIFIC SEO RULES:
 
### 1. SLUG (URL & Physical Filename SEO)
- This slug will be used directly to rename the image file on the server.
- Max 60 characters, only lowercase a-z, 0-9, and hyphens (-).
- Must contain 3 to 5 highly relevant keywords. Never use underscores or spaces.
- No special characters, diacritics, or accents (normalize them, e.g. "ł" -> "l", "ó" -> "o").
- Exclude all stop words and conjunctions (e.g. and, or, in, na, z, do, dla).
- Format: [primary-keyword]-[secondary-keyword]-[context]
 
### 2. ALT (Accessibility & Image Search)
- Max 125 characters. Crucial for screen readers and search engine indexers.
- START DIRECTLY with the specific visible object, color, material, and context (e.g. "Skórzane brązowe buty męskie na drewnianym tle").
- Never use intros like "photo of" or "image showing".
- Describe only what is clearly visible. Do not guess unseen attributes.
 
### 3. CAPTION (Page Content Placement)
- 80-130 characters, exactly 1 sentence.
- Before writing, identify 3 visual details unique to THIS image (e.g. specific color, texture, shape, arrangement). Weave at least 2 of them into the sentence.
- Write a factual, editorial observation — as if a journalist is describing the scene for a print article.
- NEVER start with an article ("A", "The") or a gerund ("Featuring", "Showcasing"). Start with a concrete noun, adjective, or the object name.
- Must NOT overlap with ALT text by more than 3 words.
 
### 4. DESC (Rich Search Snippet / Meta Description)
- 200-320 characters, 2-3 sentences.
- Sentence 1: Describe the primary subject with 2-3 physical attributes not mentioned in ALT or CAPTION (material, dimensions, texture, condition, spatial relationship).
- Sentence 2: State a factual, observable detail about setting, context, or composition.
- Sentence 3 (optional): A neutral, informational note about typical use or category — no promotional language.
- NEVER use imperative mood, second person ("your"), or benefit claims ("perfect for", "ideal for", "adds elegance").
- Must have zero text duplication with the alt or caption fields.
 
### EXPECTED OUTPUT FORMAT:
You must return ONLY a valid JSON object. Do not wrap in markdown code blocks, do not write any pre-text or post-text.
 
JSON structure template:
{
  "slug": "optimized-image-slug",
  "alt": "Alt text in the target language starting with the object",
  "caption": "A single editorial sentence in the target language.",
  "desc": "A detailed 2-3 sentence factual SEO description in the target language."
}';
    }

    /**
     * Map language code or locale to full language name
     *
     * @param string $language Code (e.g., 'pl', 'en_US')
     * @return string
     */
    private function map_language_name(string $language): string {
        $language = strtolower($language);
        
        $map = [
            'pl' => 'Polish',
            'en' => 'English',
            'es' => 'Spanish',
            'de' => 'German',
            'fr' => 'French',
            'it' => 'Italian',
            'pt' => 'Portuguese',
            'nl' => 'Dutch',
            'ru' => 'Russian',
            'zh' => 'Chinese (Simplified)',
            'ja' => 'Japanese',
            'ko' => 'Korean',
        ];

        // Try exact match first
        if (isset($map[$language])) {
            return $map[$language];
        }

        // Try prefix (e.g., 'pl_PL' -> 'pl')
        $prefix = substr($language, 0, 2);
        return $map[$prefix] ?? 'English';
    }
}
