namespace RobotNet.WebApp.Scripts.Models;

public class ScriptFolderModel(ScriptFolderModel? parrent, string name, int level) : IHierachyItemModel
{
    public int Level { get; } = level;
    public ScriptFolderModel? Parrent { get; } = parrent;
    public string Path => System.IO.Path.Combine(Parrent?.Path ?? "", Name);

    public readonly List<ScriptFolderModel> Folders = [];
    public readonly List<ScriptFileModel> Files = [];

    public bool IsModified { get; private set; }
    public int WarningCount { get; private set; }
    public int ErrorCount { get; private set; }

    public event Action? OnChildrenChanged;
    public event Action? OnModified;
    public event Action? OnNameChanged;
    public event Action<int, int>? OnDiagnosticsChanged;

    public string Name { get; private set; } = name;

    public void AddFiles(params IEnumerable<ScriptFileModel> files)
    {
        Files.AddRange(files);
        Files.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));

        IsModified = IsModified || files.Any(file => file.IsModified);
        WarningCount += files.Sum(folder => folder.WarningCount);
        ErrorCount += files.Sum(folder => folder.ErrorCount);

        foreach (var file in files)
        {
            file.OnModified += UpdateModified;
            file.OnDiagnosticsChanged += DiagnosticsChanged;
        }

        OnModified?.Invoke();
        OnChildrenChanged?.Invoke();
    }

    public void AddFolders(params IEnumerable<ScriptFolderModel> folders)
    {
        Folders.AddRange(folders);
        Folders.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));

        IsModified = IsModified || folders.Any(folder => folder.IsModified);
        WarningCount += folders.Sum(folder => folder.WarningCount);
        ErrorCount += folders.Sum(folder => folder.ErrorCount);

        foreach (var folder in folders)
        {
            folder.OnModified += UpdateModified;
            folder.OnDiagnosticsChanged += DiagnosticsChanged;
        }

        OnModified?.Invoke();
        OnChildrenChanged?.Invoke();
    }

    public void RemoveFile(ScriptFileModel file)
    {
        if(Files.Remove(file))
        {
            OnChildrenChanged?.Invoke();
        }
    }

    public void RemoveFolder(ScriptFolderModel folder)
    {
        if(Folders.Remove(folder))
        {
            OnChildrenChanged?.Invoke();
        }
    }

    public void Rename(string newName)
    {
        if(string.IsNullOrEmpty(newName)) throw new ArgumentNullException("Tên thư mục không được để trống");

        if(Name == newName) return;

        Name = newName;
        OnNameChanged?.Invoke();
    }

    private void UpdateModified()
    {
        IsModified = Files.Any(file => file.IsModified) || Folders.Any(folder => folder.IsModified);
        OnModified?.Invoke();
    }

    private void DiagnosticsChanged(int warningCount, int errorCount)
    {
        WarningCount += warningCount;
        ErrorCount += errorCount;
        //WarningCount = Files.Sum(file => file.WarningCount) + Folders.Sum(folder => folder.WarningCount);
        //ErrorCount = Files.Sum(file => file.ErrorCount) + Folders.Sum(folder => folder.ErrorCount);
        OnDiagnosticsChanged?.Invoke(warningCount, errorCount);
    }
}
