package housing

import (
	"context"
	"fmt"
	"time"

	"eq2emu/internal/database"
)

// DatabaseHousingManager implements HousingDatabase interface using the existing database wrapper
type DatabaseHousingManager struct {
	db *database.DB
}

// NewDatabaseHousingManager creates a new database housing manager
func NewDatabaseHousingManager(db *database.DB) *DatabaseHousingManager {
	return &DatabaseHousingManager{
		db: db,
	}
}

// LoadHouseZones retrieves all available house types from database
func (dhm *DatabaseHousingManager) LoadHouseZones(ctx context.Context) ([]HouseZoneData, error) {
	query := `SELECT id, name, zone_id, cost_coin, cost_status, upkeep_coin, upkeep_status,
			  alignment, guild_level, vault_slots, max_items, max_visitors, upkeep_period, description
			  FROM houses ORDER BY id`

	rows, err := dhm.db.QueryContext(ctx, query)
	if err != nil {
		return nil, fmt.Errorf("failed to query house zones: %w", err)
	}
	defer rows.Close()

	var zones []HouseZoneData
	for rows.Next() {
		var zone HouseZoneData
		var description *string

		err := rows.Scan(
			&zone.ID,
			&zone.Name,
			&zone.ZoneID,
			&zone.CostCoin,
			&zone.CostStatus,
			&zone.UpkeepCoin,
			&zone.UpkeepStatus,
			&zone.Alignment,
			&zone.GuildLevel,
			&zone.VaultSlots,
			&zone.MaxItems,
			&zone.MaxVisitors,
			&zone.UpkeepPeriod,
			&description,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan house zone row: %w", err)
		}

		// Handle nullable description field
		if description != nil {
			zone.Description = *description
		}

		zones = append(zones, zone)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating house zone rows: %w", err)
	}

	return zones, nil
}

// LoadHouseZone retrieves a specific house zone from database
func (dhm *DatabaseHousingManager) LoadHouseZone(ctx context.Context, houseID int32) (*HouseZoneData, error) {
	query := `SELECT id, name, zone_id, cost_coin, cost_status, upkeep_coin, upkeep_status,
			  alignment, guild_level, vault_slots, max_items, max_visitors, upkeep_period, description
			  FROM houses WHERE id = ?`

	var zone HouseZoneData
	var description *string

	err := dhm.db.QueryRowContext(ctx, query, houseID).Scan(
		&zone.ID,
		&zone.Name,
		&zone.ZoneID,
		&zone.CostCoin,
		&zone.CostStatus,
		&zone.UpkeepCoin,
		&zone.UpkeepStatus,
		&zone.Alignment,
		&zone.GuildLevel,
		&zone.VaultSlots,
		&zone.MaxItems,
		&zone.MaxVisitors,
		&zone.UpkeepPeriod,
		&description,
	)
	if err != nil {
		return nil, fmt.Errorf("failed to load house zone %d: %w", houseID, err)
	}

	// Handle nullable description field
	if description != nil {
		zone.Description = *description
	}

	return &zone, nil
}

// SaveHouseZone saves a house zone to database
func (dhm *DatabaseHousingManager) SaveHouseZone(ctx context.Context, zone *HouseZone) error {
	query := `INSERT OR REPLACE INTO houses 
			  (id, name, zone_id, cost_coin, cost_status, upkeep_coin, upkeep_status,
			   alignment, guild_level, vault_slots, max_items, max_visitors, upkeep_period, description)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	_, err := dhm.db.ExecContext(ctx, query,
		zone.ID,
		zone.Name,
		zone.ZoneID,
		zone.CostCoin,
		zone.CostStatus,
		zone.UpkeepCoin,
		zone.UpkeepStatus,
		zone.Alignment,
		zone.GuildLevel,
		zone.VaultSlots,
		zone.MaxItems,
		zone.MaxVisitors,
		zone.UpkeepPeriod,
		zone.Description,
	)
	if err != nil {
		return fmt.Errorf("failed to save house zone %d: %w", zone.ID, err)
	}

	return nil
}

// DeleteHouseZone removes a house zone from database
func (dhm *DatabaseHousingManager) DeleteHouseZone(ctx context.Context, houseID int32) error {
	_, err := dhm.db.ExecContext(ctx, "DELETE FROM houses WHERE id = ?", houseID)
	if err != nil {
		return fmt.Errorf("failed to delete house zone %d: %w", houseID, err)
	}

	return nil
}

// LoadPlayerHouses retrieves all houses owned by a character
func (dhm *DatabaseHousingManager) LoadPlayerHouses(ctx context.Context, characterID int32) ([]PlayerHouseData, error) {
	query := `SELECT unique_id, char_id, house_id, instance_id, upkeep_due, escrow_coins, escrow_status,
			  status, house_name, visit_permission, public_note, private_note, allow_friends, allow_guild,
			  require_approval, show_on_directory, allow_decoration, tax_exempt
			  FROM character_houses WHERE char_id = ? ORDER BY unique_id`

	rows, err := dhm.db.QueryContext(ctx, query, characterID)
	if err != nil {
		return nil, fmt.Errorf("failed to query player houses for character %d: %w", characterID, err)
	}
	defer rows.Close()

	var houses []PlayerHouseData
	for rows.Next() {
		var house PlayerHouseData
		var upkeepDueTimestamp int64
		var houseName, publicNote, privateNote *string

		err := rows.Scan(
			&house.UniqueID,
			&house.CharacterID,
			&house.HouseID,
			&house.InstanceID,
			&upkeepDueTimestamp,
			&house.EscrowCoins,
			&house.EscrowStatus,
			&house.Status,
			&houseName,
			&house.VisitPermission,
			&publicNote,
			&privateNote,
			&house.AllowFriends,
			&house.AllowGuild,
			&house.RequireApproval,
			&house.ShowOnDirectory,
			&house.AllowDecoration,
			&house.TaxExempt,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan player house row: %w", err)
		}

		// Convert timestamp to time
		house.UpkeepDue = time.Unix(upkeepDueTimestamp, 0)

		// Handle nullable fields
		if houseName != nil {
			house.HouseName = *houseName
		}
		if publicNote != nil {
			house.PublicNote = *publicNote
		}
		if privateNote != nil {
			house.PrivateNote = *privateNote
		}

		houses = append(houses, house)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating player house rows: %w", err)
	}

	return houses, nil
}

// LoadPlayerHouse retrieves a specific player house
func (dhm *DatabaseHousingManager) LoadPlayerHouse(ctx context.Context, uniqueID int64) (*PlayerHouseData, error) {
	query := `SELECT unique_id, char_id, house_id, instance_id, upkeep_due, escrow_coins, escrow_status,
			  status, house_name, visit_permission, public_note, private_note, allow_friends, allow_guild,
			  require_approval, show_on_directory, allow_decoration, tax_exempt
			  FROM character_houses WHERE unique_id = ?`

	var house PlayerHouseData
	var upkeepDueTimestamp int64
	var houseName, publicNote, privateNote *string

	err := dhm.db.QueryRowContext(ctx, query, uniqueID).Scan(
		&house.UniqueID,
		&house.CharacterID,
		&house.HouseID,
		&house.InstanceID,
		&upkeepDueTimestamp,
		&house.EscrowCoins,
		&house.EscrowStatus,
		&house.Status,
		&houseName,
		&house.VisitPermission,
		&publicNote,
		&privateNote,
		&house.AllowFriends,
		&house.AllowGuild,
		&house.RequireApproval,
		&house.ShowOnDirectory,
		&house.AllowDecoration,
		&house.TaxExempt,
	)
	if err != nil {
		return nil, fmt.Errorf("failed to load player house %d: %w", uniqueID, err)
	}

	// Convert timestamp to time
	house.UpkeepDue = time.Unix(upkeepDueTimestamp, 0)

	// Handle nullable fields
	if houseName != nil {
		house.HouseName = *houseName
	}
	if publicNote != nil {
		house.PublicNote = *publicNote
	}
	if privateNote != nil {
		house.PrivateNote = *privateNote
	}

	return &house, nil
}

// SavePlayerHouse saves a player house to database
func (dhm *DatabaseHousingManager) SavePlayerHouse(ctx context.Context, house *PlayerHouse) error {
	query := `INSERT OR REPLACE INTO character_houses 
			  (unique_id, char_id, house_id, instance_id, upkeep_due, escrow_coins, escrow_status,
			   status, house_name, visit_permission, public_note, private_note, allow_friends, allow_guild,
			   require_approval, show_on_directory, allow_decoration, tax_exempt)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	upkeepDueTimestamp := house.UpkeepDue.Unix()

	_, err := dhm.db.ExecContext(ctx, query,
		house.UniqueID,
		house.CharacterID,
		house.HouseID,
		house.InstanceID,
		upkeepDueTimestamp,
		house.EscrowCoins,
		house.EscrowStatus,
		house.Status,
		house.Settings.HouseName,
		house.Settings.VisitPermission,
		house.Settings.PublicNote,
		house.Settings.PrivateNote,
		house.Settings.AllowFriends,
		house.Settings.AllowGuild,
		house.Settings.RequireApproval,
		house.Settings.ShowOnDirectory,
		house.Settings.AllowDecoration,
		house.Settings.TaxExempt,
	)
	if err != nil {
		return fmt.Errorf("failed to save player house %d: %w", house.UniqueID, err)
	}

	return nil
}

// DeletePlayerHouse removes a player house from database
func (dhm *DatabaseHousingManager) DeletePlayerHouse(ctx context.Context, uniqueID int64) error {
	// Use a transaction to delete house and all related data
	tx, err := dhm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete related data first
	tables := []string{
		"character_house_deposits",
		"character_house_history",
		"character_house_access",
		"character_house_amenities",
		"character_house_items",
	}

	for _, table := range tables {
		query := fmt.Sprintf("DELETE FROM %s WHERE house_id = ?", table)
		_, err = tx.ExecContext(ctx, query, uniqueID)
		if err != nil {
			return fmt.Errorf("failed to delete from %s: %w", table, err)
		}
	}

	// Delete the house itself
	_, err = tx.ExecContext(ctx, "DELETE FROM character_houses WHERE unique_id = ?", uniqueID)
	if err != nil {
		return fmt.Errorf("failed to delete player house: %w", err)
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// AddPlayerHouse creates a new player house entry
func (dhm *DatabaseHousingManager) AddPlayerHouse(ctx context.Context, houseData PlayerHouseData) (int64, error) {
	query := `INSERT INTO character_houses 
			  (char_id, house_id, instance_id, upkeep_due, escrow_coins, escrow_status,
			   status, house_name, visit_permission, public_note, private_note, allow_friends, allow_guild,
			   require_approval, show_on_directory, allow_decoration, tax_exempt)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	upkeepDueTimestamp := houseData.UpkeepDue.Unix()

	result, err := dhm.db.ExecContext(ctx, query,
		houseData.CharacterID,
		houseData.HouseID,
		houseData.InstanceID,
		upkeepDueTimestamp,
		houseData.EscrowCoins,
		houseData.EscrowStatus,
		houseData.Status,
		houseData.HouseName,
		houseData.VisitPermission,
		houseData.PublicNote,
		houseData.PrivateNote,
		houseData.AllowFriends,
		houseData.AllowGuild,
		houseData.RequireApproval,
		houseData.ShowOnDirectory,
		houseData.AllowDecoration,
		houseData.TaxExempt,
	)
	if err != nil {
		return 0, fmt.Errorf("failed to create player house: %w", err)
	}

	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("failed to get new house ID: %w", err)
	}

	return id, nil
}

// LoadDeposits retrieves deposit history for a house
func (dhm *DatabaseHousingManager) LoadDeposits(ctx context.Context, houseID int64) ([]HouseDepositData, error) {
	query := `SELECT house_id, timestamp, amount, last_amount, status, last_status, name, character_id
			  FROM character_house_deposits WHERE house_id = ? 
			  ORDER BY timestamp DESC LIMIT ?`

	rows, err := dhm.db.QueryContext(ctx, query, houseID, MaxDepositHistory)
	if err != nil {
		return nil, fmt.Errorf("failed to query house deposits for house %d: %w", houseID, err)
	}
	defer rows.Close()

	var deposits []HouseDepositData
	for rows.Next() {
		var deposit HouseDepositData
		var timestampUnix int64

		err := rows.Scan(
			&deposit.HouseID,
			&timestampUnix,
			&deposit.Amount,
			&deposit.LastAmount,
			&deposit.Status,
			&deposit.LastStatus,
			&deposit.Name,
			&deposit.CharacterID,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan deposit row: %w", err)
		}

		deposit.Timestamp = time.Unix(timestampUnix, 0)
		deposits = append(deposits, deposit)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating deposit rows: %w", err)
	}

	return deposits, nil
}

// SaveDeposit saves a deposit record
func (dhm *DatabaseHousingManager) SaveDeposit(ctx context.Context, houseID int64, deposit HouseDeposit) error {
	query := `INSERT INTO character_house_deposits 
			  (house_id, timestamp, amount, last_amount, status, last_status, name, character_id)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`

	timestampUnix := deposit.Timestamp.Unix()

	_, err := dhm.db.ExecContext(ctx, query,
		houseID,
		timestampUnix,
		deposit.Amount,
		deposit.LastAmount,
		deposit.Status,
		deposit.LastStatus,
		deposit.Name,
		deposit.CharacterID,
	)
	if err != nil {
		return fmt.Errorf("failed to save house deposit: %w", err)
	}

	return nil
}

// LoadHistory retrieves transaction history for a house
func (dhm *DatabaseHousingManager) LoadHistory(ctx context.Context, houseID int64) ([]HouseHistoryData, error) {
	query := `SELECT house_id, timestamp, amount, status, reason, name, character_id, pos_flag, type
			  FROM character_house_history WHERE house_id = ? 
			  ORDER BY timestamp DESC LIMIT ?`

	rows, err := dhm.db.QueryContext(ctx, query, houseID, MaxTransactionHistory)
	if err != nil {
		return nil, fmt.Errorf("failed to query house history for house %d: %w", houseID, err)
	}
	defer rows.Close()

	var history []HouseHistoryData
	for rows.Next() {
		var entry HouseHistoryData
		var timestampUnix int64

		err := rows.Scan(
			&entry.HouseID,
			&timestampUnix,
			&entry.Amount,
			&entry.Status,
			&entry.Reason,
			&entry.Name,
			&entry.CharacterID,
			&entry.PosFlag,
			&entry.Type,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan history row: %w", err)
		}

		entry.Timestamp = time.Unix(timestampUnix, 0)
		history = append(history, entry)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating history rows: %w", err)
	}

	return history, nil
}

// AddHistory adds a new history entry
func (dhm *DatabaseHousingManager) AddHistory(ctx context.Context, houseID int64, history HouseHistory) error {
	query := `INSERT INTO character_house_history 
			  (house_id, timestamp, amount, status, reason, name, character_id, pos_flag, type)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`

	timestampUnix := history.Timestamp.Unix()

	_, err := dhm.db.ExecContext(ctx, query,
		houseID,
		timestampUnix,
		history.Amount,
		history.Status,
		history.Reason,
		history.Name,
		history.CharacterID,
		history.PosFlag,
		history.Type,
	)
	if err != nil {
		return fmt.Errorf("failed to add house history: %w", err)
	}

	return nil
}

// LoadHouseAccess retrieves access permissions for a house
func (dhm *DatabaseHousingManager) LoadHouseAccess(ctx context.Context, houseID int64) ([]HouseAccessData, error) {
	query := `SELECT house_id, character_id, player_name, access_level, permissions, granted_by,
			  granted_date, expires_date, notes
			  FROM character_house_access WHERE house_id = ?`

	rows, err := dhm.db.QueryContext(ctx, query, houseID)
	if err != nil {
		return nil, fmt.Errorf("failed to query house access for house %d: %w", houseID, err)
	}
	defer rows.Close()

	var accessList []HouseAccessData
	for rows.Next() {
		var access HouseAccessData
		var grantedDateUnix, expiresDateUnix int64
		var notes *string

		err := rows.Scan(
			&access.HouseID,
			&access.CharacterID,
			&access.PlayerName,
			&access.AccessLevel,
			&access.Permissions,
			&access.GrantedBy,
			&grantedDateUnix,
			&expiresDateUnix,
			&notes,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan access row: %w", err)
		}

		access.GrantedDate = time.Unix(grantedDateUnix, 0)
		access.ExpiresDate = time.Unix(expiresDateUnix, 0)

		if notes != nil {
			access.Notes = *notes
		}

		accessList = append(accessList, access)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating access rows: %w", err)
	}

	return accessList, nil
}

// SaveHouseAccess saves access permissions for a house
func (dhm *DatabaseHousingManager) SaveHouseAccess(ctx context.Context, houseID int64, accessList []HouseAccess) error {
	// Use a transaction for atomic updates
	tx, err := dhm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing access for this house
	_, err = tx.ExecContext(ctx, "DELETE FROM character_house_access WHERE house_id = ?", houseID)
	if err != nil {
		return fmt.Errorf("failed to delete existing house access: %w", err)
	}

	// Insert all access entries
	insertQuery := `INSERT INTO character_house_access 
					(house_id, character_id, player_name, access_level, permissions, granted_by,
					 granted_date, expires_date, notes)
					VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`

	for _, access := range accessList {
		grantedDateUnix := access.GrantedDate.Unix()
		expiresDateUnix := access.ExpiresDate.Unix()

		_, err = tx.ExecContext(ctx, insertQuery,
			houseID,
			access.CharacterID,
			access.PlayerName,
			access.AccessLevel,
			access.Permissions,
			access.GrantedBy,
			grantedDateUnix,
			expiresDateUnix,
			access.Notes,
		)
		if err != nil {
			return fmt.Errorf("failed to insert house access for character %d: %w", access.CharacterID, err)
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// DeleteHouseAccess removes access for a specific character
func (dhm *DatabaseHousingManager) DeleteHouseAccess(ctx context.Context, houseID int64, characterID int32) error {
	_, err := dhm.db.ExecContext(ctx,
		"DELETE FROM character_house_access WHERE house_id = ? AND character_id = ?",
		houseID, characterID)
	if err != nil {
		return fmt.Errorf("failed to delete house access: %w", err)
	}

	return nil
}

// Additional database methods continued in next part due to length...

// LoadHouseAmenities retrieves amenities for a house
func (dhm *DatabaseHousingManager) LoadHouseAmenities(ctx context.Context, houseID int64) ([]HouseAmenityData, error) {
	query := `SELECT house_id, id, type, name, cost, status_cost, purchase_date, x, y, z, heading, is_active
			  FROM character_house_amenities WHERE house_id = ?`

	rows, err := dhm.db.QueryContext(ctx, query, houseID)
	if err != nil {
		return nil, fmt.Errorf("failed to query house amenities for house %d: %w", houseID, err)
	}
	defer rows.Close()

	var amenities []HouseAmenityData
	for rows.Next() {
		var amenity HouseAmenityData
		var purchaseDateUnix int64

		err := rows.Scan(
			&amenity.HouseID,
			&amenity.ID,
			&amenity.Type,
			&amenity.Name,
			&amenity.Cost,
			&amenity.StatusCost,
			&purchaseDateUnix,
			&amenity.X,
			&amenity.Y,
			&amenity.Z,
			&amenity.Heading,
			&amenity.IsActive,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan amenity row: %w", err)
		}

		amenity.PurchaseDate = time.Unix(purchaseDateUnix, 0)
		amenities = append(amenities, amenity)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating amenity rows: %w", err)
	}

	return amenities, nil
}

// SaveHouseAmenity saves a house amenity
func (dhm *DatabaseHousingManager) SaveHouseAmenity(ctx context.Context, houseID int64, amenity HouseAmenity) error {
	query := `INSERT OR REPLACE INTO character_house_amenities 
			  (house_id, id, type, name, cost, status_cost, purchase_date, x, y, z, heading, is_active)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	purchaseDateUnix := amenity.PurchaseDate.Unix()

	_, err := dhm.db.ExecContext(ctx, query,
		houseID,
		amenity.ID,
		amenity.Type,
		amenity.Name,
		amenity.Cost,
		amenity.StatusCost,
		purchaseDateUnix,
		amenity.X,
		amenity.Y,
		amenity.Z,
		amenity.Heading,
		amenity.IsActive,
	)
	if err != nil {
		return fmt.Errorf("failed to save house amenity: %w", err)
	}

	return nil
}

// DeleteHouseAmenity removes a house amenity
func (dhm *DatabaseHousingManager) DeleteHouseAmenity(ctx context.Context, houseID int64, amenityID int32) error {
	_, err := dhm.db.ExecContext(ctx,
		"DELETE FROM character_house_amenities WHERE house_id = ? AND id = ?",
		houseID, amenityID)
	if err != nil {
		return fmt.Errorf("failed to delete house amenity: %w", err)
	}

	return nil
}

// LoadHouseItems retrieves items placed in a house
func (dhm *DatabaseHousingManager) LoadHouseItems(ctx context.Context, houseID int64) ([]HouseItemData, error) {
	query := `SELECT house_id, id, item_id, character_id, x, y, z, heading, pitch_x, pitch_y,
			  roll_x, roll_y, placed_date, quantity, condition, house
			  FROM character_house_items WHERE house_id = ?`

	rows, err := dhm.db.QueryContext(ctx, query, houseID)
	if err != nil {
		return nil, fmt.Errorf("failed to query house items for house %d: %w", houseID, err)
	}
	defer rows.Close()

	var items []HouseItemData
	for rows.Next() {
		var item HouseItemData
		var placedDateUnix int64

		err := rows.Scan(
			&item.HouseID,
			&item.ID,
			&item.ItemID,
			&item.CharacterID,
			&item.X,
			&item.Y,
			&item.Z,
			&item.Heading,
			&item.PitchX,
			&item.PitchY,
			&item.RollX,
			&item.RollY,
			&placedDateUnix,
			&item.Quantity,
			&item.Condition,
			&item.House,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan item row: %w", err)
		}

		item.PlacedDate = time.Unix(placedDateUnix, 0)
		items = append(items, item)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating item rows: %w", err)
	}

	return items, nil
}

// SaveHouseItem saves a house item
func (dhm *DatabaseHousingManager) SaveHouseItem(ctx context.Context, houseID int64, item HouseItem) error {
	query := `INSERT OR REPLACE INTO character_house_items 
			  (house_id, id, item_id, character_id, x, y, z, heading, pitch_x, pitch_y,
			   roll_x, roll_y, placed_date, quantity, condition, house)
			  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	placedDateUnix := item.PlacedDate.Unix()

	_, err := dhm.db.ExecContext(ctx, query,
		houseID,
		item.ID,
		item.ItemID,
		item.CharacterID,
		item.X,
		item.Y,
		item.Z,
		item.Heading,
		item.PitchX,
		item.PitchY,
		item.RollX,
		item.RollY,
		placedDateUnix,
		item.Quantity,
		item.Condition,
		item.House,
	)
	if err != nil {
		return fmt.Errorf("failed to save house item: %w", err)
	}

	return nil
}

// DeleteHouseItem removes a house item
func (dhm *DatabaseHousingManager) DeleteHouseItem(ctx context.Context, houseID int64, itemID int64) error {
	_, err := dhm.db.ExecContext(ctx,
		"DELETE FROM character_house_items WHERE house_id = ? AND id = ?",
		houseID, itemID)
	if err != nil {
		return fmt.Errorf("failed to delete house item: %w", err)
	}

	return nil
}

// Utility operations

// GetNextHouseID returns the next available house unique ID
func (dhm *DatabaseHousingManager) GetNextHouseID(ctx context.Context) (int64, error) {
	query := "SELECT COALESCE(MAX(unique_id), 0) + 1 FROM character_houses"

	var nextID int64
	err := dhm.db.QueryRowContext(ctx, query).Scan(&nextID)
	if err != nil {
		return 0, fmt.Errorf("failed to get next house ID: %w", err)
	}

	return nextID, nil
}

// GetHouseByInstance finds a house by instance ID
func (dhm *DatabaseHousingManager) GetHouseByInstance(ctx context.Context, instanceID int32) (*PlayerHouseData, error) {
	query := `SELECT unique_id, char_id, house_id, instance_id, upkeep_due, escrow_coins, escrow_status,
			  status, house_name, visit_permission, public_note, private_note, allow_friends, allow_guild,
			  require_approval, show_on_directory, allow_decoration, tax_exempt
			  FROM character_houses WHERE instance_id = ?`

	var house PlayerHouseData
	var upkeepDueTimestamp int64
	var houseName, publicNote, privateNote *string

	err := dhm.db.QueryRowContext(ctx, query, instanceID).Scan(
		&house.UniqueID,
		&house.CharacterID,
		&house.HouseID,
		&house.InstanceID,
		&upkeepDueTimestamp,
		&house.EscrowCoins,
		&house.EscrowStatus,
		&house.Status,
		&houseName,
		&house.VisitPermission,
		&publicNote,
		&privateNote,
		&house.AllowFriends,
		&house.AllowGuild,
		&house.RequireApproval,
		&house.ShowOnDirectory,
		&house.AllowDecoration,
		&house.TaxExempt,
	)
	if err != nil {
		return nil, fmt.Errorf("failed to load house by instance %d: %w", instanceID, err)
	}

	// Convert timestamp and handle nullable fields
	house.UpkeepDue = time.Unix(upkeepDueTimestamp, 0)

	if houseName != nil {
		house.HouseName = *houseName
	}
	if publicNote != nil {
		house.PublicNote = *publicNote
	}
	if privateNote != nil {
		house.PrivateNote = *privateNote
	}

	return &house, nil
}

// UpdateHouseUpkeepDue updates the upkeep due date for a house
func (dhm *DatabaseHousingManager) UpdateHouseUpkeepDue(ctx context.Context, houseID int64, upkeepDue time.Time) error {
	query := "UPDATE character_houses SET upkeep_due = ? WHERE unique_id = ?"
	upkeepDueTimestamp := upkeepDue.Unix()

	_, err := dhm.db.ExecContext(ctx, query, upkeepDueTimestamp, houseID)
	if err != nil {
		return fmt.Errorf("failed to update house upkeep due: %w", err)
	}

	return nil
}

// UpdateHouseEscrow updates the escrow balances for a house
func (dhm *DatabaseHousingManager) UpdateHouseEscrow(ctx context.Context, houseID int64, coins, status int64) error {
	query := "UPDATE character_houses SET escrow_coins = ?, escrow_status = ? WHERE unique_id = ?"

	_, err := dhm.db.ExecContext(ctx, query, coins, status, houseID)
	if err != nil {
		return fmt.Errorf("failed to update house escrow: %w", err)
	}

	return nil
}

// GetHousesForUpkeep returns houses that need upkeep processing
func (dhm *DatabaseHousingManager) GetHousesForUpkeep(ctx context.Context, cutoffTime time.Time) ([]PlayerHouseData, error) {
	query := `SELECT unique_id, char_id, house_id, instance_id, upkeep_due, escrow_coins, escrow_status,
			  status, house_name, visit_permission, public_note, private_note, allow_friends, allow_guild,
			  require_approval, show_on_directory, allow_decoration, tax_exempt
			  FROM character_houses WHERE upkeep_due <= ? AND status = ?`

	cutoffTimestamp := cutoffTime.Unix()

	rows, err := dhm.db.QueryContext(ctx, query, cutoffTimestamp, HouseStatusActive)
	if err != nil {
		return nil, fmt.Errorf("failed to query houses for upkeep: %w", err)
	}
	defer rows.Close()

	var houses []PlayerHouseData
	for rows.Next() {
		var house PlayerHouseData
		var upkeepDueTimestamp int64
		var houseName, publicNote, privateNote *string

		err := rows.Scan(
			&house.UniqueID,
			&house.CharacterID,
			&house.HouseID,
			&house.InstanceID,
			&upkeepDueTimestamp,
			&house.EscrowCoins,
			&house.EscrowStatus,
			&house.Status,
			&houseName,
			&house.VisitPermission,
			&publicNote,
			&privateNote,
			&house.AllowFriends,
			&house.AllowGuild,
			&house.RequireApproval,
			&house.ShowOnDirectory,
			&house.AllowDecoration,
			&house.TaxExempt,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan upkeep house row: %w", err)
		}

		house.UpkeepDue = time.Unix(upkeepDueTimestamp, 0)

		if houseName != nil {
			house.HouseName = *houseName
		}
		if publicNote != nil {
			house.PublicNote = *publicNote
		}
		if privateNote != nil {
			house.PrivateNote = *privateNote
		}

		houses = append(houses, house)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating upkeep house rows: %w", err)
	}

	return houses, nil
}

// GetHouseStatistics returns housing system statistics
func (dhm *DatabaseHousingManager) GetHouseStatistics(ctx context.Context) (*HousingStatistics, error) {
	stats := &HousingStatistics{
		HousesByType:      make(map[int32]int64),
		HousesByAlignment: make(map[int8]int64),
		RevenueByType:     make(map[int]int64),
		TopDepositors:     make([]PlayerDeposits, 0),
	}

	// Get basic counts
	queries := map[string]*int64{
		"SELECT COUNT(*) FROM character_houses":                           &stats.TotalHouses,
		"SELECT COUNT(*) FROM character_houses WHERE status = 0":          &stats.ActiveHouses,
		"SELECT COUNT(*) FROM character_houses WHERE status = 2":          &stats.ForelosedHouses,
		"SELECT COUNT(*) FROM character_house_deposits":                   &stats.TotalDeposits,
		"SELECT COUNT(*) FROM character_house_history WHERE pos_flag = 0": &stats.TotalWithdrawals,
	}

	for query, target := range queries {
		err := dhm.db.QueryRowContext(ctx, query).Scan(target)
		if err != nil {
			return nil, fmt.Errorf("failed to get statistics: %w", err)
		}
	}

	return stats, nil
}

// EnsureHousingTables creates the housing tables if they don't exist
func (dhm *DatabaseHousingManager) EnsureHousingTables(ctx context.Context) error {
	queries := []string{
		`CREATE TABLE IF NOT EXISTS houses (
			id INTEGER PRIMARY KEY,
			name TEXT NOT NULL,
			zone_id INTEGER NOT NULL,
			cost_coin INTEGER NOT NULL DEFAULT 0,
			cost_status INTEGER NOT NULL DEFAULT 0,
			upkeep_coin INTEGER NOT NULL DEFAULT 0,
			upkeep_status INTEGER NOT NULL DEFAULT 0,
			alignment INTEGER NOT NULL DEFAULT 0,
			guild_level INTEGER NOT NULL DEFAULT 0,
			vault_slots INTEGER NOT NULL DEFAULT 4,
			max_items INTEGER NOT NULL DEFAULT 100,
			max_visitors INTEGER NOT NULL DEFAULT 50,
			upkeep_period INTEGER NOT NULL DEFAULT 604800,
			description TEXT DEFAULT '',
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
		)`,
		`CREATE TABLE IF NOT EXISTS character_houses (
			unique_id INTEGER PRIMARY KEY AUTOINCREMENT,
			char_id INTEGER NOT NULL,
			house_id INTEGER NOT NULL,
			instance_id INTEGER NOT NULL,
			upkeep_due INTEGER NOT NULL,
			escrow_coins INTEGER NOT NULL DEFAULT 0,
			escrow_status INTEGER NOT NULL DEFAULT 0,
			status INTEGER NOT NULL DEFAULT 0,
			house_name TEXT DEFAULT '',
			visit_permission INTEGER NOT NULL DEFAULT 0,
			public_note TEXT DEFAULT '',
			private_note TEXT DEFAULT '',
			allow_friends INTEGER NOT NULL DEFAULT 1,
			allow_guild INTEGER NOT NULL DEFAULT 0,
			require_approval INTEGER NOT NULL DEFAULT 0,
			show_on_directory INTEGER NOT NULL DEFAULT 1,
			allow_decoration INTEGER NOT NULL DEFAULT 0,
			tax_exempt INTEGER NOT NULL DEFAULT 0,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			FOREIGN KEY (house_id) REFERENCES houses(id)
		)`,
		`CREATE TABLE IF NOT EXISTS character_house_deposits (
			house_id INTEGER NOT NULL,
			timestamp INTEGER NOT NULL,
			amount INTEGER NOT NULL,
			last_amount INTEGER NOT NULL,
			status INTEGER NOT NULL,
			last_status INTEGER NOT NULL,
			name TEXT NOT NULL,
			character_id INTEGER NOT NULL,
			FOREIGN KEY (house_id) REFERENCES character_houses(unique_id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS character_house_history (
			house_id INTEGER NOT NULL,
			timestamp INTEGER NOT NULL,
			amount INTEGER NOT NULL,
			status INTEGER NOT NULL,
			reason TEXT NOT NULL,
			name TEXT NOT NULL,
			character_id INTEGER NOT NULL,
			pos_flag INTEGER NOT NULL,
			type INTEGER NOT NULL,
			FOREIGN KEY (house_id) REFERENCES character_houses(unique_id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS character_house_access (
			house_id INTEGER NOT NULL,
			character_id INTEGER NOT NULL,
			player_name TEXT NOT NULL,
			access_level INTEGER NOT NULL,
			permissions INTEGER NOT NULL,
			granted_by INTEGER NOT NULL,
			granted_date INTEGER NOT NULL,
			expires_date INTEGER NOT NULL,
			notes TEXT DEFAULT '',
			PRIMARY KEY (house_id, character_id),
			FOREIGN KEY (house_id) REFERENCES character_houses(unique_id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS character_house_amenities (
			house_id INTEGER NOT NULL,
			id INTEGER NOT NULL,
			type INTEGER NOT NULL,
			name TEXT NOT NULL,
			cost INTEGER NOT NULL,
			status_cost INTEGER NOT NULL,
			purchase_date INTEGER NOT NULL,
			x REAL NOT NULL,
			y REAL NOT NULL,
			z REAL NOT NULL,
			heading REAL NOT NULL,
			is_active INTEGER NOT NULL DEFAULT 1,
			PRIMARY KEY (house_id, id),
			FOREIGN KEY (house_id) REFERENCES character_houses(unique_id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS character_house_items (
			house_id INTEGER NOT NULL,
			id INTEGER NOT NULL,
			item_id INTEGER NOT NULL,
			character_id INTEGER NOT NULL,
			x REAL NOT NULL,
			y REAL NOT NULL,
			z REAL NOT NULL,
			heading REAL NOT NULL,
			pitch_x REAL NOT NULL DEFAULT 0,
			pitch_y REAL NOT NULL DEFAULT 0,
			roll_x REAL NOT NULL DEFAULT 0,
			roll_y REAL NOT NULL DEFAULT 0,
			placed_date INTEGER NOT NULL,
			quantity INTEGER NOT NULL,
			condition INTEGER NOT NULL,
			house TEXT NOT NULL,
			PRIMARY KEY (house_id, id),
			FOREIGN KEY (house_id) REFERENCES character_houses(unique_id) ON DELETE CASCADE
		)`,
	}

	for i, query := range queries {
		_, err := dhm.db.ExecContext(ctx, query)
		if err != nil {
			return fmt.Errorf("failed to create housing table %d: %w", i+1, err)
		}
	}

	// Create indexes for better performance
	indexes := []string{
		`CREATE INDEX IF NOT EXISTS idx_character_houses_char_id ON character_houses(char_id)`,
		`CREATE INDEX IF NOT EXISTS idx_character_houses_instance_id ON character_houses(instance_id)`,
		`CREATE INDEX IF NOT EXISTS idx_character_houses_upkeep_due ON character_houses(upkeep_due)`,
		`CREATE INDEX IF NOT EXISTS idx_character_houses_status ON character_houses(status)`,
		`CREATE INDEX IF NOT EXISTS idx_house_deposits_house_id ON character_house_deposits(house_id)`,
		`CREATE INDEX IF NOT EXISTS idx_house_deposits_timestamp ON character_house_deposits(timestamp)`,
		`CREATE INDEX IF NOT EXISTS idx_house_history_house_id ON character_house_history(house_id)`,
		`CREATE INDEX IF NOT EXISTS idx_house_history_timestamp ON character_house_history(timestamp)`,
		`CREATE INDEX IF NOT EXISTS idx_house_access_character_id ON character_house_access(character_id)`,
		`CREATE INDEX IF NOT EXISTS idx_house_items_item_id ON character_house_items(item_id)`,
		`CREATE INDEX IF NOT EXISTS idx_houses_zone_id ON houses(zone_id)`,
		`CREATE INDEX IF NOT EXISTS idx_houses_alignment ON houses(alignment)`,
	}

	for i, query := range indexes {
		_, err := dhm.db.ExecContext(ctx, query)
		if err != nil {
			return fmt.Errorf("failed to create housing index %d: %w", i+1, err)
		}
	}

	return nil
}
