/**
 * rExchange Schemas — P2P on/off-ramp exchange intents, trades, and reputation.
 *
 * DocId formats:
 *   {space}:rexchange:intents    → ExchangeIntentsDoc (active buy/sell intents)
 *   {space}:rexchange:trades     → ExchangeTradesDoc (active & historical trades)
 *   {space}:rexchange:reputation → ExchangeReputationDoc (per-member trading reputation)
 */

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

// ── Enums / Literals ──

export type ExchangeSide = 'buy' | 'sell';
export type TokenId = 'cusdc' | 'myco' | 'fusdc';
export type FiatCurrency = 'EUR' | 'USD' | 'GBP' | 'BRL' | 'MXN' | 'INR' | 'NGN' | 'ARS';
export type RateType = 'fixed' | 'market_plus_bps';
export type IntentStatus = 'active' | 'matched' | 'completed' | 'cancelled' | 'expired';

export type TradeStatus =
	| 'proposed'
	| 'accepted'
	| 'escrow_locked'
	| 'fiat_sent'
	| 'fiat_confirmed'
	| 'completed'
	| 'disputed'
	| 'resolved'
	| 'cancelled'
	| 'timed_out';

// ── Exchange Intent ──

export interface ExchangeIntent {
	id: string;
	creatorDid: string;
	creatorName: string;
	side: ExchangeSide;
	tokenId: TokenId;
	fiatCurrency: FiatCurrency;
	tokenAmountMin: number;      // base units (6 decimals)
	tokenAmountMax: number;
	rateType: RateType;
	rateFixed?: number;          // fiat per token (e.g. 0.98 EUR/cUSDC)
	rateMarketBps?: number;      // basis points spread over market rate
	paymentMethods: string[];    // "SEPA", "Revolut", "PIX", "M-Pesa", "Cash", etc.
	isStandingOrder: boolean;    // LP flag — re-activates after fill
	autoAccept: boolean;         // skip manual match acceptance
	allowInstitutionalFallback: boolean; // escalate to HyperSwitch if unmatched
	minCounterpartyReputation?: number;  // 0-100
	preferredCounterparties?: string[];  // DID list
	status: IntentStatus;
	createdAt: number;
	expiresAt?: number;
}

// ── Trade Chat Message ──

export interface TradeChatMessage {
	id: string;
	senderDid: string;
	senderName: string;
	text: string;
	timestamp: number;
}

// ── Exchange Trade ──

export interface ExchangeTrade {
	id: string;
	buyIntentId: string;
	sellIntentId: string;
	buyerDid: string;
	buyerName: string;
	sellerDid: string;
	sellerName: string;
	tokenId: TokenId;
	tokenAmount: number;         // agreed amount in base units
	fiatCurrency: FiatCurrency;
	fiatAmount: number;          // agreed fiat amount
	agreedRate: number;          // fiat per token
	paymentMethod: string;
	escrowTxId?: string;
	status: TradeStatus;
	acceptances: Record<string, boolean>;  // did → accepted?
	chatMessages: TradeChatMessage[];
	fiatConfirmDeadline?: number; // timestamp — 24h default
	disputeReason?: string;
	resolution?: 'released_to_buyer' | 'returned_to_seller';
	createdAt: number;
	completedAt?: number;
}

// ── Liquidity Pools ──

export type PoolStatus = 'active' | 'paused' | 'withdrawn';

export interface LiquidityPosition {
	id: string;
	creatorDid: string;
	creatorName: string;
	tokenId: TokenId;
	fiatCurrency: FiatCurrency;
	// Token side (sellable)
	tokenCommitted: number;       // base units locked for selling
	tokenRemaining: number;       // decrements as sells fill
	// Fiat side (buyable)
	fiatCommitted: number;        // fiat amount committed for buying tokens
	fiatRemaining: number;        // decrements as buys fill
	// Spread = the LP's fee (applied as market_plus_bps on both sides)
	spreadBps: number;            // e.g., 50 = 0.5% each side, 1% round-trip
	// Payment
	paymentMethods: string[];
	// Linked standing order IDs (created automatically)
	buyIntentId: string;
	sellIntentId: string;
	// Earnings tracking
	feesEarnedToken: number;      // token base units earned from spread
	feesEarnedFiat: number;       // fiat earned from spread
	tradesMatched: number;
	// State
	status: PoolStatus;
	createdAt: number;
	updatedAt: number;
}

export interface ExchangePoolsDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	positions: Record<string, LiquidityPosition>;
}

// ── Reputation ──

export interface ExchangeReputationRecord {
	did: string;
	tradesCompleted: number;
	tradesCancelled: number;
	disputesRaised: number;
	disputesLost: number;
	totalVolumeBase: number;    // total token volume in base units
	avgConfirmTimeMs: number;
	score: number;              // 0-100
	badges: string[];           // 'verified_seller', 'liquidity_provider', 'top_trader'
}

// ── Documents ──

export interface ExchangeIntentsDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	intents: Record<string, ExchangeIntent>;
}

export interface ExchangeTradesDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	trades: Record<string, ExchangeTrade>;
}

export interface ExchangeReputationDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	records: Record<string, ExchangeReputationRecord>;
}

// ── DocId helpers ──

export function exchangeIntentsDocId(space: string) {
	return `${space}:rexchange:intents` as const;
}

export function exchangeTradesDocId(space: string) {
	return `${space}:rexchange:trades` as const;
}

export function exchangeReputationDocId(space: string) {
	return `${space}:rexchange:reputation` as const;
}

export function exchangePoolsDocId(space: string) {
	return `${space}:rexchange:pools` as const;
}

// ── Schema registrations ──

export const exchangeIntentsSchema: DocSchema<ExchangeIntentsDoc> = {
	module: 'rexchange',
	collection: 'intents',
	version: 1,
	init: (): ExchangeIntentsDoc => ({
		meta: {
			module: 'rexchange',
			collection: 'intents',
			version: 1,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		intents: {},
	}),
};

export const exchangeTradesSchema: DocSchema<ExchangeTradesDoc> = {
	module: 'rexchange',
	collection: 'trades',
	version: 1,
	init: (): ExchangeTradesDoc => ({
		meta: {
			module: 'rexchange',
			collection: 'trades',
			version: 1,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		trades: {},
	}),
};

export const exchangeReputationSchema: DocSchema<ExchangeReputationDoc> = {
	module: 'rexchange',
	collection: 'reputation',
	version: 1,
	init: (): ExchangeReputationDoc => ({
		meta: {
			module: 'rexchange',
			collection: 'reputation',
			version: 1,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		records: {},
	}),
};

export const exchangePoolsSchema: DocSchema<ExchangePoolsDoc> = {
	module: 'rexchange',
	collection: 'pools',
	version: 1,
	init: (): ExchangePoolsDoc => ({
		meta: {
			module: 'rexchange',
			collection: 'pools',
			version: 1,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		positions: {},
	}),
};
