package housing

import (
	"context"
	"time"
)

// HousingDatabase defines the interface for database operations
type HousingDatabase interface {
	// House zone operations
	LoadHouseZones(ctx context.Context) ([]HouseZoneData, error)
	LoadHouseZone(ctx context.Context, houseID int32) (*HouseZoneData, error)
	SaveHouseZone(ctx context.Context, zone *HouseZone) error
	DeleteHouseZone(ctx context.Context, houseID int32) error

	// Player house operations
	LoadPlayerHouses(ctx context.Context, characterID int32) ([]PlayerHouseData, error)
	LoadPlayerHouse(ctx context.Context, uniqueID int64) (*PlayerHouseData, error)
	SavePlayerHouse(ctx context.Context, house *PlayerHouse) error
	DeletePlayerHouse(ctx context.Context, uniqueID int64) error
	AddPlayerHouse(ctx context.Context, houseData PlayerHouseData) (int64, error)

	// Deposit operations
	LoadDeposits(ctx context.Context, houseID int64) ([]HouseDepositData, error)
	SaveDeposit(ctx context.Context, houseID int64, deposit HouseDeposit) error

	// History operations
	LoadHistory(ctx context.Context, houseID int64) ([]HouseHistoryData, error)
	AddHistory(ctx context.Context, houseID int64, history HouseHistory) error

	// Access operations
	LoadHouseAccess(ctx context.Context, houseID int64) ([]HouseAccessData, error)
	SaveHouseAccess(ctx context.Context, houseID int64, access []HouseAccess) error
	DeleteHouseAccess(ctx context.Context, houseID int64, characterID int32) error

	// Amenity operations
	LoadHouseAmenities(ctx context.Context, houseID int64) ([]HouseAmenityData, error)
	SaveHouseAmenity(ctx context.Context, houseID int64, amenity HouseAmenity) error
	DeleteHouseAmenity(ctx context.Context, houseID int64, amenityID int32) error

	// Item operations
	LoadHouseItems(ctx context.Context, houseID int64) ([]HouseItemData, error)
	SaveHouseItem(ctx context.Context, houseID int64, item HouseItem) error
	DeleteHouseItem(ctx context.Context, houseID int64, itemID int64) error

	// Utility operations
	GetNextHouseID(ctx context.Context) (int64, error)
	GetHouseByInstance(ctx context.Context, instanceID int32) (*PlayerHouseData, error)
	UpdateHouseUpkeepDue(ctx context.Context, houseID int64, upkeepDue time.Time) error
	UpdateHouseEscrow(ctx context.Context, houseID int64, coins, status int64) error
	GetHousesForUpkeep(ctx context.Context, cutoffTime time.Time) ([]PlayerHouseData, error)
	GetHouseStatistics(ctx context.Context) (*HousingStatistics, error)
	EnsureHousingTables(ctx context.Context) error
}

// HousingEventHandler defines the interface for handling housing events
type HousingEventHandler interface {
	// House lifecycle events
	OnHousePurchased(house *PlayerHouse, purchaser int32, cost int64, statusCost int64)
	OnHouseForeclosed(house *PlayerHouse, reason string)
	OnHouseTransferred(house *PlayerHouse, fromCharacterID, toCharacterID int32)
	OnHouseAbandoned(house *PlayerHouse, characterID int32)

	// Financial events
	OnDepositMade(house *PlayerHouse, characterID int32, amount int64, status int64)
	OnWithdrawalMade(house *PlayerHouse, characterID int32, amount int64, status int64)
	OnUpkeepPaid(house *PlayerHouse, amount int64, status int64, automatic bool)
	OnUpkeepOverdue(house *PlayerHouse, daysPastDue int)

	// Access events
	OnAccessGranted(house *PlayerHouse, grantedTo int32, grantedBy int32, accessLevel int8)
	OnAccessRevoked(house *PlayerHouse, revokedFrom int32, revokedBy int32)
	OnPlayerEntered(house *PlayerHouse, characterID int32)
	OnPlayerExited(house *PlayerHouse, characterID int32)

	// Item events
	OnItemPlaced(house *PlayerHouse, item *HouseItem, placedBy int32)
	OnItemRemoved(house *PlayerHouse, item *HouseItem, removedBy int32)
	OnItemMoved(house *PlayerHouse, item *HouseItem, movedBy int32)

	// Amenity events
	OnAmenityPurchased(house *PlayerHouse, amenity *HouseAmenity, purchasedBy int32)
	OnAmenityRemoved(house *PlayerHouse, amenity *HouseAmenity, removedBy int32)
}

// ClientManager defines the interface for client communication
type ClientManager interface {
	// Send housing packets to clients
	SendHousePurchase(characterID int32, data *HousePurchasePacketData) error
	SendHousingList(characterID int32, data *HouseListPacketData) error
	SendBaseHouseWindow(characterID int32, data *BaseHouseWindowPacketData) error
	SendHouseVisitWindow(characterID int32, data *HouseVisitPacketData) error
	SendHouseUpdate(characterID int32, house *PlayerHouse) error
	SendHouseError(characterID int32, errorCode int, message string) error

	// Broadcast to multiple clients
	BroadcastHouseUpdate(characterIDs []int32, house *PlayerHouse) error
	BroadcastHouseEvent(characterIDs []int32, eventType int, data string) error

	// Client validation
	IsClientConnected(characterID int32) bool
	GetClientVersion(characterID int32) int
}

// PlayerManager defines the interface for player system integration
type PlayerManager interface {
	// Get player information
	GetPlayerInfo(characterID int32) (*PlayerInfo, error)
	GetPlayerName(characterID int32) string
	GetPlayerAlignment(characterID int32) int8
	GetPlayerGuildLevel(characterID int32) int8
	IsPlayerOnline(characterID int32) bool

	// Player finances
	GetPlayerCoins(characterID int32) (int64, error)
	GetPlayerStatus(characterID int32) (int64, error)
	DeductPlayerCoins(characterID int32, amount int64) error
	DeductPlayerStatus(characterID int32, amount int64) error
	AddPlayerCoins(characterID int32, amount int64) error
	AddPlayerStatus(characterID int32, amount int64) error

	// Player validation
	CanPlayerAffordHouse(characterID int32, cost int64, statusCost int64) (bool, error)
	ValidatePlayerExists(playerName string) (int32, error)
}

// ItemManager defines the interface for item system integration
type ItemManager interface {
	// Item operations
	GetItemInfo(itemID int32) (*ItemInfo, error)
	ValidateItemPlacement(itemID int32, x, y, z float32) error
	CreateHouseItem(itemID int32, characterID int32, quantity int32) (*HouseItem, error)
	RemoveItemFromPlayer(characterID int32, itemID int32, quantity int32) error
	ReturnItemToPlayer(characterID int32, item *HouseItem) error

	// Item queries
	IsItemPlaceable(itemID int32) bool
	GetItemWeight(itemID int32) float32
	GetItemValue(itemID int32) int64
}

// ZoneManager defines the interface for zone system integration
type ZoneManager interface {
	// Zone operations
	GetZoneInfo(zoneID int32) (*ZoneInfo, error)
	CreateHouseInstance(houseID int32, ownerID int32) (int32, error)
	DestroyHouseInstance(instanceID int32) error
	GetHouseInstance(instanceID int32) (*HouseInstance, error)

	// Player zone operations
	MovePlayerToHouse(characterID int32, instanceID int32) error
	GetPlayersInHouse(instanceID int32) ([]int32, error)
	IsPlayerInHouse(characterID int32) (bool, int32)

	// Zone validation
	IsHouseZoneValid(zoneID int32) bool
	GetHouseSpawnPoint(instanceID int32) (float32, float32, float32, float32, error)
}

// LogHandler defines the interface for logging operations
type LogHandler interface {
	LogDebug(system, format string, args ...interface{})
	LogInfo(system, format string, args ...interface{})
	LogWarning(system, format string, args ...interface{})
	LogError(system, format string, args ...interface{})
}

// Additional integration interfaces

// PlayerInfo contains player details needed for housing system
type PlayerInfo struct {
	CharacterID    int32  `json:"character_id"`
	CharacterName  string `json:"character_name"`
	AccountID      int32  `json:"account_id"`
	AdventureLevel int16  `json:"adventure_level"`
	Alignment      int8   `json:"alignment"`
	GuildID        int32  `json:"guild_id"`
	GuildLevel     int8   `json:"guild_level"`
	Zone           string `json:"zone"`
	IsOnline       bool   `json:"is_online"`
	HouseZoneID    int32  `json:"house_zone_id"`
}

// ItemInfo contains item details for placement validation
type ItemInfo struct {
	ID          int32   `json:"id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Icon        int16   `json:"icon"`
	Weight      float32 `json:"weight"`
	Value       int64   `json:"value"`
	IsPlaceable bool    `json:"is_placeable"`
	MaxStack    int32   `json:"max_stack"`
	Type        int8    `json:"type"`
}

// ZoneInfo contains zone details for house instances
type ZoneInfo struct {
	ID          int32   `json:"id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Type        int8    `json:"type"`
	MinLevel    int16   `json:"min_level"`
	MaxLevel    int16   `json:"max_level"`
	SafeX       float32 `json:"safe_x"`
	SafeY       float32 `json:"safe_y"`
	SafeZ       float32 `json:"safe_z"`
	SafeHeading float32 `json:"safe_heading"`
}

// HouseInstance contains active house instance information
type HouseInstance struct {
	InstanceID      int32     `json:"instance_id"`
	HouseID         int64     `json:"house_id"`
	OwnerID         int32     `json:"owner_id"`
	ZoneID          int32     `json:"zone_id"`
	CreatedTime     time.Time `json:"created_time"`
	LastActivity    time.Time `json:"last_activity"`
	CurrentVisitors []int32   `json:"current_visitors"`
	IsActive        bool      `json:"is_active"`
}

// Adapter interfaces for integration with existing systems

// HousingAware defines interface for entities that can interact with housing
type HousingAware interface {
	GetCharacterID() int32
	GetPlayerName() string
	GetAlignment() int8
	GetGuildLevel() int8
	CanAffordCost(coins int64, status int64) bool
	GetCurrentZone() int32
}

// EntityHousingAdapter adapts entity system for housing integration
type EntityHousingAdapter struct {
	entity HousingAware
}

// PacketBuilder defines interface for building housing packets
type PacketBuilder interface {
	BuildHousePurchasePacket(data *HousePurchasePacketData) ([]byte, error)
	BuildHousingListPacket(data *HouseListPacketData) ([]byte, error)
	BuildBaseHouseWindowPacket(data *BaseHouseWindowPacketData) ([]byte, error)
	BuildHouseVisitPacket(data *HouseVisitPacketData) ([]byte, error)
	BuildHouseUpdatePacket(house *PlayerHouse) ([]byte, error)
	BuildHouseErrorPacket(errorCode int, message string) ([]byte, error)
}

// UpkeepManager defines interface for upkeep processing
type UpkeepManager interface {
	ProcessUpkeep(ctx context.Context) error
	ProcessForeclosures(ctx context.Context) error
	SendUpkeepNotices(ctx context.Context) error
	CalculateUpkeep(house *PlayerHouse, zone *HouseZone) (int64, int64, error)
	CanPayUpkeep(house *PlayerHouse, coinCost, statusCost int64) bool
	ProcessPayment(ctx context.Context, house *PlayerHouse, coinCost, statusCost int64) error
}

// StatisticsCollector defines interface for collecting housing statistics
type StatisticsCollector interface {
	RecordHousePurchase(houseType int32, cost int64, statusCost int64)
	RecordDeposit(houseID int64, amount int64, status int64)
	RecordWithdrawal(houseID int64, amount int64, status int64)
	RecordUpkeepPayment(houseID int64, amount int64, status int64)
	RecordForeclosure(houseID int64, reason string)
	GetStatistics() *HousingStatistics
	Reset()
}

// AccessManager defines interface for managing house access
type AccessManager interface {
	GrantAccess(ctx context.Context, house *PlayerHouse, characterID int32, accessLevel int8, permissions int32) error
	RevokeAccess(ctx context.Context, house *PlayerHouse, characterID int32) error
	CheckAccess(house *PlayerHouse, characterID int32, requiredPermission int32) bool
	GetAccessLevel(house *PlayerHouse, characterID int32) int8
	GetPermissions(house *PlayerHouse, characterID int32) int32
	UpdateAccess(ctx context.Context, house *PlayerHouse, characterID int32, accessLevel int8, permissions int32) error
}

// ConfigManager defines interface for configuration management
type ConfigManager interface {
	GetHousingConfig() *HousingConfig
	UpdateHousingConfig(config *HousingConfig) error
	GetConfigValue(key string) interface{}
	SetConfigValue(key string, value interface{}) error
}

// NotificationManager defines interface for housing notifications
type NotificationManager interface {
	SendUpkeepReminder(characterID int32, house *PlayerHouse, daysRemaining int)
	SendForeclosureWarning(characterID int32, house *PlayerHouse, daysRemaining int)
	SendAccessGrantedNotification(characterID int32, house *PlayerHouse, grantedBy int32)
	SendAccessRevokedNotification(characterID int32, house *PlayerHouse, revokedBy int32)
	SendHouseVisitorNotification(ownerID int32, visitorID int32, house *PlayerHouse)
}

// CacheManager defines interface for caching operations
type CacheManager interface {
	// Cache operations
	Set(key string, value interface{}, expiration time.Duration) error
	Get(key string) (interface{}, bool)
	Delete(key string) error
	Clear() error

	// House-specific cache operations
	CachePlayerHouses(characterID int32, houses []*PlayerHouse) error
	GetCachedPlayerHouses(characterID int32) ([]*PlayerHouse, bool)
	InvalidateHouseCache(houseID int64) error
}

// SearchManager defines interface for house searching
type SearchManager interface {
	SearchHouses(criteria HousingSearchCriteria) ([]*PlayerHouse, error)
	SearchHouseZones(criteria HousingSearchCriteria) ([]*HouseZone, error)
	GetPopularHouses(limit int) ([]*PlayerHouse, error)
	GetRecentHouses(limit int) ([]*PlayerHouse, error)
	IndexHouseForSearch(house *PlayerHouse) error
	RemoveHouseFromIndex(houseID int64) error
}
