<?php
// includes/card_generator.php — sobrepõe o código no molde do card (mensal/semestral/anual)

const CLIENT_CARDS_DIR = __DIR__ . '/../uploads/cards';

const CARD_CODE_TEXT_HEX = '#000000';
const CARD_CODE_MIN_FONT_PT = 26;
const CARD_CODE_MAX_FONT_PT = 140;

function card_plan_options(): array {
    return [
        'mensal' => [
            'label' => 'Mensal',
            'file' => 'cards.png',
        ],
        'semestral' => [
            'label' => 'Semestral',
            'file' => 'cardssemestral.png',
        ],
        'anual' => [
            'label' => 'Anual',
            'file' => 'cardsanual.png',
        ],
    ];
}

/** Posição do código por plano (ratios 0–1 sobre a imagem do molde) */
function card_code_box_config(string $plan = 'mensal'): array {
    $base = [
        'x' => 0.105,
        'y' => 0.702,
        'w' => 0.790,
        'h' => 0.088,
        'pad_w' => 0.96,
        'pad_h' => 0.92,
        'offset_x' => 0.0,
        'offset_y' => 0.0,
        'min_font' => CARD_CODE_MIN_FONT_PT,
        'max_font' => CARD_CODE_MAX_FONT_PT,
    ];

    $overrides = [
        'semestral' => [
            'y' => 0.700,
            'h' => 0.089,
        ],
        'anual' => [
            'x' => 0.108,
            'y' => 0.702,
            'w' => 0.784,
            'h' => 0.092,
            'pad_w' => 0.94,
            'pad_h' => 0.88,
            'offset_y' => 0.014,
            'min_font' => 24,
            'max_font' => 132,
        ],
    ];

    $plan = normalize_card_plan($plan);
    if (isset($overrides[$plan])) {
        $base = array_merge($base, $overrides[$plan]);
    }

    return $base;
}

function normalize_card_plan(string $raw): string {
    $plan = strtolower(trim($raw));
    $options = card_plan_options();
    return array_key_exists($plan, $options) ? $plan : 'mensal';
}

function card_plan_label(string $plan): string {
    $plan = normalize_card_plan($plan);
    return card_plan_options()[$plan]['label'];
}

function card_template_filename(string $plan = 'mensal'): string {
    $plan = normalize_card_plan($plan);
    return card_plan_options()[$plan]['file'];
}

function card_template_path(string $plan = 'mensal'): string {
    return __DIR__ . '/../' . card_template_filename($plan);
}

function client_card_path(int $client_id): string {
    return CLIENT_CARDS_DIR . '/client_' . $client_id . '.png';
}

function ensure_client_cards_dir(): bool {
    if (!is_dir(CLIENT_CARDS_DIR)) {
        return @mkdir(CLIENT_CARDS_DIR, 0755, true);
    }
    return true;
}

function card_gd_available(): bool {
    return extension_loaded('gd')
        && function_exists('imagecreatefrompng')
        && function_exists('imagettftext')
        && function_exists('imagettfbbox');
}

function card_font_path(): string {
    $candidates = [
        __DIR__ . '/../assets/fonts/Arial-Bold.ttf',
        __DIR__ . '/../assets/fonts/DejaVuSans-Bold.ttf',
        'C:/Windows/Fonts/arialbd.ttf',
        'C:/Windows/Fonts/ARIALBD.TTF',
        '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf',
        '/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf',
        '/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf',
    ];
    foreach ($candidates as $file) {
        if (is_readable($file)) {
            return $file;
        }
    }
    return '';
}

function card_hex_color($img, string $hex) {
    $hex = ltrim($hex, '#');
    if (strlen($hex) === 3) {
        $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
    }
    return imagecolorallocate(
        $img,
        hexdec(substr($hex, 0, 2)),
        hexdec(substr($hex, 2, 2)),
        hexdec(substr($hex, 4, 2))
    );
}

function card_text_metrics(string $font, int $size, string $text): array {
    $box = imagettfbbox($size, 0, $font, $text);
    if ($box === false) {
        return ['w' => 0, 'h'  => 0, 'box' => null];
    }
    return [
        'w' => abs($box[2] - $box[0]),
        'h' => abs($box[7] - $box[1]),
        'box' => $box,
    ];
}

function card_best_font_size(string $text, string $font, int $maxWidth, int $maxHeight, int $minFont = CARD_CODE_MIN_FONT_PT, int $maxFont = CARD_CODE_MAX_FONT_PT): int {
    $best = $minFont;
    $hi = min($maxFont, (int)max($maxHeight * 1.15, $minFont));

    for ($size = $minFont; $size <= $hi; $size++) {
        $m = card_text_metrics($font, $size, $text);
        if ($m['w'] <= $maxWidth && $m['h'] <= $maxHeight) {
            $best = $size;
            continue;
        }
        break;
    }

    return $best;
}

function card_draw_bold_ttf($img, int $size, int $x, int $y, $color, string $font, string $text): void {
    imagettftext($img, $size, 0, $x, $y, $color, $font, $text);
    imagettftext($img, $size, 0, $x + 1, $y, $color, $font, $text);
}

/** Desenha apenas o texto centralizado — sem criar faixa branca extra */
function card_draw_text_in_box($img, string $text, int $boxX, int $boxY, int $boxW, int $boxH, $color, string $font, array $config = []): void {
    $padW = (float)($config['pad_w'] ?? 0.96);
    $padH = (float)($config['pad_h'] ?? 0.92);
    $minFont = (int)($config['min_font'] ?? CARD_CODE_MIN_FONT_PT);
    $maxFont = (int)($config['max_font'] ?? CARD_CODE_MAX_FONT_PT);
    $offsetX = (float)($config['offset_x'] ?? 0.0);
    $offsetY = (float)($config['offset_y'] ?? 0.0);

    $imgW = imagesx($img);
    $imgH = imagesy($img);

    $maxW = (int)($boxW * $padW);
    $maxH = (int)($boxH * $padH);

    $size = card_best_font_size($text, $font, $maxW, $maxH, $minFont, $maxFont);
    $metrics = card_text_metrics($font, $size, $text);
    $box = $metrics['box'];
    if (!$box) {
        return;
    }

    $centerX = $boxX + ($boxW / 2);
    $centerY = $boxY + ($boxH / 2);
    $x = (int)($centerX - (($box[2] - $box[0]) / 2) + ($imgW * $offsetX));
    $y = (int)($centerY - (($box[1] + $box[7]) / 2) + ($imgH * $offsetY));

    card_draw_bold_ttf($img, $size, $x, $y, $color, $font, $text);
}

function load_card_template_image(string $plan = 'mensal') {
    $path = card_template_path($plan);
    if (!is_readable($path)) {
        return null;
    }
    $img = @imagecreatefrompng($path);
    return $img ?: null;
}

function card_download_filename(string $formatted_code, string $plan = 'mensal'): string {
    $plan = normalize_card_plan($plan);
    return 'card-' . $plan . '-' . strtoupper(format_activation_code($formatted_code)) . '.png';
}

function generate_client_card_png(int $client_id, string $formatted_code, string $plan = 'mensal'): array {
    $plan = normalize_card_plan($plan);
    $templateFile = card_template_filename($plan);

    if (!card_gd_available()) {
        return ['ok' => false, 'message' => 'GD/FreeType indisponível. Ative extensão GD com suporte TTF no PHP.'];
    }
    if (!ensure_client_cards_dir()) {
        return ['ok' => false, 'message' => 'Não foi possível criar a pasta de cards.'];
    }

    if (!is_readable(card_template_path($plan))) {
        return ['ok' => false, 'message' => 'Arquivo ' . $templateFile . ' não encontrado na pasta painel.'];
    }

    $font = card_font_path();
    if ($font === '') {
        return ['ok' => false, 'message' => 'Fonte bold não encontrada. Coloque Arial-Bold.ttf em painel/assets/fonts/.'];
    }

    $formatted_code = strtoupper(format_activation_code($formatted_code));
    if (strlen(preg_replace('/\D+/', '', $formatted_code)) !== 12) {
        return ['ok' => false, 'message' => 'Código inválido para gerar card.'];
    }

    $img = load_card_template_image($plan);
    if (!$img) {
        return ['ok' => false, 'message' => 'Não foi possível carregar o molde ' . $templateFile . '.'];
    }

    imagealphablending($img, true);
    imagesavealpha($img, true);

    $w = imagesx($img);
    $h = imagesy($img);

    $boxCfg = card_code_box_config($plan);
    $boxX = (int)($w * (float)$boxCfg['x']);
    $boxY = (int)($h * (float)$boxCfg['y']);
    $boxW = (int)($w * (float)$boxCfg['w']);
    $boxH = (int)($h * (float)$boxCfg['h']);

    $textColor = card_hex_color($img, CARD_CODE_TEXT_HEX);
    card_draw_text_in_box($img, $formatted_code, $boxX, $boxY, $boxW, $boxH, $textColor, $font, $boxCfg);

    $path = client_card_path($client_id);
    if (!imagepng($img, $path, 6)) {
        imagedestroy($img);
        return ['ok' => false, 'message' => 'Erro ao salvar PNG do card.'];
    }
    imagedestroy($img);

    $relative = 'uploads/cards/client_' . $client_id . '.png';
    return [
        'ok' => true,
        'path' => $path,
        'url' => get_base_url() . '/' . $relative,
        'filename' => card_download_filename($formatted_code, $plan),
        'card_plan' => $plan,
        'card_plan_label' => card_plan_label($plan),
    ];
}

function save_client_card_image(int $client_id, string $relative_path): void {
    $stmt = db()->prepare('UPDATE app_clients SET card_image = ? WHERE id = ?');
    $stmt->execute([$relative_path, $client_id]);
}

function generate_and_store_client_card(int $client_id, string $formatted_code, string $plan = 'mensal'): array {
    $plan = normalize_card_plan($plan);
    $result = generate_client_card_png($client_id, $formatted_code, $plan);
    if (!empty($result['ok'])) {
        save_client_card_image($client_id, 'uploads/cards/client_' . $client_id . '.png');
    }
    return $result;
}

function build_all_client_cards_zip(): array {
    if (!class_exists('ZipArchive')) {
        return ['ok' => false, 'message' => 'Extensão ZIP não disponível no PHP.'];
    }

    $clients = get_clients();
    if (empty($clients)) {
        return ['ok' => false, 'message' => 'Nenhum cliente cadastrado para gerar cards.'];
    }

    if (!ensure_client_cards_dir()) {
        return ['ok' => false, 'message' => 'Não foi possível acessar a pasta de cards.'];
    }

    $tempZip = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'cards_all_' . uniqid('', true) . '.zip';
    $zip = new ZipArchive();
    if ($zip->open($tempZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
        return ['ok' => false, 'message' => 'Não foi possível criar o arquivo ZIP.'];
    }

    $added = 0;
    $usedNames = [];

    foreach ($clients as $client) {
        $id = (int)($client['id'] ?? 0);
        if ($id <= 0) {
            continue;
        }

        $code = format_activation_code($client['activation_code'] ?? '');
        if (strlen(preg_replace('/\D+/', '', $code)) !== 12) {
            continue;
        }

        $plan = normalize_card_plan($client['card_plan'] ?? 'mensal');
        $gen = generate_client_card_png($id, $code, $plan);
        if (empty($gen['ok']) || empty($gen['path']) || !is_readable($gen['path'])) {
            continue;
        }

        $entryName = $gen['filename'] ?? card_download_filename($code, $plan);
        if (isset($usedNames[$entryName])) {
            $entryName = 'client-' . $id . '-' . $entryName;
        }
        $usedNames[$entryName] = true;

        $zip->addFile($gen['path'], $entryName);
        $added++;
    }

    $zip->close();

    if ($added === 0) {
        @unlink($tempZip);
        return ['ok' => false, 'message' => 'Nenhum card foi gerado. Verifique os arquivos cards*.png e a fonte TTF.'];
    }

    return [
        'ok' => true,
        'path' => $tempZip,
        'filename' => 'cards-tvexpress-' . date('Y-m-d-His') . '.zip',
        'count' => $added,
    ];
}
