using GmRelay.Shared.Domain;
using GmRelay.Shared.Features.Showcase;

namespace GmRelay.Web.Services;

public sealed record PlayerAttendanceStats(
    Guid PlayerId,
    string DisplayName,
    string? ExternalUsername,
    long TotalSessions,
    long ConfirmedCount,
    long DeclinedCount,
    long NoResponseCount,
    long WaitlistedCount,
    long CancellationAffectedCount,
    decimal AttendanceRate);

public sealed record SessionAuditLogEntry(
    Guid Id,
    Guid SessionId,
    string ActorExternalUserId,
    string ActorName,
    string ChangeType,
    string? OldValue,
    string? NewValue,
    DateTime ChangedAt);

public sealed record WebPublicGroupSettings(
    Guid GroupId,
    string GroupName,
    string? PublicSlug,
    bool PublicScheduleEnabled,
    int PublicSessionCount);

public sealed record WebPublicSession(
    Guid Id,
    Guid GroupId,
    string GroupName,
    string? GroupSlug,
    string Title,
    DateTime ScheduledAt,
    string Status,
    int? MaxPlayers,
    int ActivePlayerCount,
    int WaitlistedPlayerCount,
    string PublicationMode = PublicationModeExtensions.NoneValue,
    bool IsMembersOnly = false,
    string? MasterProfileSlug = null,
    string? MasterDisplayName = null);

public sealed record WebMembership(
    Guid MembershipId,
    Guid GroupId,
    string GroupName,
    string? GroupSlug,
    string Status,
    string Role,
    string? Message,
    DateTime AppliedAt,
    DateTime? DecidedAt,
    string? DecidedByDisplayName);

public sealed record WebPendingApplication(
    Guid MembershipId,
    Guid PlayerId,
    string DisplayName,
    string Platform,
    string? ExternalUsername,
    string? Message,
    DateTime AppliedAt);

public sealed record WebClubShowcaseSession(
    Guid Id,
    string Title,
    DateTime ScheduledAt,
    string Status,
    string? System,
    bool IsOneShot,
    string? Format,
    int? DurationMinutes,
    string? CoverImageUrl,
    int? MaxPlayers,
    int ActivePlayerCount,
    int WaitlistedPlayerCount,
    string PublicationMode,
    bool IsMembersOnly,
    string? Description,
    bool AllowDirectRegistration);

public sealed record WebPublicClub(
    Guid GroupId,
    string Name,
    string Slug,
    IReadOnlyList<WebPublicSession> Sessions,
    string? MasterProfileSlug = null,
    string? MasterDisplayName = null);

public sealed record MasterProfileSettings(
    Guid PlayerId,
    string DisplayName,
    string? PublicSlug,
    bool IsPublic,
    string? Bio);

public sealed record PublicMasterClub(
    Guid GroupId,
    string Name,
    string Slug);

public sealed record PublicMasterProfile(
    string Slug,
    string DisplayName,
    string? Bio,
    IReadOnlyList<PublicMasterClub> Clubs,
    IReadOnlyList<WebPublicSession> Sessions);

public interface ISessionStore
{
    Task<List<WebGameGroup>> GetGroupsForUserAsync(string platform, string externalUserId);
    Task<WebGameGroup?> GetGroupAsync(Guid groupId);
    Task<WebPublicGroupSettings?> GetPublicGroupSettingsAsync(Guid groupId);
    Task UpdatePublicGroupSettingsAsync(Guid groupId, string? publicSlug, bool publicScheduleEnabled);
    Task SetSessionPublicationModeAsync(Guid sessionId, Guid groupId, PublicationMode mode);
    Task SetBatchPublicationModeAsync(Guid batchId, Guid groupId, PublicationMode mode);
    Task<WebPublicClub?> GetPublicClubBySlugAsync(string slug, Guid? viewerPlayerId);
    Task<WebPublicSession?> GetPublicSessionAsync(Guid sessionId, Guid? viewerPlayerId);
    Task<bool> IsGroupManagerAsync(Guid groupId, string platform, string externalUserId);
    Task<bool> IsGroupOwnerAsync(Guid groupId, string platform, string externalUserId);
    Task<bool> IsActiveClubMemberAsync(Guid groupId, Guid playerId);
    Task<Guid?> GetPlayerIdByPlatformIdentityAsync(string platform, string externalUserId);
    Task<List<WebGroupManager>> GetGroupManagersAsync(Guid groupId);
    Task<List<WebSession>> GetUpcomingSessionsAsync(Guid groupId);
    Task<WebSession?> GetSessionAsync(Guid sessionId);
    Task<WebSessionBatch?> GetBatchAsync(Guid batchId);
    Task UpdateSessionAsync(Guid sessionId, Guid groupId, string title, DateTime scheduledAt, string joinLink, int? maxPlayers);
    Task PromoteWaitlistedPlayerAsync(Guid sessionId, Guid groupId);
    Task UpdateBatchDetailsAsync(Guid batchId, Guid groupId, string title, string joinLink);
    Task UpdateBatchNotificationModeAsync(Guid batchId, Guid groupId, SessionNotificationMode notificationMode);
    Task RescheduleBatchAsync(Guid batchId, Guid groupId, DateTime firstScheduledAt, int intervalDays);
    Task<WebSessionBatch> CloneBatchAsync(Guid batchId, Guid groupId, BatchCloneInterval interval);
    Task<List<WebCampaignTemplate>> GetCampaignTemplatesAsync(Guid groupId);
    Task<WebCampaignTemplate?> GetCampaignTemplateAsync(Guid templateId);
    Task<WebCampaignTemplate> CreateCampaignTemplateAsync(Guid groupId, CreateCampaignTemplateRequest request);
    Task DeleteCampaignTemplateAsync(Guid templateId, Guid groupId);
    Task<WebSessionBatch> CreateBatchFromTemplateAsync(Guid templateId, Guid groupId, DateTime firstScheduledAt);
    Task AddGroupCoGmAsync(Guid groupId, string ownerPlatform, string ownerExternalUserId, string coGmPlatform, string coGmExternalUserId, string displayName, string? externalUsername);
    Task RemoveGroupCoGmAsync(Guid groupId, string coGmPlatform, string coGmExternalUserId);
    Task<List<WebParticipant>> GetSessionParticipantsAsync(Guid sessionId);
    Task RemovePlayerFromSessionAsync(Guid sessionId, Guid groupId, Guid participantId);
    Task<List<PlayerAttendanceStats>> GetGroupAttendanceStatsAsync(Guid groupId);
    Task LogSessionChangeAsync(Guid sessionId, string actorExternalUserId, string actorName, string changeType, string? oldValue, string? newValue);
    Task<List<SessionAuditLogEntry>> GetSessionHistoryAsync(Guid sessionId);
    Task UpsertDiscordUserAsync(string discordId, string displayName, string? avatarUrl);
    Task<MasterProfileSettings?> GetMasterProfileSettingsAsync(string platform, string externalUserId);
    Task UpdateMasterProfileSettingsAsync(string platform, string externalUserId, string? publicSlug, bool isPublic, string displayName, string? bio);
    Task<PublicMasterProfile?> GetPublicMasterProfileBySlugAsync(string slug, Guid? viewerPlayerId);

    // --- Identity linking (issue #35) ---
    Task<Guid?> ResolveEffectivePlayerIdAsync(string platform, string externalUserId);
    Task<List<LinkedIdentity>> GetLinkedIdentitiesAsync(string platform, string externalUserId);
    Task LinkIdentityAsync(string currentPlatform, string currentExternalUserId, string targetPlatform, string targetExternalUserId, string? currentName);
    Task UnlinkIdentityAsync(string currentPlatform, string currentExternalUserId, string targetPlatform, string targetExternalUserId);
    Task UpsertPlayerAsync(string platform, string externalUserId, string displayName, string? avatarUrl);

    // --- Showcase / game catalog (issue #39) ---
    Task<IReadOnlyList<ShowcaseSessionDto>> GetShowcaseSessionsAsync(ShowcaseFilter filter, int page, int pageSize);
    Task<ShowcaseSessionDto?> GetShowcaseSessionAsync(Guid sessionId);
    Task<bool> RegisterFromShowcaseAsync(Guid sessionId, string platform, string externalUserId, string displayName);

    // --- Private club showcases / memberships (issue #110) ---
    Task<IReadOnlyList<WebClubShowcaseSession>> GetClubShowcaseSessionsAsync(Guid groupId, Guid? viewerPlayerId, int page, int pageSize);
    Task<int> GetPendingApplicationsCountAsync(Guid groupId);
    Task<List<WebPendingApplication>> GetPendingApplicationsAsync(Guid groupId);
    Task<List<WebMembership>> GetMembershipsForPlayerAsync(Guid playerId);
    Task<Guid> ApplyForMembershipAsync(Guid groupId, Guid playerId, string? message);
    Task ApproveMembershipAsync(Guid membershipId, Guid approverPlayerId);
    Task RejectMembershipAsync(Guid membershipId, Guid approverPlayerId);
    Task LeaveClubMembershipAsync(Guid membershipId, Guid playerId);
    Task<Guid?> GetGroupIdForMembershipAsync(Guid membershipId);
}

public sealed record LinkedIdentity(
    string Platform,
    string ExternalUserId,
    string DisplayName,
    string? ExternalUsername,
    string? AvatarUrl,
    DateTime LinkedAt);
