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

namespace OpcUaManager.Controllers;

[ApiController]
[Route("api/crawler")]
[Produces("application/json")]
public class CrawlerController : ControllerBase
{
    private readonly OpcCrawlerService _crawlerSvc;
    private readonly OpcSessionService _sessionSvc;
    private readonly ILogger<CrawlerController> _logger;

    public CrawlerController(
        OpcCrawlerService crawlerSvc,
        OpcSessionService sessionSvc,
        ILogger<CrawlerController> logger)
    {
        _crawlerSvc = crawlerSvc;
        _sessionSvc = sessionSvc;
        _logger     = logger;
    }

    /// <summary>
    /// 지정한 시작 노드부터 OPC UA 노드 트리를 재귀 탐색합니다.
    /// </summary>
    /// <remarks>
    /// Sample request:
    ///
    ///     POST /api/crawler/start
    ///     {
    ///         "startNodeId": "ns=1;s=$assetmodel",
    ///         "maxDepth": 5
    ///     }
    ///
    /// 탐색 결과는 응답 JSON 과 함께 서버 로컬에 Honeywell_FullMap.csv 로 저장됩니다.
    /// </remarks>
    [HttpPost("start")]
    [ProducesResponseType(typeof(CrawlResult), 200)]
    [ProducesResponseType(typeof(ApiError), 400)]
    public async Task<IActionResult> Start([FromBody] CrawlRequest req)
    {
        if (!_sessionSvc.IsConnected)
            return BadRequest(new ApiError
            {
                Error  = "세션 없음",
                Detail = "먼저 /api/session/connect 로 OPC 서버에 연결하세요."
            });

        _logger.LogInformation("Crawler 시작: {NodeId} (depth={Depth})",
            req.StartNodeId, req.MaxDepth);

        // 대규모 탐사는 시간이 오래 걸릴 수 있으므로 타임아웃을 늘려줍니다
        HttpContext.RequestAborted.ThrowIfCancellationRequested();

        var result = await _crawlerSvc.CrawlAsync(req);

        return result.Success ? Ok(result)
            : BadRequest(new ApiError { Error = "탐사 실패", Detail = result.Message });
    }

    /// <summary>마지막 탐사로 생성된 CSV 파일을 다운로드합니다.</summary>
    [HttpGet("csv")]
    public IActionResult DownloadCsv()
    {
        string path = Path.GetFullPath("Honeywell_FullMap.csv");
        if (!System.IO.File.Exists(path))
            return NotFound(new ApiError { Error = "CSV 없음", Detail = "탐사를 먼저 실행하세요." });

        byte[] bytes = System.IO.File.ReadAllBytes(path);
        return File(bytes, "text/csv", "Honeywell_FullMap.csv");
    }
}
