using LiquidCode.Tester.Common.Models;
using LiquidCode.Tester.Gateway.Models;
using LiquidCode.Tester.Gateway.Services;
using Microsoft.AspNetCore.Mvc;

namespace LiquidCode.Tester.Gateway.Controllers;

[ApiController]
[Route("api/[controller]")]
public class TesterController : ControllerBase
{
    private readonly IPackageDownloadService _packageDownloadService;
    private readonly IWorkerClientService _workerClientService;
    private readonly ILogger<TesterController> _logger;

    public TesterController(
        IPackageDownloadService packageDownloadService,
        IWorkerClientService workerClientService,
        ILogger<TesterController> logger)
    {
        _packageDownloadService = packageDownloadService;
        _workerClientService = workerClientService;
        _logger = logger;
    }

    [HttpPost("submit")]
    public async Task<IActionResult> Submit([FromBody] SubmitForTesterModel request)
    {
        _logger.LogInformation("Received submit request for ID {SubmitId}", request.Id);

        try
        {
            // Download the package or use cached version if available
            var packagePath = await _packageDownloadService.GetOrDownloadPackageAsync(request.MissionId, request.PackageUrl);

            // Send to appropriate worker based on language
            await _workerClientService.SendToWorkerAsync(request, packagePath, deletePackageAfterSend: false);

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

    [HttpPost("submit-local")]
    public async Task<IActionResult> SubmitLocal([FromForm] LocalSubmitModel request)
    {
        _logger.LogInformation("Received local submit request for ID {SubmitId}", request.Id);

        try
        {
            if (request.Package == null)
            {
                return BadRequest(new { error = "Package file is required" });
            }

            // Save uploaded package to temporary file
            var packageDirectory = Path.Combine(Path.GetTempPath(), "packages");
            if (!Directory.Exists(packageDirectory))
            {
                Directory.CreateDirectory(packageDirectory);
            }

            var packageFileName = $"package_{Guid.NewGuid()}.zip";
            var packagePath = Path.Combine(packageDirectory, packageFileName);

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

            _logger.LogInformation("Package saved to {PackagePath}", packagePath);

            // Create SubmitForTesterModel from local submit
            var submitModel = new SubmitForTesterModel(
                Id: request.Id,
                MissionId: request.MissionId,
                Language: request.Language,
                LanguageVersion: request.LanguageVersion,
                SourceCode: request.SourceCode,
                PackageUrl: packagePath, // Use local path instead of URL
                CallbackUrl: request.CallbackUrl
            );

            // Send to appropriate worker based on language
            await _workerClientService.SendToWorkerAsync(submitModel, packagePath, deletePackageAfterSend: true);

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

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