/**
 * rSocials Automerge document schemas.
 *
 * Granularity: one Automerge document per space.
 * DocId format: {space}:socials:data
 *
 * Images stay on filesystem, referenced by URL strings in the doc.
 */

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

// ── Thread types ──

export interface ThreadData {
	id: string;
	name: string;
	handle: string;
	title: string;
	tweets: string[];
	imageUrl?: string | null;
	tweetImages?: Record<string, string> | null;
	createdAt: number;
	updatedAt: number;
}

// ── Campaign types ──

export interface CampaignPost {
	id: string;
	platform: string;
	postType: string;
	stepNumber: number;
	content: string;
	scheduledAt: string;
	status: string;
	hashtags: string[];
	phase: number;
	phaseLabel: string;
	threadPosts?: string[];
	threadId?: string;
	emailSubject?: string;
	emailHtml?: string;
}

export interface Campaign {
	id: string;
	title: string;
	description: string;
	duration: string;
	platforms: string[];
	phases: { name: string; label: string; days: string }[];
	posts: CampaignPost[];
	createdAt: number;
	updatedAt: number;
}

// ── Campaign planner (flow canvas) types ──

export type CampaignNodeType = 'post' | 'thread' | 'platform' | 'audience' | 'phase' | 'goal' | 'message' | 'tone' | 'brief';

export interface PostNodeData {
	label: string;
	platform: string;
	postType: string;
	content: string;
	scheduledAt: string;
	status: 'draft' | 'scheduled' | 'published';
	hashtags: string[];
}

export interface ThreadNodeData {
	label: string;
	threadId: string;
	tweetCount: number;
	status: 'draft' | 'ready' | 'published';
	preview: string;
}

export interface PlatformNodeData {
	label: string;
	platform: string;
	handle: string;
}

export interface AudienceNodeData {
	label: string;
	description: string;
	sizeEstimate: string;
}

export interface PhaseNodeData {
	label: string;
	dateRange: string;
	color: string;
	progress?: number;
	childNodeIds: string[];
	size: { w: number; h: number };
}

export interface GoalNodeData {
	label: string;
	objective: string;
	startDate: string;
	endDate: string;
}

export interface MessageNodeData {
	label: string;
	text: string;
	priority: 'high' | 'medium' | 'low';
}

export interface ToneNodeData {
	label: string;
	tone: string;
	style: string;
	audience: string;
	sizeEstimate: string;
}

export interface BriefNodeData {
	label: string;
	text: string;
	platforms: string[];
	generating?: boolean;
	lastGeneratedAt?: number;
}

export interface CampaignPlannerNode {
	id: string;
	type: CampaignNodeType;
	position: { x: number; y: number };
	data: PostNodeData | ThreadNodeData | PlatformNodeData | AudienceNodeData | PhaseNodeData | GoalNodeData | MessageNodeData | ToneNodeData | BriefNodeData;
	stale?: boolean;
	staleReason?: string;
}

export type CampaignEdgeType = 'publish' | 'sequence' | 'target' | 'feeds';

export interface CampaignEdge {
	id: string;
	from: string;
	to: string;
	type: CampaignEdgeType;
	waypoint?: { x: number; y: number };
}

export interface CampaignFlow {
	id: string;
	name: string;
	nodes: CampaignPlannerNode[];
	edges: CampaignEdge[];
	createdAt: number;
	updatedAt: number;
	createdBy: string | null;
}

// ── Campaign workflow (n8n-style) types ──

export type CampaignWorkflowNodeType =
	// Triggers
	| 'campaign-start'
	| 'schedule-trigger'
	| 'webhook-trigger'
	// Delays
	| 'wait-duration'
	| 'wait-approval'
	// Conditions
	| 'engagement-check'
	| 'time-window'
	// Actions
	| 'post-to-platform'
	| 'cross-post'
	| 'publish-thread'
	| 'send-newsletter'
	| 'post-webhook';

export type CampaignWorkflowNodeCategory = 'trigger' | 'delay' | 'condition' | 'action';

export interface CampaignWorkflowNodePort {
	name: string;
	type: 'trigger' | 'data' | 'boolean';
}

export interface CampaignWorkflowNode {
	id: string;
	type: CampaignWorkflowNodeType;
	label: string;
	position: { x: number; y: number };
	config: Record<string, unknown>;
	runtimeStatus?: 'idle' | 'running' | 'success' | 'error';
	runtimeMessage?: string;
	runtimeDurationMs?: number;
}

export interface CampaignWorkflowEdge {
	id: string;
	fromNode: string;
	fromPort: string;
	toNode: string;
	toPort: string;
}

export interface CampaignWorkflow {
	id: string;
	name: string;
	enabled: boolean;
	nodes: CampaignWorkflowNode[];
	edges: CampaignWorkflowEdge[];
	lastRunAt: number | null;
	lastRunStatus: 'success' | 'error' | null;
	runCount: number;
	createdAt: number;
	updatedAt: number;
}

export interface CampaignWorkflowNodeDef {
	type: CampaignWorkflowNodeType;
	category: CampaignWorkflowNodeCategory;
	label: string;
	icon: string;
	description: string;
	inputs: CampaignWorkflowNodePort[];
	outputs: CampaignWorkflowNodePort[];
	configSchema: { key: string; label: string; type: 'text' | 'number' | 'select' | 'textarea' | 'cron'; options?: string[]; placeholder?: string }[];
}

export const CAMPAIGN_NODE_CATALOG: CampaignWorkflowNodeDef[] = [
	// ── Triggers ──
	{
		type: 'campaign-start',
		category: 'trigger',
		label: 'Campaign Start',
		icon: '\u25B6',
		description: 'Manual kick-off for this campaign workflow',
		inputs: [],
		outputs: [{ name: 'trigger', type: 'trigger' }],
		configSchema: [
			{ key: 'description', label: 'Description', type: 'text', placeholder: 'Launch campaign' },
		],
	},
	{
		type: 'schedule-trigger',
		category: 'trigger',
		label: 'Schedule Trigger',
		icon: '\u23F0',
		description: 'Fire on a cron schedule',
		inputs: [],
		outputs: [{ name: 'trigger', type: 'trigger' }, { name: 'timestamp', type: 'data' }],
		configSchema: [
			{ key: 'cronExpression', label: 'Cron Expression', type: 'cron', placeholder: '0 9 * * 1' },
			{ key: 'timezone', label: 'Timezone', type: 'text', placeholder: 'America/Vancouver' },
		],
	},
	{
		type: 'webhook-trigger',
		category: 'trigger',
		label: 'Webhook Trigger',
		icon: '\uD83D\uDD17',
		description: 'Fire when an external webhook is received',
		inputs: [],
		outputs: [{ name: 'trigger', type: 'trigger' }, { name: 'payload', type: 'data' }],
		configSchema: [
			{ key: 'hookId', label: 'Hook ID', type: 'text', placeholder: 'auto-generated' },
		],
	},
	// ── Delays ──
	{
		type: 'wait-duration',
		category: 'delay',
		label: 'Wait Duration',
		icon: '\u23F3',
		description: 'Wait for a specified amount of time',
		inputs: [{ name: 'trigger', type: 'trigger' }],
		outputs: [{ name: 'done', type: 'trigger' }],
		configSchema: [
			{ key: 'amount', label: 'Amount', type: 'number', placeholder: '2' },
			{ key: 'unit', label: 'Unit', type: 'select', options: ['minutes', 'hours', 'days'] },
		],
	},
	{
		type: 'wait-approval',
		category: 'delay',
		label: 'Wait for Approval',
		icon: '\u270B',
		description: 'Pause until a team member approves',
		inputs: [{ name: 'trigger', type: 'trigger' }],
		outputs: [{ name: 'approved', type: 'trigger' }, { name: 'rejected', type: 'trigger' }],
		configSchema: [
			{ key: 'approver', label: 'Approver', type: 'text', placeholder: 'Team lead' },
			{ key: 'message', label: 'Approval Message', type: 'textarea', placeholder: 'Please review...' },
		],
	},
	// ── Conditions ──
	{
		type: 'engagement-check',
		category: 'condition',
		label: 'Engagement Check',
		icon: '\uD83D\uDCC8',
		description: 'Check if engagement exceeds a threshold',
		inputs: [{ name: 'trigger', type: 'trigger' }, { name: 'metrics', type: 'data' }],
		outputs: [{ name: 'above', type: 'trigger' }, { name: 'below', type: 'trigger' }],
		configSchema: [
			{ key: 'metric', label: 'Metric', type: 'select', options: ['likes', 'retweets', 'replies', 'impressions', 'clicks'] },
			{ key: 'threshold', label: 'Threshold', type: 'number', placeholder: '100' },
		],
	},
	{
		type: 'time-window',
		category: 'condition',
		label: 'Time Window',
		icon: '\uD83D\uDD50',
		description: 'Check if current time is within posting hours',
		inputs: [{ name: 'trigger', type: 'trigger' }],
		outputs: [{ name: 'in-window', type: 'trigger' }, { name: 'outside', type: 'trigger' }],
		configSchema: [
			{ key: 'startHour', label: 'Start Hour (0-23)', type: 'number', placeholder: '9' },
			{ key: 'endHour', label: 'End Hour (0-23)', type: 'number', placeholder: '17' },
			{ key: 'days', label: 'Days (1=Mon)', type: 'text', placeholder: '1,2,3,4,5' },
		],
	},
	// ── Actions ──
	{
		type: 'post-to-platform',
		category: 'action',
		label: 'Post to Platform',
		icon: '\uD83D\uDCE4',
		description: 'Publish a post to a social platform',
		inputs: [{ name: 'trigger', type: 'trigger' }, { name: 'content', type: 'data' }],
		outputs: [{ name: 'done', type: 'trigger' }, { name: 'postId', type: 'data' }],
		configSchema: [
			{ key: 'platform', label: 'Platform', type: 'select', options: ['X', 'LinkedIn', 'Instagram', 'Threads', 'Bluesky', 'YouTube'] },
			{ key: 'content', label: 'Post Content', type: 'textarea', placeholder: 'Your post text...' },
			{ key: 'hashtags', label: 'Hashtags', type: 'text', placeholder: '#launch #campaign' },
		],
	},
	{
		type: 'cross-post',
		category: 'action',
		label: 'Cross-Post',
		icon: '\uD83D\uDCE1',
		description: 'Broadcast to multiple platforms at once',
		inputs: [{ name: 'trigger', type: 'trigger' }, { name: 'content', type: 'data' }],
		outputs: [{ name: 'done', type: 'trigger' }, { name: 'results', type: 'data' }],
		configSchema: [
			{ key: 'platforms', label: 'Platforms (comma-sep)', type: 'text', placeholder: 'X, LinkedIn, Threads' },
			{ key: 'content', label: 'Post Content', type: 'textarea', placeholder: 'Shared content...' },
			{ key: 'adaptPerPlatform', label: 'Adapt per platform', type: 'select', options: ['yes', 'no'] },
		],
	},
	{
		type: 'publish-thread',
		category: 'action',
		label: 'Publish Thread',
		icon: '\uD83E\uDDF5',
		description: 'Publish a multi-tweet thread',
		inputs: [{ name: 'trigger', type: 'trigger' }],
		outputs: [{ name: 'done', type: 'trigger' }, { name: 'threadId', type: 'data' }],
		configSchema: [
			{ key: 'platform', label: 'Platform', type: 'select', options: ['X', 'Bluesky', 'Threads'] },
			{ key: 'threadId', label: 'Thread ID (link existing)', type: 'text', placeholder: 'Leave empty to use inline content' },
			{ key: 'threadContent', label: 'Thread (--- between tweets)', type: 'textarea', placeholder: 'Tweet 1\n---\nTweet 2\n---\nTweet 3' },
		],
	},
	{
		type: 'send-newsletter',
		category: 'action',
		label: 'Send Newsletter',
		icon: '\uD83D\uDCE7',
		description: 'Send an email campaign via Listmonk',
		inputs: [{ name: 'trigger', type: 'trigger' }, { name: 'content', type: 'data' }],
		outputs: [{ name: 'done', type: 'trigger' }, { name: 'campaignId', type: 'data' }],
		configSchema: [
			{ key: 'subject', label: 'Email Subject', type: 'text', placeholder: 'Newsletter: Campaign Update' },
			{ key: 'listId', label: 'List ID', type: 'text', placeholder: '1' },
			{ key: 'bodyTemplate', label: 'Body (HTML)', type: 'textarea', placeholder: '<p>Hello {{name}}</p>' },
		],
	},
	{
		type: 'post-webhook',
		category: 'action',
		label: 'POST Webhook',
		icon: '\uD83C\uDF10',
		description: 'Send an HTTP POST to an external URL',
		inputs: [{ name: 'trigger', type: 'trigger' }, { name: 'data', type: 'data' }],
		outputs: [{ name: 'done', type: 'trigger' }, { name: 'response', type: 'data' }],
		configSchema: [
			{ key: 'url', label: 'URL', type: 'text', placeholder: 'https://api.example.com/hook' },
			{ key: 'bodyTemplate', label: 'Body Template', type: 'textarea', placeholder: '{"event": "campaign_step"}' },
		],
	},
];

// ── Newsletter draft types ──

export interface NewsletterSubscriber {
	email: string;
	name?: string;
	addedAt: number;
}

export interface NewsletterDraft {
	id: string;
	title: string;
	subject: string;
	body: string; // HTML
	status: 'draft' | 'ready' | 'sent';
	subscribers: NewsletterSubscriber[];
	createdAt: number;
	updatedAt: number;
	createdBy: string;
}

// ── Approval queue types ──

export interface PendingApproval {
	id: string;
	workflowId: string;
	nodeId: string;
	message: string;
	approver: string;
	status: 'pending' | 'approved' | 'rejected';
	createdAt: number;
	resolvedAt: number | null;
}

// ── Campaign wizard types ──

export interface ExtractedBrief {
	title: string;
	audience: string;
	startDate: string;  // ISO
	endDate: string;
	platforms: string[];
	tone: string;
	style: string;
	keyMessages: string[];
}

export interface CampaignStructure {
	phases: {
		name: string;
		label: string;
		days: string;
		platforms: string[];
		cadence: Record<string, number>;  // platform → post count
	}[];
	summary: string;
}

export interface CampaignWizard {
	id: string;
	step: 'brief' | 'structure' | 'content' | 'review' | 'committed' | 'abandoned';
	rawBrief: string;
	extractedBrief: ExtractedBrief | null;
	structure: CampaignStructure | null;
	campaignDraft: Campaign | null;
	committedCampaignId: string | null;
	createdAt: number;
	updatedAt: number;
	createdBy: string | null;
}

// ── Document root ──

export interface SocialsDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	threads: Record<string, ThreadData>;
	campaigns: Record<string, Campaign>;
	campaignFlows: Record<string, CampaignFlow>;
	activeFlowId: string;
	campaignWorkflows: Record<string, CampaignWorkflow>;
	pendingApprovals: Record<string, PendingApproval>;
	campaignWizards: Record<string, CampaignWizard>;
	newsletterDrafts: Record<string, NewsletterDraft>;
}

// ── Schema registration ──

export const socialsSchema: DocSchema<SocialsDoc> = {
	module: 'socials',
	collection: 'data',
	version: 8,
	init: (): SocialsDoc => ({
		meta: {
			module: 'socials',
			collection: 'data',
			version: 8,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		threads: {},
		campaigns: {},
		campaignFlows: {},
		activeFlowId: '',
		campaignWorkflows: {},
		pendingApprovals: {},
		campaignWizards: {},
		newsletterDrafts: {},
	}),
	migrate: (doc: SocialsDoc, _fromVersion: number): SocialsDoc => {
		if (!doc.campaignFlows) (doc as any).campaignFlows = {};
		if (!doc.activeFlowId) (doc as any).activeFlowId = '';
		if (!doc.campaignWorkflows) (doc as any).campaignWorkflows = {};
		if (!doc.pendingApprovals) (doc as any).pendingApprovals = {};
		if (!doc.campaignWizards) (doc as any).campaignWizards = {};
		if (!doc.newsletterDrafts) (doc as any).newsletterDrafts = {};
		if (doc.meta) doc.meta.version = 8;
		return doc;
	},
};

// ── Helpers ──

export function socialsDocId(space: string) {
	return `${space}:socials:data` as const;
}
