<?php
// includes/card_generator.php - gera o card dinamicamente a partir de cardmodel.png

const CARD_TEMPLATE_FILE = __DIR__ . '/../cardmodel.png';
const CARD_CODE_TEXT_HEX = '#000000';
const CARD_TEXT_LIGHT_HEX = '#FFFFFF';
const CARD_OVERLAY_HEX = '#6F28D9';
const CARD_CODE_MIN_FONT_PT = 26;
const CARD_CODE_MAX_FONT_PT = 140;

function card_code_box_config(): array {
    return [
        'x' => 0.114,
        'y' => 0.670,
        'w' => 0.772,
        'h' => 0.072,
        'pad_w' => 0.90,
        'pad_h' => 0.74,
        'offset_x' => 0.0,
        'offset_y' => 0.001,
        'min_font' => 20,
        'max_font' => 72,
    ];
}

function card_title_box_config(): array {
    return [
        'x' => 0.0,
        'y' => 0.0,
        'w' => 0.0,
        'h' => 0.0,
        'pad_w' => 0.96,
        'pad_h' => 0.88,
        'offset_x' => 0.0,
        'offset_y' => 0.0,
        'min_font' => 18,
        'max_font' => 44,
    ];
}

function card_expiry_box_config(): array {
    return [
        'x' => 0.690,
        'y' => 0.240,
        'w' => 0.205,
        'h' => 0.040,
        'pad_w' => 0.90,
        'pad_h' => 0.76,
        'offset_x' => 0.0,
        'offset_y' => 0.002,
        'min_font' => 16,
        'max_font' => 16,
    ];
}

function card_title_text(): string {
    return '';
}

function card_template_path(): string {
    return CARD_TEMPLATE_FILE;
}

function card_download_filename(string $formatted_code, string $expires_label = ''): string {
    $code = strtoupper(format_activation_code($formatted_code));
    $suffix = preg_replace('/[^0-9]/', '', $expires_label);
    $datePart = $suffix !== '' ? '-vence-' . $suffix : '';
    return 'card-tvexpress' . $datePart . '-' . $code . '.png';
}

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_hex_color_alpha($img, string $hex, int $alpha) {
    $hex = ltrim($hex, '#');
    if (strlen($hex) === 3) {
        $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
    }
    return imagecolorallocatealpha(
        $img,
        hexdec(substr($hex, 0, 2)),
        hexdec(substr($hex, 2, 2)),
        hexdec(substr($hex, 4, 2)),
        max(0, min(127, $alpha))
    );
}

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_ttf($img, int $size, int $x, int $y, $color, string $font, string $text): void {
    imagettftext($img, $size, 0, $x, $y, $color, $font, $text);
}

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_ttf($img, $size, $x, $y, $color, $font, $text);
}

function card_fill_box($img, int $boxX, int $boxY, int $boxW, int $boxH, $color): void {
    imagefilledrectangle($img, $boxX, $boxY, $boxX + $boxW, $boxY + $boxH, $color);
}

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

function card_expiry_label_from_client(array $client): string {
    if (function_exists('format_client_expiry_for_panel')) {
        $expiry = format_client_expiry_for_panel($client);
        $label = trim((string)($expiry['date'] ?? ''));
        if ($label !== '') {
            return $label;
        }
    }

    $raw = trim((string)($client['expires_at'] ?? ''));
    if ($raw === '') {
        return '--/--/----';
    }
    $ts = strtotime($raw);
    return $ts ? date('d/m/Y', $ts) : '--/--/----';
}

function build_client_card_image(array $client): array {
    if (!card_gd_available()) {
        return ['ok' => false, 'message' => 'GD/FreeType indisponivel. Ative extensao GD com suporte TTF no PHP.'];
    }

    if (!is_readable(card_template_path())) {
        return ['ok' => false, 'message' => 'Arquivo cardmodel.png nao encontrado na pasta painel.'];
    }

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

    $formatted_code = strtoupper(format_activation_code((string)($client['activation_code'] ?? '')));
    if (strlen(preg_replace('/\D+/', '', $formatted_code)) !== 12) {
        return ['ok' => false, 'message' => 'Codigo invalido para gerar card.'];
    }

    $img = load_card_template_image();
    if (!$img) {
        return ['ok' => false, 'message' => 'Nao foi possivel carregar o molde cardmodel.png.'];
    }

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

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

    $codeText = card_hex_color($img, CARD_CODE_TEXT_HEX);

    $titleCfg = card_title_box_config();
    if (card_title_text() !== '' && (float)$titleCfg['w'] > 0 && (float)$titleCfg['h'] > 0) {
        $overlayColor = card_hex_color_alpha($img, CARD_OVERLAY_HEX, 18);
        $titleX = (int)($w * (float)$titleCfg['x']);
        $titleY = (int)($h * (float)$titleCfg['y']);
        $titleW = (int)($w * (float)$titleCfg['w']);
        $titleH = (int)($h * (float)$titleCfg['h']);
        card_fill_box($img, $titleX, $titleY, $titleW, $titleH, $overlayColor);
        $lightText = card_hex_color($img, CARD_TEXT_LIGHT_HEX);
        card_draw_text_in_box($img, card_title_text(), $titleX, $titleY, $titleW, $titleH, $lightText, $font, $titleCfg);
    }

    $expiryCfg = card_expiry_box_config();
    $expiryX = (int)($w * (float)$expiryCfg['x']);
    $expiryY = (int)($h * (float)$expiryCfg['y']);
    $expiryW = (int)($w * (float)$expiryCfg['w']);
    $expiryH = (int)($h * (float)$expiryCfg['h']);
    card_draw_text_in_box($img, card_expiry_label_from_client($client), $expiryX, $expiryY, $expiryW, $expiryH, $codeText, $font, $expiryCfg);

    $codeCfg = card_code_box_config();
    $codeX = (int)($w * (float)$codeCfg['x']);
    $codeY = (int)($h * (float)$codeCfg['y']);
    $codeW = (int)($w * (float)$codeCfg['w']);
    $codeH = (int)($h * (float)$codeCfg['h']);
    card_draw_text_in_box($img, $formatted_code, $codeX, $codeY, $codeW, $codeH, $codeText, $font, $codeCfg);

    return [
        'ok' => true,
        'image' => $img,
        'filename' => card_download_filename($formatted_code, card_expiry_label_from_client($client)),
        'formatted_code' => $formatted_code,
        'expires_label' => card_expiry_label_from_client($client),
    ];
}

function generate_client_card_png_bytes(array $client): array {
    $result = build_client_card_image($client);
    if (empty($result['ok']) || empty($result['image'])) {
        return $result;
    }

    ob_start();
    imagepng($result['image'], null, 6);
    $bytes = ob_get_clean();
    imagedestroy($result['image']);

    if (!is_string($bytes) || $bytes === '') {
        return ['ok' => false, 'message' => 'Erro ao renderizar PNG do card.'];
    }

    $result['bytes'] = $bytes;
    unset($result['image']);
    return $result;
}

function build_all_client_cards_zip(): array {
    if (!class_exists('ZipArchive')) {
        return ['ok' => false, 'message' => 'Extensao ZIP nao disponivel no PHP.'];
    }

    $clients = get_clients();
    if (empty($clients)) {
        return ['ok' => false, 'message' => 'Nenhum cliente cadastrado para gerar 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' => 'Nao foi possivel criar o arquivo ZIP.'];
    }

    $added = 0;
    $usedNames = [];

    foreach ($clients as $client) {
        $gen = generate_client_card_png_bytes($client);
        if (empty($gen['ok']) || empty($gen['bytes'])) {
            continue;
        }

        $entryName = $gen['filename'] ?? ('card-client-' . (int)($client['id'] ?? 0) . '.png');
        if (isset($usedNames[$entryName])) {
            $entryName = 'client-' . (int)($client['id'] ?? 0) . '-' . $entryName;
        }
        $usedNames[$entryName] = true;

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

    $zip->close();

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

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