using Microsoft.AspNetCore.Mvc;
using OpcUaManager.Models;
using OpcUaManager.Services;

namespace OpcUaManager.Controllers;

[ApiController]
[Route("api/cert")]
[Produces("application/json")]
public class CertController : ControllerBase
{
    private readonly CertService _certService;
    private readonly ILogger<CertController> _logger;

    public CertController(CertService certService, ILogger<CertController> logger)
    {
        _certService = certService;
        _logger      = logger;
    }

    /// <summary>
    /// X.509 클라이언트 인증서를 생성하고 pki/own/certs/ 에 PFX로 저장합니다.
    /// </summary>
    /// <remarks>
    /// 원본 Program.cs 의 인증서 체계(pki/ 폴더, Exportable|MachineKeySet 플래그)를 유지합니다.
    ///
    /// Sample request:
    ///
    ///     POST /api/cert/generate
    ///     {
    ///         "clientHostName": "dbsvr",
    ///         "applicationName": "OpcTestClient",
    ///         "serverHostName": "opc-server-01",
    ///         "serverIp": "192.168.0.20",
    ///         "pfxPassword": "",
    ///         "validDays": 365
    ///     }
    /// </remarks>
    [HttpPost("generate")]
    [ProducesResponseType(typeof(CertCreateResult), 200)]
    [ProducesResponseType(typeof(ApiError), 400)]
    public async Task<IActionResult> Generate([FromBody] CertCreateRequest req)
    {
        if (string.IsNullOrWhiteSpace(req.ClientHostName) ||
            string.IsNullOrWhiteSpace(req.ApplicationName))
            return BadRequest(new ApiError
            {
                Error  = "필수값 누락",
                Detail = "ClientHostName, ApplicationName 은 필수입니다."
            });

        _logger.LogInformation("인증서 생성 요청: {Host}/{App}", req.ClientHostName, req.ApplicationName);

        var result = await _certService.GenerateAsync(req);

        if (!result.Success)
            return BadRequest(new ApiError { Error = "인증서 생성 실패", Detail = result.Message });

        return Ok(result);
    }

    /// <summary>pki/own/certs/ 폴더의 PFX 파일 목록을 반환합니다.</summary>
    [HttpGet("list")]
    [ProducesResponseType(typeof(IEnumerable<string>), 200)]
    public IActionResult List()
        => Ok(_certService.ListCertificates());

    /// <summary>PFX 파일을 다운로드합니다.</summary>
    [HttpGet("download/{fileName}")]
    public IActionResult Download(string fileName)
    {
        // 경로 traversal 방지
        if (fileName.Contains("..") || fileName.Contains('/') || fileName.Contains('\\'))
            return BadRequest(new ApiError { Error = "잘못된 파일 이름" });

        string path = Path.Combine("pki", "own", "certs", fileName);
        if (!System.IO.File.Exists(path))
            return NotFound(new ApiError { Error = "파일 없음", Detail = path });

        byte[] bytes = System.IO.File.ReadAllBytes(path);
        return File(bytes, "application/x-pkcs12", fileName);
    }
}
