<#
.SYNOPSIS
    PEM 인증서 파일로부터 firmware/certs/server_ca.c 를 재생성한다.

.DESCRIPTION
    Cafe24 서버 루트 CA(필요 시 intermediate+root 를 연결한 체인) PEM 을 읽어,
    mbedTLS 가 그대로 파싱할 수 있는 C 문자열 리터럴 형태로 server_ca.c 에 임베드한다.

    - 각 PEM 라인을 "....\n" C 리터럴로 변환(끝의 종결 NUL 은 sizeof 에 포함).
    - SERVER_CA_PEM_LEN = sizeof(SERVER_CA_PEM) 로 정의(NUL 포함 → mbedTLS 요구).
    - 폐쇄망: 이 스크립트는 *빌드 머신*에서만 실행. 타깃은 결과 .c 만 컴파일.

.PARAMETER PemPath
    입력 PEM 파일 경로(.pem/.crt). 하나 이상의 -----BEGIN CERTIFICATE----- 블록 포함.

.PARAMETER OutPath
    출력 C 파일 경로. 기본값: 이 스크립트와 같은 폴더의 server_ca.c

.EXAMPLE
    ./gen_ca_header.ps1 -PemPath cafe24_root.pem

.EXAMPLE
    # 체인 추출 → 헤더 생성 (한 번에)
    openssl s_client -showcerts -connect your-domain.example:443 -servername your-domain.example </dev/null `
        | openssl x509 -out cafe24_root.pem
    ./gen_ca_header.ps1 -PemPath cafe24_root.pem

.NOTES
    위험 R3(docs/stm32f407_migration_plan.md): 인증서 만료 시 펌웨어 재빌드/재배포 필요.
#>
[CmdletBinding()]
param(
    [Parameter(Mandatory = $true, Position = 0)]
    [string]$PemPath,

    [Parameter(Position = 1)]
    [string]$OutPath = (Join-Path $PSScriptRoot 'server_ca.c')
)

$ErrorActionPreference = 'Stop'

# --- 입력 검증 ----------------------------------------------------------------
if (-not (Test-Path -LiteralPath $PemPath)) {
    throw "PEM 파일을 찾을 수 없습니다: $PemPath"
}

# CRLF/CR 을 LF 로 정규화하고 라인 분해. 빈 끝줄은 제거.
$raw = Get-Content -LiteralPath $PemPath -Raw
$normalized = $raw -replace "`r`n", "`n" -replace "`r", "`n"
$lines = $normalized -split "`n"

# 최소한 BEGIN/END CERTIFICATE 마커가 있어야 한다.
if (-not ($normalized -match '-----BEGIN CERTIFICATE-----')) {
    throw "유효한 PEM 인증서 블록(-----BEGIN CERTIFICATE-----)이 없습니다: $PemPath"
}
if (-not ($normalized -match '-----END CERTIFICATE-----')) {
    throw "PEM 종료 마커(-----END CERTIFICATE-----)가 없습니다: $PemPath"
}

# 인증서 블록 개수(intermediate+root 연결이면 2개 이상).
$certCount = ([regex]::Matches($normalized, '-----BEGIN CERTIFICATE-----')).Count

# --- C 문자열 리터럴로 변환 ---------------------------------------------------
# 후행 빈 라인 제거(마지막 -----END----- 뒤의 공백 라인).
$body = New-Object System.Collections.Generic.List[string]
foreach ($line in $lines) {
    $body.Add($line) | Out-Null
}
while ($body.Count -gt 0 -and [string]::IsNullOrEmpty($body[$body.Count - 1])) {
    $body.RemoveAt($body.Count - 1)
}

# 각 라인을 C escape: 백슬래시/큰따옴표 이스케이프 후 "...\n" 형태로.
$escapedLines = foreach ($line in $body) {
    $esc = $line -replace '\\', '\\' -replace '"', '\"'
    '    "' + $esc + '\n"'
}

$generatedAt = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss zzz')
$pemFileName = Split-Path -Leaf $PemPath

$header = @"
/* =============================================================================
 * server_ca.c - 서버 루트 CA 인증서 (PEM, flash 임베드)  [자동 생성]
 *
 * gen_ca_header.ps1 로 자동 생성됨. 직접 편집하지 말 것.
 *   source PEM : $pemFileName
 *   생성 시각  : $generatedAt
 *   인증서 블록: $certCount 개
 *
 * mbedTLS PEM 요구사항: SERVER_CA_PEM_LEN 은 종결 NUL 을 포함해야 한다
 *   → sizeof(SERVER_CA_PEM) 사용.
 * 위험 R3: 인증서 만료/교체 시 이 파일 재생성 + 펌웨어 재배포 필요.
 * ===========================================================================*/
#include "server_ca.h"

const char SERVER_CA_PEM[] =
"@

$footer = @"
;

/* 길이: 종결 NUL 포함(mbedTLS PEM 요구). */
const unsigned int SERVER_CA_PEM_LEN = sizeof(SERVER_CA_PEM);
"@

$content = $header + "`n" + ($escapedLines -join "`n") + $footer + "`n"

# UTF-8 (BOM 없음) 로 기록 — arm-none-eabi-gcc 가 깔끔히 읽도록.
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($OutPath, $content, $utf8NoBom)

Write-Host "[OK] $OutPath 생성 완료 (인증서 블록 $certCount 개, source: $pemFileName)"
