/**
 * rBnb Automerge document schemas.
 *
 * Community hospitality — trust-based space sharing and couch surfing.
 * Granularity: one Automerge document per space (listings + stays + endorsements).
 * DocId format: {space}:bnb:listings
 */

import type { DocSchema } from '../../shared/local-first/document';

// ── Economy model ──

export type EconomyModel = 'gift' | 'suggested' | 'fixed' | 'sliding_scale' | 'exchange';

// ── Listing types ──

export type ListingType =
	| 'couch'
	| 'room'
	| 'apartment'
	| 'cabin'
	| 'tent_site'
	| 'land'
	| 'studio'
	| 'loft'
	| 'house'
	| 'other';

// ── Stay request status ──

export type StayStatus =
	| 'pending'
	| 'accepted'
	| 'declined'
	| 'cancelled'
	| 'completed'
	| 'endorsed';

// ── Endorsement visibility ──

export type EndorsementVisibility = 'public' | 'private' | 'community';

// ── Core types ──

export interface AvailabilityWindow {
	id: string;
	listingId: string;
	startDate: number;        // epoch ms (start of day)
	endDate: number;          // epoch ms (end of day)
	status: 'available' | 'blocked' | 'tentative';
	notes: string | null;
	createdAt: number;
}

export interface Listing {
	id: string;
	hostDid: string;          // DID of the host
	hostName: string;
	title: string;
	description: string;
	type: ListingType;
	economy: EconomyModel;

	// Pricing (relevant for non-gift economies)
	suggestedAmount: number | null;    // suggested/fixed price per night
	currency: string | null;           // e.g. 'USD', 'EUR', or null for gift
	slidingMin: number | null;         // sliding scale minimum
	slidingMax: number | null;         // sliding scale maximum
	exchangeDescription: string | null; // what the host wants in exchange

	// Location
	locationName: string;
	locationLat: number | null;
	locationLng: number | null;
	locationGranularity: string | null;  // 'city', 'neighborhood', 'address'

	// Capacity & details
	guestCapacity: number;
	bedroomCount: number | null;
	bedCount: number | null;
	bathroomCount: number | null;
	amenities: string[];         // e.g. ['wifi', 'kitchen', 'laundry', 'parking']
	houseRules: string[];        // e.g. ['no_smoking', 'quiet_hours', 'shoes_off']
	photos: string[];            // asset IDs or URLs
	coverPhoto: string | null;

	// Trust & auto-accept
	trustThreshold: number | null;   // 0-100, rNetwork trust score for auto-accept
	instantAccept: boolean;          // if true + trust met → auto-accept requests

	// Metadata
	isActive: boolean;
	createdAt: number;
	updatedAt: number;
}

export interface StayMessage {
	id: string;
	senderDid: string;
	senderName: string;
	body: string;
	sentAt: number;
}

export interface StayRequest {
	id: string;
	listingId: string;
	guestDid: string;
	guestName: string;
	hostDid: string;

	// Dates
	checkIn: number;          // epoch ms
	checkOut: number;         // epoch ms
	guestCount: number;

	// Status flow: pending → accepted/declined → completed → endorsed
	status: StayStatus;

	// Messages embedded in the CRDT (conversation lives in the request)
	messages: StayMessage[];

	// Contribution (for non-gift economies)
	offeredAmount: number | null;
	offeredCurrency: string | null;
	offeredExchange: string | null;

	// Timestamps
	requestedAt: number;
	respondedAt: number | null;
	completedAt: number | null;
	cancelledAt: number | null;
}

export interface Endorsement {
	id: string;
	stayId: string;
	listingId: string;

	// Who wrote it and about whom
	authorDid: string;
	authorName: string;
	subjectDid: string;       // the person being endorsed (host or guest)
	subjectName: string;
	direction: 'guest_to_host' | 'host_to_guest';

	// Content
	body: string;
	rating: number | null;    // 1-5, optional (endorsements > ratings)
	tags: string[];           // e.g. ['welcoming', 'clean', 'great_conversation']
	visibility: EndorsementVisibility;

	// Trust integration — feeds into rNetwork trust graph
	trustWeight: number;      // 0-1, how much this endorsement affects trust score

	createdAt: number;
}

export interface SpaceConfig {
	defaultEconomy: EconomyModel;
	defaultTrustThreshold: number;    // 0-100
	amenityCatalog: string[];         // available amenities for this community
	houseRuleCatalog: string[];       // available house rules
	endorsementTagCatalog: string[];  // available endorsement tags
	requireEndorsement: boolean;      // whether both parties must endorse after stay
	maxStayDays: number;              // maximum stay length in days
}

// ── Top-level document ──

export interface BnbDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	config: SpaceConfig;
	listings: Record<string, Listing>;
	availability: Record<string, AvailabilityWindow>;
	stays: Record<string, StayRequest>;
	endorsements: Record<string, Endorsement>;
}

// ── Schema registration ──

export const DEFAULT_AMENITIES = [
	'wifi', 'kitchen', 'laundry', 'parking', 'garden', 'workspace',
	'heating', 'air_conditioning', 'hot_water', 'towels', 'linens',
	'pets_welcome', 'wheelchair_accessible', 'bike_storage',
];

export const DEFAULT_HOUSE_RULES = [
	'no_smoking', 'quiet_hours', 'shoes_off', 'no_parties',
	'clean_up_after', 'no_pets', 'check_in_by_10pm',
];

export const DEFAULT_ENDORSEMENT_TAGS = [
	'welcoming', 'clean', 'great_conversation', 'respectful',
	'generous', 'good_communication', 'safe_space', 'cozy',
	'well_located', 'quiet', 'fun', 'helpful',
];

const DEFAULT_CONFIG: SpaceConfig = {
	defaultEconomy: 'gift',
	defaultTrustThreshold: 30,
	amenityCatalog: DEFAULT_AMENITIES,
	houseRuleCatalog: DEFAULT_HOUSE_RULES,
	endorsementTagCatalog: DEFAULT_ENDORSEMENT_TAGS,
	requireEndorsement: false,
	maxStayDays: 30,
};

export const bnbSchema: DocSchema<BnbDoc> = {
	module: 'bnb',
	collection: 'listings',
	version: 1,
	init: (): BnbDoc => ({
		meta: {
			module: 'bnb',
			collection: 'listings',
			version: 1,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		config: { ...DEFAULT_CONFIG },
		listings: {},
		availability: {},
		stays: {},
		endorsements: {},
	}),
};

// ── Helpers ──

export function bnbDocId(space: string) {
	return `${space}:bnb:listings` as const;
}

/** Economy model display labels */
export const ECONOMY_LABELS: Record<EconomyModel, string> = {
	gift: 'Gift Economy',
	suggested: 'Suggested Contribution',
	fixed: 'Fixed Price',
	sliding_scale: 'Sliding Scale',
	exchange: 'Skill/Service Exchange',
};

/** Listing type display labels */
export const LISTING_TYPE_LABELS: Record<ListingType, string> = {
	couch: 'Couch',
	room: 'Private Room',
	apartment: 'Apartment',
	cabin: 'Cabin',
	tent_site: 'Tent Site',
	land: 'Land',
	studio: 'Studio',
	loft: 'Loft',
	house: 'House',
	other: 'Other',
};

/** Listing type icons */
export const LISTING_TYPE_ICONS: Record<ListingType, string> = {
	couch: '\u{1F6CB}',      // couch
	room: '\u{1F6CF}',       // bed
	apartment: '\u{1F3E2}',  // building
	cabin: '\u{1F3E1}',      // house
	tent_site: '\u{26FA}',   // tent
	land: '\u{1F333}',       // tree
	studio: '\u{1F3A8}',     // palette
	loft: '\u{1F3D7}',       // building construction
	house: '\u{1F3E0}',      // house
	other: '\u{1F3E8}',      // hotel
};
