using LiquidCode.Tester.Worker.Services;
using Microsoft.AspNetCore.Mvc;

namespace LiquidCode.Tester.Worker.Controllers;

[ApiController]
[Route("api/[controller]")]
public class TestController : ControllerBase
{
    private readonly ITestingService _testingService;
    private readonly ILogger<TestController> _logger;

    public TestController(ITestingService testingService, ILogger<TestController> logger)
    {
        _testingService = testingService;
        _logger = logger;
    }

    [HttpPost]
    public async Task<IActionResult> Test([FromForm] TestRequest request)
    {
        _logger.LogInformation("Received test request for submit {SubmitId}", request.Id);

        try
        {
            // Save package to temporary file before starting background task
            // This is necessary because IFormFile becomes unavailable after request completes
            string? packageFilePath = null;
            if (request.Package != null)
            {
                var tempDirectory = Path.Combine(Path.GetTempPath(), "worker-packages");
                Directory.CreateDirectory(tempDirectory);

                packageFilePath = Path.Combine(tempDirectory, $"package_{Guid.NewGuid()}.zip");

                await using (var fileStream = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    await request.Package.CopyToAsync(fileStream);
                }

                _logger.LogInformation("Package saved to temporary file: {FilePath}", packageFilePath);
            }

            // Create a copy of request data for background task
            var backgroundRequest = new TestRequest
            {
                Id = request.Id,
                MissionId = request.MissionId,
                Language = request.Language,
                LanguageVersion = request.LanguageVersion,
                SourceCode = request.SourceCode,
                CallbackUrl = request.CallbackUrl,
                Package = null, // Will use file path instead
                PackageFilePath = packageFilePath
            };

            // Start testing in background
            _ = Task.Run(async () =>
            {
                try
                {
                    await _testingService.ProcessSubmitAsync(backgroundRequest);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error processing submit {SubmitId}", backgroundRequest.Id);
                }
                finally
                {
                    // Cleanup temporary package file
                    if (packageFilePath != null && System.IO.File.Exists(packageFilePath))
                    {
                        try
                        {
                            System.IO.File.Delete(packageFilePath);
                            _logger.LogInformation("Deleted temporary package file: {FilePath}", packageFilePath);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogWarning(ex, "Failed to delete temporary package file: {FilePath}", packageFilePath);
                        }
                    }
                }
            });

            return Accepted(new { message = "Test request accepted", submitId = request.Id });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to accept test request for submit {SubmitId}", request.Id);
            return StatusCode(500, new { error = "Failed to accept test request", details = ex.Message });
        }
    }

    [HttpGet("health")]
    public IActionResult Health()
    {
        return Ok(new { status = "healthy", service = "universal-worker", timestamp = DateTime.UtcNow });
    }
}

public class TestRequest
{
    public long Id { get; set; }
    public long MissionId { get; set; }
    public string Language { get; set; } = string.Empty;
    public string LanguageVersion { get; set; } = string.Empty;
    public string SourceCode { get; set; } = string.Empty;
    public string CallbackUrl { get; set; } = string.Empty;
    public IFormFile? Package { get; set; }
    public string? PackageFilePath { get; set; } // Internal use - path to saved package file
}
