using RpgRoller.Components.Pages.HomeControls;
using RpgRoller.Contracts;
using RpgRoller.Domain;

namespace RpgRoller.Components.Pages;

public sealed class WorkspaceState
{
    public string OwnerLabel(Guid ownerUserId)
    {
        if (User is not null && ownerUserId == User.Id)
            return "You";

        if (SelectedCampaign is null)
            return "Unknown owner";

        if (ownerUserId == SelectedCampaign.Gm.Id)
            return $"{SelectedCampaign.Gm.DisplayName} (GM)";

        var ownerDisplayName = SelectedCampaign.Characters.Where(character => character.OwnerUserId == ownerUserId)
            .Select(character => character.OwnerDisplayName)
            .FirstOrDefault(displayName => !string.IsNullOrWhiteSpace(displayName));

        return string.IsNullOrWhiteSpace(ownerDisplayName) ? "Unknown owner" : ownerDisplayName;
    }

    public string SkillDefinitionLabel(CharacterSheetSkill skill)
    {
        if (!string.Equals(SelectedCampaign?.RulesetId, "d6", StringComparison.OrdinalIgnoreCase))
        {
            if (string.Equals(SelectedCampaign?.RulesetId, RulesetFormHelpers.RulesetIds.Rolemaster,
                    StringComparison.OrdinalIgnoreCase))
                return RulesetFormHelpers.DescribeRolemasterExpression(skill.DiceRollDefinition, skill.FumbleRange,
                    skill.RolemasterAutoRetry);

            return skill.DiceRollDefinition;
        }

        var fumbleLabel = skill.AllowFumble ? "fumble on" : "fumble off";
        return $"{skill.DiceRollDefinition}, wild {skill.WildDice}, {fumbleLabel}";
    }

    public UserSummary? User { get; set; }
    public Guid? ActiveCharacterId { get; set; }
    public Guid? SelectedCampaignId { get; set; }
    public CampaignRoster? SelectedCampaign { get; set; }
    public List<CampaignSummary> Campaigns { get; set; } = [];
    public List<CampaignOption> CharacterCampaignOptions { get; set; } = [];
    public List<CharacterSheetSkill> SelectedCharacterSkills { get; set; } = [];
    public List<CharacterSheetSkillGroup> SelectedCharacterSkillGroups { get; set; } = [];
    public List<CampaignLogListEntry> CampaignLog { get; set; } = [];
    public List<RulesetDefinition> Rulesets { get; set; } = [];
    public List<AdminUserSummary> AdminUsers { get; set; } = [];
    public Guid? SelectedCharacterId { get; set; }
    public RollResult? LastRoll { get; set; }
    public List<string> KnownUsernames { get; set; } = [];
    public string RollVisibility { get; set; } = "public";

    public bool IsMutating { get; set; }
    public bool IsCampaignDataLoading { get; set; }
    public bool IsAdminDataLoading { get; set; }
    public bool HasLoadedAdminUsers { get; set; }
    public bool HasHealthIssue { get; set; }
    public string HealthIssueMessage { get; set; } = "Retry to restore the API connection.";
    public List<WorkspaceToast> Toasts { get; } = [];
    public string MobilePanel { get; set; } = "character";
    public string ConnectionState { get; set; } = "offline";
    public string LiveAnnouncement { get; set; } = string.Empty;
    public bool IsScreenMenuOpen { get; set; }

    public bool ShowCreateCharacterModal { get; set; }
    public bool ShowEditCharacterModal { get; set; }
    public bool ShowRolemasterSkillRollModal { get; set; }
    public bool CanEditCharacterOwner { get; set; }
    public Guid? EditingCharacterId { get; set; }
    public CharacterSheetSkill? PendingRolemasterSkillRoll { get; set; }
    public string PendingRolemasterSituationalModifier { get; set; } = string.Empty;
    public string? PendingRolemasterSkillRollError { get; set; }
    public bool IsSubmittingRolemasterSkillRoll { get; set; }
    public CharacterFormModel CreateCharacterInitialModel { get; set; } = new();
    public CharacterFormModel EditCharacterInitialModel { get; set; } = new();
    public int CreateCharacterFormVersion { get; set; }
    public int EditCharacterFormVersion { get; set; }
    public bool StateRefreshInProgress { get; set; }
    public bool HasInteractiveRenderStarted { get; set; }
    public CampaignStateSnapshot? CurrentCampaignState { get; set; }
    public Guid? CampaignLogCursor { get; set; }
    public Guid? ExpandedCampaignLogRollId { get; set; }
    public Guid? FreshCampaignLogRollId { get; set; }
    public Dictionary<Guid, CampaignRollDetail> CampaignLogDetails { get; } = [];
    public HashSet<Guid> CampaignLogDetailsLoading { get; } = [];
    public Dictionary<Guid, string> CampaignLogDetailErrors { get; } = [];

    public string? SelectedCampaignName => SelectedCampaign?.Name ??
                                           Campaigns.FirstOrDefault(campaign => campaign.Id == SelectedCampaignId)
                                               ?.Name;

    public CharacterSummary? SelectedCharacter =>
        SelectedCampaign?.Characters.FirstOrDefault(character => character.Id == SelectedCharacterId);

    public CampaignRoster? PlaySelectedCampaign
    {
        get
        {
            if (SelectedCampaign is null)
                return null;

            if (User is null)
                return new(SelectedCampaign.Id, SelectedCampaign.Name, SelectedCampaign.RulesetId, SelectedCampaign.Gm,
                    []);

            if (IsCurrentUserGm)
                return SelectedCampaign;

            var ownedCharacters = SelectedCampaign.Characters.Where(character => character.OwnerUserId == User.Id)
                .ToArray();

            return new(SelectedCampaign.Id, SelectedCampaign.Name, SelectedCampaign.RulesetId, SelectedCampaign.Gm,
                ownedCharacters);
        }
    }

    public CharacterSummary? PlaySelectedCharacter
    {
        get
        {
            var playSelectedCampaign = PlaySelectedCampaign;
            if (playSelectedCampaign is null || playSelectedCampaign.Characters.Length == 0)
                return null;

            if (SelectedCharacterId.HasValue)
            {
                var selectedCharacter =
                    playSelectedCampaign.Characters.FirstOrDefault(character =>
                        character.Id == SelectedCharacterId.Value);
                if (selectedCharacter is not null)
                    return selectedCharacter;
            }

            if (ActiveCharacterId.HasValue)
            {
                var activeCharacter =
                    playSelectedCampaign.Characters.FirstOrDefault(character =>
                        character.Id == ActiveCharacterId.Value);
                if (activeCharacter is not null)
                    return activeCharacter;
            }

            return playSelectedCampaign.Characters[0];
        }
    }

    public Guid? PlaySelectedCharacterId => PlaySelectedCharacter?.Id;

    public List<CharacterSheetSkill> PlaySelectedCharacterSkills =>
        PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue ? [] : SelectedCharacterSkills;

    public List<CharacterSheetSkillGroup> PlaySelectedCharacterSkillGroups =>
        PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue ? [] : SelectedCharacterSkillGroups;

    public List<CampaignLogListEntry> PlayVisibleCampaignLog => CampaignLog;

    public bool IsCurrentUserGm =>
        SelectedCampaign is not null && User is not null && SelectedCampaign.Gm.Id == User.Id;

    public bool IsCurrentUserAdmin =>
        User is not null && User.Roles.Contains(UserRoles.Admin, StringComparer.OrdinalIgnoreCase);

    public bool CanDeleteSelectedCampaign =>
        SelectedCampaign is not null && User is not null && (SelectedCampaign.Gm.Id == User.Id || IsCurrentUserAdmin);

    public bool IsSelectedCampaignD6 =>
        string.Equals(SelectedCampaign?.RulesetId, "d6", StringComparison.OrdinalIgnoreCase);

    public string ConnectionStateLabel => ConnectionState switch
    {
        "connected" => "Connected",
        "reconnecting" => "Reconnecting",
        _ => "Offline fallback"
    };

    public string ConnectionStateCssClass => ConnectionState switch
    {
        "connected" => "ok",
        "reconnecting" => "warn",
        _ => "offline"
    };
}