using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using RobotNet.Script.Shares;
using RobotNet.ScriptManager.Helpers;
using RobotNet.ScriptManager.Services;
using RobotNet.Shares;

namespace RobotNet.ScriptManager.Controllers;

[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ScriptController(ScriptStateManager scriptBuilder) : ControllerBase
{
    [HttpGet]
    [Route("")]
    public ScriptFolder Gets() => new("Scripts", GetScriptFolders(ScriptConfiguration.ScriptStorePath), GetScriptFiles(ScriptConfiguration.ScriptStorePath));

    [HttpPost]
    [Route("Directory")]
    public MessageResult CreateDirectory([FromBody] CreateModel model)
    {
        if(scriptBuilder.State == ProcessorState.Building 
            ||  scriptBuilder.State == ProcessorState.Starting 
            || scriptBuilder.State == ProcessorState.Running 
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể tạo thư mục");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, model.Path, model.Name);
        if (Directory.Exists(fullPath)) return new(false, "Folder đã tồn tại");
        try
        {
            Directory.CreateDirectory(fullPath);
            return new(true, "");
        }
        catch (Exception e)
        {
            return new(false, e.Message);
        }
    }

    [HttpPost]
    [Route("File")]
    public MessageResult CreateFile([FromBody] CreateModel model)
    {
        if (scriptBuilder.State == ProcessorState.Building
            || scriptBuilder.State == ProcessorState.Starting
            || scriptBuilder.State == ProcessorState.Running
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể tạo file");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, model.Path, model.Name);
        if (System.IO.File.Exists(fullPath)) return new(false, "File đã tồn tại");
        try
        {
            var fs = System.IO.File.Create(fullPath);
            fs.Close();
            return new(true, "");
        }
        catch (Exception e)
        {
            return new(false, e.Message);
        }
    }

    [HttpPatch]
    [Route("File")]
    public MessageResult UpdateCode([FromBody] UpdateModel model)
    {
        if (scriptBuilder.State == ProcessorState.Building
            || scriptBuilder.State == ProcessorState.Starting
            || scriptBuilder.State == ProcessorState.Running
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể update file");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, model.Path);
        System.IO.File.WriteAllText(fullPath, model.Code);
        ResetScriptProcessor();
        return new(true, "");
    }


    [HttpPatch]
    [Route("FileName")]
    public MessageResult RenameFile([FromBody] RenameModel model)
    {
        if (scriptBuilder.State == ProcessorState.Building
            || scriptBuilder.State == ProcessorState.Starting
            || scriptBuilder.State == ProcessorState.Running
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể thay đổi tên file");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, model.Path);
        if (!System.IO.File.Exists(fullPath)) return new(false, "Source code không tồn tại");

        var folder = Path.GetDirectoryName(fullPath) ?? "";
        var fi = new FileInfo(fullPath);
        fi.MoveTo(Path.Combine(folder, model.NewName));
        return new(true, "");
    }

    [HttpPatch]
    [Route("DirectoryName")]
    public MessageResult RenameDirectory([FromBody] RenameModel model)
    {
        if (scriptBuilder.State == ProcessorState.Building
            || scriptBuilder.State == ProcessorState.Starting
            || scriptBuilder.State == ProcessorState.Running
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể thay đổi tên thư mục");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, model.Path);
        if (!Directory.Exists(fullPath)) return new(false, "Folder không tồn tại");

        var folder = Path.GetDirectoryName(fullPath) ?? "";
        var di = new DirectoryInfo(fullPath);
        di.MoveTo(Path.Combine(folder, model.NewName));
        return new(true, "");
    }

    [HttpDelete]
    [Route("File")]
    public MessageResult DeleteFile([FromQuery] string path)
    {
        if (scriptBuilder.State == ProcessorState.Building
            || scriptBuilder.State == ProcessorState.Starting
            || scriptBuilder.State == ProcessorState.Running
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể xóa file");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, path);
        if (!System.IO.File.Exists(fullPath)) return new(false, "Source code không tồn tại");

        System.IO.File.Delete(fullPath);
        ResetScriptProcessor();
        return new(true, "");
    }

    [HttpDelete]
    [Route("Directory")]
    public MessageResult DeleteDirectory([FromQuery] string path)
    {
        if (scriptBuilder.State == ProcessorState.Building
            || scriptBuilder.State == ProcessorState.Starting
            || scriptBuilder.State == ProcessorState.Running
            || scriptBuilder.State == ProcessorState.Stopping)
        {
            return new(false, $"Hệ thống đang trong trạng thái {scriptBuilder.State}, không thể xóa thư mục");
        }
        var fullPath = Path.Combine(ScriptConfiguration.ScriptStorePath, path);
        if (!Directory.Exists(fullPath)) return new(false, "Folder không tồn tại");

        var di = new DirectoryInfo(fullPath);
        di.Delete(true);
        ResetScriptProcessor();
        return new(true, "");
    }

    [HttpGet]
    [Route("UsingNamespaces")]
    public IEnumerable<string> GetUsingNamespaces() => ScriptConfiguration.UsingNamespaces;

    [HttpGet]
    [Route("PreCode")]
    public string GetPreCode() => ScriptConfiguration.DeveloptGlobalsScript;

    private void ResetScriptProcessor()
    {
        string message = string.Empty;
        scriptBuilder.Reset(ref message);
    }

    private static IEnumerable<ScriptFile> GetScriptFiles(string parentDir)
    {
        var dirInfo = new DirectoryInfo(parentDir);
        foreach (var fileInfo in dirInfo.GetFiles())
        {
            yield return new ScriptFile(fileInfo.Name, System.IO.File.ReadAllText(fileInfo.FullName));
        }
    }

    private static IEnumerable<ScriptFolder> GetScriptFolders(string parentDir)
    {
        var dirInfo = new DirectoryInfo(parentDir);
        foreach (var dir in dirInfo.GetDirectories())
        {
            yield return new ScriptFolder(dir.Name, GetScriptFolders(dir.FullName), GetScriptFiles(dir.FullName));
        }
    }

}
