package guilds

import (
	"context"
	"time"
)

// GuildDatabase defines database operations for guilds
type GuildDatabase interface {
	// LoadGuilds retrieves all guilds from database
	LoadGuilds(ctx context.Context) ([]GuildData, error)

	// LoadGuild retrieves a specific guild from database
	LoadGuild(ctx context.Context, guildID int32) (*GuildData, error)

	// LoadGuildMembers retrieves all members for a guild
	LoadGuildMembers(ctx context.Context, guildID int32) ([]GuildMemberData, error)

	// LoadGuildEvents retrieves events for a guild
	LoadGuildEvents(ctx context.Context, guildID int32) ([]GuildEventData, error)

	// LoadGuildRanks retrieves custom rank names for a guild
	LoadGuildRanks(ctx context.Context, guildID int32) ([]GuildRankData, error)

	// LoadGuildPermissions retrieves permissions for a guild
	LoadGuildPermissions(ctx context.Context, guildID int32) ([]GuildPermissionData, error)

	// LoadGuildEventFilters retrieves event filters for a guild
	LoadGuildEventFilters(ctx context.Context, guildID int32) ([]GuildEventFilterData, error)

	// LoadGuildRecruiting retrieves recruiting settings for a guild
	LoadGuildRecruiting(ctx context.Context, guildID int32) ([]GuildRecruitingData, error)

	// LoadPointHistory retrieves point history for a member
	LoadPointHistory(ctx context.Context, characterID int32) ([]PointHistoryData, error)

	// SaveGuild saves guild basic data
	SaveGuild(ctx context.Context, guild *Guild) error

	// SaveGuildMembers saves all guild members
	SaveGuildMembers(ctx context.Context, guildID int32, members []*GuildMember) error

	// SaveGuildEvents saves guild events
	SaveGuildEvents(ctx context.Context, guildID int32, events []GuildEvent) error

	// SaveGuildRanks saves guild rank names
	SaveGuildRanks(ctx context.Context, guildID int32, ranks map[int8]string) error

	// SaveGuildPermissions saves guild permissions
	SaveGuildPermissions(ctx context.Context, guildID int32, permissions map[int8]map[int8]int8) error

	// SaveGuildEventFilters saves guild event filters
	SaveGuildEventFilters(ctx context.Context, guildID int32, filters map[int8]map[int8]int8) error

	// SaveGuildRecruiting saves guild recruiting settings
	SaveGuildRecruiting(ctx context.Context, guildID int32, flags, descTags map[int8]int8) error

	// SavePointHistory saves point history for a member
	SavePointHistory(ctx context.Context, characterID int32, history []PointHistory) error

	// GetGuildIDByCharacterID returns guild ID for a character
	GetGuildIDByCharacterID(ctx context.Context, characterID int32) (int32, error)

	// CreateGuild creates a new guild
	CreateGuild(ctx context.Context, guildData GuildData) (int32, error)

	// DeleteGuild removes a guild and all related data
	DeleteGuild(ctx context.Context, guildID int32) error

	// GetNextGuildID returns the next available guild ID
	GetNextGuildID(ctx context.Context) (int32, error)

	// GetNextEventID returns the next available event ID for a guild
	GetNextEventID(ctx context.Context, guildID int32) (int64, error)
}

// ClientManager handles client communication for guilds
type ClientManager interface {
	// SendGuildUpdate sends guild information update to client
	SendGuildUpdate(characterID int32, guild *Guild) error

	// SendGuildMemberList sends guild member list to client
	SendGuildMemberList(characterID int32, members []MemberInfo) error

	// SendGuildMember sends single member info to client
	SendGuildMember(characterID int32, member *GuildMember) error

	// SendGuildMOTD sends message of the day to client
	SendGuildMOTD(characterID int32, motd string) error

	// SendGuildEvent sends guild event to client
	SendGuildEvent(characterID int32, event *GuildEvent) error

	// SendGuildEventList sends guild event list to client
	SendGuildEventList(characterID int32, events []GuildEventInfo) error

	// SendGuildChatMessage sends guild chat message to client
	SendGuildChatMessage(characterID int32, senderName, message string, language int8) error

	// SendOfficerChatMessage sends officer chat message to client
	SendOfficerChatMessage(characterID int32, senderName, message string, language int8) error

	// SendGuildInvite sends guild invitation to client
	SendGuildInvite(characterID int32, invite GuildInvite) error

	// SendGuildRecruitingInfo sends recruiting information to client
	SendGuildRecruitingInfo(characterID int32, info RecruitingInfo) error

	// SendGuildPermissions sends guild permissions to client
	SendGuildPermissions(characterID int32, permissions map[int8]map[int8]int8) error

	// IsClientOnline checks if a character is currently online
	IsClientOnline(characterID int32) bool

	// GetClientLanguage returns the language setting for a client
	GetClientLanguage(characterID int32) int8
}

// PlayerManager provides player information for guilds
type PlayerManager interface {
	// GetPlayerInfo retrieves basic player information
	GetPlayerInfo(characterID int32) (PlayerInfo, error)

	// IsPlayerOnline checks if a player is currently online
	IsPlayerOnline(characterID int32) bool

	// GetPlayerZone returns the current zone for a player
	GetPlayerZone(characterID int32) string

	// GetPlayerLevel returns player's current level
	GetPlayerLevel(characterID int32) (int8, int8) // adventure, tradeskill

	// GetPlayerClass returns player's current class
	GetPlayerClass(characterID int32) (int8, int8) // adventure, tradeskill

	// GetPlayerName returns player's character name
	GetPlayerName(characterID int32) string

	// ValidatePlayerExists checks if a player exists
	ValidatePlayerExists(characterName string) (int32, error)

	// GetAccountID returns the account ID for a character
	GetAccountID(characterID int32) int32
}

// GuildEventHandler handles guild-related events
type GuildEventHandler interface {
	// OnGuildCreated called when a guild is created
	OnGuildCreated(guild *Guild)

	// OnGuildDeleted called when a guild is deleted
	OnGuildDeleted(guildID int32, guildName string)

	// OnMemberJoined called when a member joins a guild
	OnMemberJoined(guild *Guild, member *GuildMember, inviterName string)

	// OnMemberLeft called when a member leaves a guild
	OnMemberLeft(guild *Guild, member *GuildMember, reason string)

	// OnMemberPromoted called when a member is promoted
	OnMemberPromoted(guild *Guild, member *GuildMember, oldRank, newRank int8, promoterName string)

	// OnMemberDemoted called when a member is demoted
	OnMemberDemoted(guild *Guild, member *GuildMember, oldRank, newRank int8, demoterName string)

	// OnPointsAwarded called when points are awarded to members
	OnPointsAwarded(guild *Guild, members []int32, points float64, comment, awardedBy string)

	// OnGuildEvent called when a guild event occurs
	OnGuildEvent(guild *Guild, event *GuildEvent)

	// OnGuildLevelUp called when a guild levels up
	OnGuildLevelUp(guild *Guild, oldLevel, newLevel int8)

	// OnGuildChatMessage called when a guild chat message is sent
	OnGuildChatMessage(guild *Guild, senderID int32, senderName, message string, language int8)

	// OnOfficerChatMessage called when an officer chat message is sent
	OnOfficerChatMessage(guild *Guild, senderID int32, senderName, message string, language int8)
}

// LogHandler provides logging functionality
type LogHandler interface {
	// LogDebug logs debug messages
	LogDebug(category, message string, args ...interface{})

	// LogInfo logs informational messages
	LogInfo(category, message string, args ...interface{})

	// LogError logs error messages
	LogError(category, message string, args ...interface{})

	// LogWarning logs warning messages
	LogWarning(category, message string, args ...interface{})
}

// PlayerInfo contains basic player information
type PlayerInfo struct {
	CharacterID     int32     `json:"character_id"`
	CharacterName   string    `json:"character_name"`
	AccountID       int32     `json:"account_id"`
	AdventureLevel  int8      `json:"adventure_level"`
	AdventureClass  int8      `json:"adventure_class"`
	TradeskillLevel int8      `json:"tradeskill_level"`
	TradeskillClass int8      `json:"tradeskill_class"`
	Zone            string    `json:"zone"`
	IsOnline        bool      `json:"is_online"`
	LastLogin       time.Time `json:"last_login"`
}

// GuildAware interface for entities that can participate in guilds
type GuildAware interface {
	GetCharacterID() int32
	GetGuildID() int32
	GetGuildRank() int8
	IsInGuild() bool
	HasGuildPermission(permission int8) bool
}

// EntityGuildAdapter adapts entities to work with guild system
type EntityGuildAdapter struct {
	entity interface {
		GetID() int32
		// Add other entity methods as needed
	}
	guildManager *GuildManager
}

// GetCharacterID returns the character ID from the adapted entity
func (a *EntityGuildAdapter) GetCharacterID() int32 {
	return a.entity.GetID()
}

// GetGuildID returns the guild ID for the character
func (a *EntityGuildAdapter) GetGuildID() int32 {
	// TODO: Implement guild lookup through guild manager
	return 0
}

// GetGuildRank returns the guild rank for the character
func (a *EntityGuildAdapter) GetGuildRank() int8 {
	// TODO: Implement rank lookup through guild manager
	return RankRecruit
}

// IsInGuild checks if the character is in a guild
func (a *EntityGuildAdapter) IsInGuild() bool {
	return a.GetGuildID() > 0
}

// HasGuildPermission checks if the character has a specific guild permission
func (a *EntityGuildAdapter) HasGuildPermission(permission int8) bool {
	// TODO: Implement permission checking through guild manager
	return false
}

// InviteManager handles guild invitations
type InviteManager interface {
	// SendInvite sends a guild invitation
	SendInvite(guildID, characterID, inviterID int32, rank int8) error

	// AcceptInvite accepts a guild invitation
	AcceptInvite(characterID, guildID int32) error

	// DeclineInvite declines a guild invitation
	DeclineInvite(characterID, guildID int32) error

	// GetPendingInvites returns pending invites for a character
	GetPendingInvites(characterID int32) ([]GuildInvite, error)

	// ClearExpiredInvites removes expired invitations
	ClearExpiredInvites() error
}

// PermissionChecker provides permission validation
type PermissionChecker interface {
	// CanInvite checks if a member can invite players
	CanInvite(guild *Guild, memberRank int8) bool

	// CanRemoveMember checks if a member can remove other members
	CanRemoveMember(guild *Guild, memberRank, targetRank int8) bool

	// CanPromote checks if a member can promote other members
	CanPromote(guild *Guild, memberRank, targetRank int8) bool

	// CanDemote checks if a member can demote other members
	CanDemote(guild *Guild, memberRank, targetRank int8) bool

	// CanEditPermissions checks if a member can edit guild permissions
	CanEditPermissions(guild *Guild, memberRank int8) bool

	// CanUseBankSlot checks if a member can access a specific bank slot
	CanUseBankSlot(guild *Guild, memberRank int8, bankSlot int, action string) bool

	// CanSpeakInOfficerChat checks if a member can speak in officer chat
	CanSpeakInOfficerChat(guild *Guild, memberRank int8) bool

	// CanAssignPoints checks if a member can assign guild points
	CanAssignPoints(guild *Guild, memberRank int8) bool
}

// NotificationManager handles guild notifications
type NotificationManager interface {
	// NotifyMemberLogin notifies guild of member login
	NotifyMemberLogin(guild *Guild, member *GuildMember)

	// NotifyMemberLogout notifies guild of member logout
	NotifyMemberLogout(guild *Guild, member *GuildMember)

	// NotifyGuildMessage sends a message to all guild members
	NotifyGuildMessage(guild *Guild, eventType int8, message string, args ...interface{})

	// NotifyOfficers sends a message to officers only
	NotifyOfficers(guild *Guild, message string, args ...interface{})

	// NotifyGuildUpdate notifies guild members of guild changes
	NotifyGuildUpdate(guild *Guild)
}

// BankManager handles guild bank operations
type BankManager interface {
	// GetBankContents returns contents of a guild bank
	GetBankContents(guildID int32, bankSlot int) ([]BankItem, error)

	// DepositItem deposits an item into guild bank
	DepositItem(guildID int32, bankSlot int, item BankItem, depositorID int32) error

	// WithdrawItem withdraws an item from guild bank
	WithdrawItem(guildID int32, bankSlot int, itemSlot int, withdrawerID int32) error

	// LogBankEvent logs a bank event
	LogBankEvent(guildID int32, bankSlot int, eventType int32, description string) error

	// GetBankEventHistory returns bank event history
	GetBankEventHistory(guildID int32, bankSlot int) ([]GuildBankEvent, error)
}

// BankItem represents an item in the guild bank
type BankItem struct {
	Slot        int       `json:"slot"`
	ItemID      int32     `json:"item_id"`
	Quantity    int32     `json:"quantity"`
	DepositorID int32     `json:"depositor_id"`
	DepositDate time.Time `json:"deposit_date"`
}
