#!/usr/bin/env php
<?php

declare(strict_types=1);

require_once __DIR__ . '/../lib/Env.php';
require_once __DIR__ . '/../lib/Db.php';
require_once __DIR__ . '/../lib/Logger.php';
require_once __DIR__ . '/../lib/OpenAIClient.php';
require_once __DIR__ . '/../lib/Mailer.php';

Env::load(__DIR__ . '/../.env');

$options = getopt('', ['topic:']);
$topic = trim($options['topic'] ?? '');

if ($topic === '') {
    echo "Usage: php scripts/generate_blog.php --topic=\"Your topic\"\n";
    exit(1);
}

Logger::log('info', 'Starting generation for topic: ' . $topic);

$brandPack = loadGuidance(__DIR__ . '/../storage/brand_pack.txt');
$voicePack = loadGuidance(__DIR__ . '/../storage/voice_pack.txt');
$guidanceSystemText = buildGuidanceSystemText($brandPack, $voicePack);

$db = Db::getConnection();
$draftId = null;

try {
    $db->beginTransaction();

    $insert = $db->prepare('INSERT INTO drafts (topic, status, created_at, updated_at) VALUES (:topic, :status, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)');
    $insert->execute([
        ':topic' => $topic,
        ':status' => 'pending_approval',
    ]);
    $draftId = (int)$db->lastInsertId();

    $openAI = new OpenAIClient();
    $textModel = Env::get('OPENAI_MODEL', 'gpt-4o-2024-08-06');
    Logger::log('info', 'Generating text content with model: ' . $textModel);

    $systemPrompt = 'You are a helpful marketing writer. Provide SEO-ready blog copy in JSON with the fields title, slug, meta_description, and content_html.' . $guidanceSystemText;
    $messages = [
        [
            'role' => 'system',
            'content' => $systemPrompt,
        ],
        [
            'role' => 'user',
            'content' => sprintf(
                "Create an 800-1200 word blog on \"%s\". Use headings, short paragraphs, bullet lists, a FAQ section, and a CTA at the end. Return valid JSON that includes the requested fields, uses kebab-case for the slug, keeps the meta description at or below 160 characters, and wraps content_html in semantic HTML tags (h1-h3, p, ul/ol, strong).",
                $topic
            ),
        ],
    ];

    $schema = [
        'type' => 'object',
        'additionalProperties' => false,
        'properties' => [
            'title' => ['type' => 'string'],
            'slug' => ['type' => 'string'],
            'meta_description' => ['type' => 'string'],
            'content_html' => ['type' => 'string'],
        ],
        'required' => ['title', 'slug', 'meta_description', 'content_html'],
    ];

    $payload = $openAI->chatCompletionJson($messages, $schema, ['temperature' => 0.3, 'max_tokens' => 1500, 'model' => $textModel]);

    $title = trim($payload['title'] ?? '');
    $slug = trim($payload['slug'] ?? '');
    $metaDescription = trim($payload['meta_description'] ?? '');
    $contentHtml = trim($payload['content_html'] ?? '');

    if ($title === '' || $contentHtml === '') {
        throw new RuntimeException('OpenAI response missing title or content');
    }

    if ($slug === '') {
        $slug = createSlug($title);
    }

    $metaDescription = mb_substr($metaDescription, 0, 160);
    $metaDescription = $metaDescription !== '' ? $metaDescription : $title;

    Logger::log('info', "Generated initial content for draft {$draftId}");

    $editorialEnabled = filter_var(Env::get('EDITORIAL_PASS_ENABLED', 'false'), FILTER_VALIDATE_BOOLEAN);
    if ($editorialEnabled) {
        $editorialModel = Env::get('EDITORIAL_MODEL', $textModel);
        $editorialTemperature = (float)Env::get('EDITORIAL_TEMPERATURE', '0.7');
        Logger::log('info', 'Running editorial pass with model: ' . $editorialModel);

        $editorialSystemPrompt = 'You are an editorial assistant focused on clarity, specificity, and a natural tone. Rewrite content_html (and optionally title/meta_description) without changing meaning or structure, remove clichés, and add practical examples. Do not invent new factual claims, statistics, or case studies.' . $guidanceSystemText;

        $editorialMessages = [
            [
                'role' => 'system',
                'content' => $editorialSystemPrompt,
            ],
            [
                'role' => 'user',
                'content' => <<<MSG
Current draft:
Title: {$title}
Slug: {$slug}
Meta description: {$metaDescription}
Content HTML:
{$contentHtml}
Rewrite only content_html (and update title/meta_description only if it is strictly improving clarity) while keeping headings, lists, and the CTA intact. Preserve meaning, avoid invented facts or data, and deliver human readability.
MSG,
            ],
        ];

        $editorialSchema = [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'title' => ['type' => 'string'],
                'slug' => ['type' => 'string'],
                'meta_description' => ['type' => 'string'],
                'content_html' => ['type' => 'string'],
            ],
            'required' => ['title', 'slug', 'meta_description', 'content_html'],
        ];

        $editorialResponse = $openAI->chatCompletionJson($editorialMessages, $editorialSchema, [
            'model' => $editorialModel,
            'temperature' => $editorialTemperature,
            'max_tokens' => 1500,
        ]);

        if (!empty($editorialResponse['title'])) {
            $title = trim($editorialResponse['title']);
        }

        if (!empty($editorialResponse['slug'])) {
            $slug = trim($editorialResponse['slug']);
        }

        if (!empty($editorialResponse['meta_description'])) {
            $metaDescription = mb_substr(trim($editorialResponse['meta_description']), 0, 160);
        }

        $contentHtml = trim($editorialResponse['content_html']);
        Logger::log('info', "Editorial pass completed for draft {$draftId}");
    }

    $imagePromptStyle = Env::get('IMAGE_PROMPT_STYLE', 'premium');
    $imageSubject = Env::get('IMAGE_SUBJECT', 'smart community infrastructure');
    $imagePrompt = sprintf(
        'Modern South African community with smart infrastructure, digital dashboards, and utilities (smart metering) as a %s illustration for "%s". Clean, premium, minimal corporate tech design, soft light, no text/logos/watermarks, strong subject with ample negative space and blog-featured-image framing.',
        $imagePromptStyle,
        $topic
    );
    if ($imageSubject !== '') {
        $imagePrompt .= ' Focus on ' . $imageSubject . '.';
    }
    $imageSize = Env::get('IMAGE_SIZE', '1024x1024');
    $imageQuality = Env::get('IMAGE_QUALITY', 'standard');
    $imageCount = max(1, (int)Env::get('IMAGE_N', '1'));
    $imageModel = Env::get('IMAGE_MODEL', Env::get('OPENAI_IMAGE_MODEL', 'gpt-image-1'));
    if (strcasecmp($imageModel, 'dall-e-3') === 0) {
        $imageCount = 1;
    }
    Logger::log('info', sprintf('Generating image with model %s (size=%s quality=%s n=%d)', $imageModel, $imageSize, $imageQuality, $imageCount));
    Logger::log('info', sprintf('Image prompt (%s): %s', $imagePromptStyle, $imagePrompt));

    $imagePath = null;
    $imagesDir = __DIR__ . '/../storage/images';
    if (ensureImageDirectory($imagesDir)) {
        try {
            $imageData = $openAI->generateImage($imagePrompt, $imageSize, $imageQuality, $imageCount);
            $imagePathCandidate = $imagesDir . '/' . $draftId . '.png';
            if (file_put_contents($imagePathCandidate, $imageData) === false) {
                throw new RuntimeException('Unable to persist generated image');
            }
            $imagePath = $imagePathCandidate;
            Logger::log('info', "Saved featured image for draft {$draftId} at {$imagePath}");
        } catch (Throwable $imgEx) {
            Logger::log('error', "Image generation skipped for draft {$draftId}: " . $imgEx->getMessage());
        }
    } else {
        Logger::log('warning', "Storage directory {$imagesDir} is not available; skipping image for draft {$draftId}");
    }

    $update = $db->prepare(
        'UPDATE drafts SET title = :title, slug = :slug, meta_description = :meta, content_html = :content, image_path = :image, updated_at = CURRENT_TIMESTAMP WHERE id = :id'
    );
    $update->execute([
        ':title' => $title,
        ':slug' => $slug,
        ':meta' => $metaDescription,
        ':content' => $contentHtml,
        ':image' => $imagePath,
        ':id' => $draftId,
    ]);

    $token = bin2hex(random_bytes(16));
    $tokenStmt = $db->prepare('INSERT INTO approvals (draft_id, token, action) VALUES (:draft_id, :token, :action)');
    $tokenStmt->execute([
        ':draft_id' => $draftId,
        ':token' => $token,
        ':action' => 'requested',
    ]);

    $db->commit();

    Logger::log('info', "Draft {$draftId} stored and awaiting approval");

    $mailer = new Mailer();
    $baseUrl = rtrim(Env::get('APP_BASE_URL', ''), '/');
    if ($baseUrl === '') {
        throw new RuntimeException('APP_BASE_URL is not configured');
    }

    $previewUrl = $baseUrl . '/preview.php?id=' . $draftId;
    $approveUrl = $baseUrl . '/approve.php?token=' . $token;

    $body = implode("\n", [
        'Topic: ' . $topic,
        'Title: ' . $title,
        '',
        'Preview URL: ' . $previewUrl,
        'Approve URL: ' . $approveUrl,
        '',
        'To regenerate this draft, rerun scripts/generate_blog.php with the same topic.',
    ]);

    $mailer->send('Blog approval needed: ' . $title, $body);
    Logger::log('info', "Approval email sent for draft {$draftId}");

    echo "Draft {$draftId} ready for approval. Preview: {$previewUrl}\n";
} catch (Throwable $e) {
    if ($db->inTransaction()) {
        $db->rollBack();
    }

    Logger::log('error', 'Draft generation failed: ' . $e->getMessage());

    if ($draftId !== null) {
        $stmt = $db->prepare('UPDATE drafts SET status = :status, title = :title, content_html = :content, updated_at = CURRENT_TIMESTAMP WHERE id = :id');
        $stmt->execute([
            ':status' => 'failed',
            ':title' => 'Generation failed',
            ':content' => 'Error: ' . $e->getMessage(),
            ':id' => $draftId,
        ]);
    }

    echo "Error: " . $e->getMessage() . "\n";
    exit(1);
}

function createSlug(string $input): string
{
    $slug = mb_strtolower($input, 'UTF-8');
    $slug = preg_replace('/[^a-z0-9]+/i', '-', $slug);
    $slug = trim($slug, '-');
    return $slug !== '' ? $slug : 'blog-post';
}

function loadGuidance(string $path): string
{
    if (!is_file($path)) {
        return '';
    }

    return trim(file_get_contents($path) ?: '');
}

function buildGuidanceSystemText(string $brand, string $voice): string
{
    $parts = [];
    if ($brand !== '') {
        $parts[] = 'Brand guidelines: ' . $brand;
    }
    if ($voice !== '') {
        $parts[] = 'Voice guidance: ' . $voice;
    }

    return $parts === [] ? '' : "\n" . implode("\n", $parts);
}

function ensureImageDirectory(string $path): bool
{
    if (!is_dir($path)) {
        if (!@mkdir($path, 0775, true)) {
            Logger::log('error', 'Unable to create image directory: ' . $path);
            return false;
        }
    }

    if (!is_writable($path)) {
        Logger::log('error', 'Image directory is not writable: ' . $path);
        return false;
    }

    return true;
}
