/**
 * Smart Block Editor
 *
 * AI-powered block editor that generates content structure and HTML templates
 * from natural language prompts.
 */

import React, { useState, useCallback, useMemo } from "react";
import {
	// Types
	type BlockEditorProps,
	type Generation,
	type SmartBlockMeta,
	// Components
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
	Tabs,
	TabsContent,
	TabsList,
	TabsTrigger,
	ScrollArea,
	Button,
	Input,
	Textarea,
	Label,
	Badge,
	Monaco,
	Loader2,
	Sparkles,
	Check,
	Code,
	History,
	Wand2,
	Send,
	Edit3,
	// Hooks
	useAIGenerate,
	useAIAssist,
} from "@block-ninja/ui";

function SmartBlockEditor({ content, onChange }: BlockEditorProps) {
	const [activeTab, setActiveTab] = useState("generate");
	const [prompt, setPrompt] = useState("");
	const [assistPrompt, setAssistPrompt] = useState("");
	const [lastExplanation, setLastExplanation] = useState("");

	const { generate, isLoading: isGenerating } = useAIGenerate();
	const { assist, isLoading: isAssisting } = useAIAssist();

	// Extract meta and current generation
	const meta = useMemo<SmartBlockMeta>(() => {
		return (content._meta as SmartBlockMeta) ?? { currentGenerationId: "", generations: [] };
	}, [content._meta]);
	const currentGeneration = useMemo(() => meta.generations?.find((g: Generation) => g.id === meta.currentGenerationId), [meta]);
	const currentTemplate = currentGeneration?.template || "";

	// Get content fields (excluding _meta)
	const contentFields = useMemo(() => {
		const fields: Record<string, unknown> = {};
		for (const [key, value] of Object.entries(content)) {
			if (!key.startsWith("_")) {
				fields[key] = value;
			}
		}
		return fields;
	}, [content]);

	// Handle generate
	const handleGenerate = useCallback(async () => {
		if (!prompt.trim()) return;

		try {
			const result = await generate(prompt, currentTemplate);

			const newGeneration: Generation = {
				id: result.generationId,
				prompt: prompt,
				schema: result.schema,
				template: result.template,
				createdAt: new Date().toISOString(),
			};

			const updatedMeta: SmartBlockMeta = {
				currentGenerationId: result.generationId,
				generations: [...(meta.generations || []), newGeneration],
			};

			// Clear old content fields and add new schema defaults
			const newContent: Record<string, unknown> = { _meta: updatedMeta };
			if (result.schema?.properties) {
				for (const key of Object.keys(result.schema.properties as Record<string, unknown>)) {
					newContent[key] = "";
				}
			}

			onChange(newContent);
			setLastExplanation(result.explanation);
			setPrompt("");
			setActiveTab("content");
		} catch (error) {
			console.error("Generation failed:", error);
		}
	}, [prompt, currentTemplate, meta, generate, onChange]);

	// Handle assist
	const handleAssist = useCallback(async () => {
		if (!assistPrompt.trim() || !currentTemplate) return;

		try {
			const result = await assist(assistPrompt, currentTemplate, currentGeneration?.schema ? JSON.stringify(currentGeneration.schema) : undefined);

			// Update the current generation's template
			const updatedGenerations = (meta.generations || []).map((g: Generation) => (g.id === meta.currentGenerationId ? { ...g, template: result.template } : g));

			onChange({
				...content,
				_meta: { ...meta, generations: updatedGenerations },
			});

			setLastExplanation(result.explanation);
			setAssistPrompt("");
		} catch (error) {
			console.error("Assist failed:", error);
		}
	}, [assistPrompt, currentTemplate, currentGeneration, meta, content, assist, onChange]);

	// Handle template change (direct edit)
	const handleTemplateChange = useCallback(
		(newTemplate: string | undefined) => {
			if (!newTemplate || !currentGeneration) return;

			const updatedGenerations = (meta.generations || []).map((g: Generation) => (g.id === meta.currentGenerationId ? { ...g, template: newTemplate } : g));

			onChange({
				...content,
				_meta: { ...meta, generations: updatedGenerations },
			});
		},
		[currentGeneration, meta, content, onChange],
	);

	// Handle switching generation
	const handleSwitchGeneration = useCallback(
		(generationId: string) => {
			const generation = meta.generations?.find((g: Generation) => g.id === generationId);
			if (!generation) return;

			// Clear current content and set defaults from new schema
			const newContent: Record<string, unknown> = {
				_meta: { ...meta, currentGenerationId: generationId },
			};

			if (generation.schema?.properties) {
				for (const key of Object.keys(generation.schema.properties as Record<string, unknown>)) {
					newContent[key] = content[key] ?? "";
				}
			}

			onChange(newContent);
			setActiveTab("content");
		},
		[meta, content, onChange],
	);

	// Handle content field change
	const handleFieldChange = useCallback(
		(fieldName: string, value: unknown) => {
			onChange({ ...content, [fieldName]: value });
		},
		[content, onChange],
	);

	// Render content fields based on schema
	const renderContentFields = () => {
		const schema = currentGeneration?.schema as Record<string, unknown> | undefined;
		if (!schema?.properties) {
			return (
				<div className="text-center py-8 text-muted-foreground">
					<p>Generate content structure first</p>
				</div>
			);
		}

		const properties = Object.entries(schema.properties as Record<string, unknown>);
		const requiredFields = new Set((schema.required as string[]) || []);

		return (
			<Card>
				<CardHeader className="pb-2">
					<CardTitle className="text-sm">Content Fields</CardTitle>
				</CardHeader>
				<CardContent className="space-y-4">
					{properties.map(([name, prop]) => {
						const propObj = prop as Record<string, unknown>;
						const isRequired = requiredFields.has(name);
						const editor = (propObj["x-editor"] as string) || "text";
						let inputType = "text";
						if (editor === "number") {
							inputType = "number";
						} else if (editor === "url") {
							inputType = "url";
						}

						return (
							<div key={name} className="space-y-2">
								<Label htmlFor={name}>
									{(propObj.title as string) || (propObj.description as string) || name}
									{isRequired && <span className="text-destructive ml-1">*</span>}
								</Label>
								{editor === "textarea" ?
									<Textarea
										id={name}
										value={(contentFields[name] as string) || ""}
										onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => handleFieldChange(name, e.target.value)}
										placeholder={propObj.description as string}
										rows={4}
									/>
								:	<Input
										id={name}
										type={inputType}
										value={(contentFields[name] as string) || ""}
										onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleFieldChange(name, e.target.value)}
										placeholder={propObj.description as string}
									/>
								}
							</div>
						);
					})}
				</CardContent>
			</Card>
		);
	};

	return (
		<div className="space-y-4">
			<Tabs value={activeTab} onValueChange={setActiveTab}>
				<TabsList className="grid w-full grid-cols-4">
					<TabsTrigger value="generate" className="gap-2">
						<Wand2 className="h-4 w-4" />
						Generate
					</TabsTrigger>
					<TabsTrigger value="content" className="gap-2" disabled={!currentGeneration}>
						<Edit3 className="h-4 w-4" />
						Content
					</TabsTrigger>
					<TabsTrigger value="html" className="gap-2" disabled={!currentGeneration}>
						<Code className="h-4 w-4" />
						HTML
					</TabsTrigger>
					<TabsTrigger value="history" className="gap-2" disabled={(meta.generations?.length || 0) === 0}>
						<History className="h-4 w-4" />
						History
					</TabsTrigger>
				</TabsList>

				{/* Generate Tab */}
				<TabsContent value="generate" className="space-y-4">
					<Card>
						<CardHeader>
							<CardTitle className="flex items-center gap-2">
								<Sparkles className="h-5 w-5 text-primary" />
								Generate Content Structure
							</CardTitle>
							<CardDescription>Describe the content you want to create. AI will generate both the form fields and HTML template.</CardDescription>
						</CardHeader>
						<CardContent className="space-y-4">
							<Textarea
								placeholder="E.g., Create a testimonial card with author photo, quote, name, title, and 5-star rating..."
								value={prompt}
								onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setPrompt(e.target.value)}
								className="min-h-[100px]"
							/>
							<div className="flex justify-between items-center">
								<p className="text-sm text-muted-foreground">{currentGeneration ? "Generating will create a new version" : "Start by describing your content"}</p>
								<Button action="create" entity="smart-block-generation" onClick={handleGenerate} disabled={isGenerating || !prompt.trim()}>
									{isGenerating ?
										<>
											<Loader2 className="h-4 w-4 mr-2 animate-spin" />
											Generating...
										</>
									:	<>
											<Wand2 className="h-4 w-4 mr-2" />
											Generate
										</>
									}
								</Button>
							</div>
						</CardContent>
					</Card>

					{lastExplanation && (
						<Card>
							<CardHeader className="pb-2">
								<CardTitle className="text-sm">AI Response</CardTitle>
							</CardHeader>
							<CardContent>
								<p className="text-sm text-muted-foreground">{lastExplanation}</p>
							</CardContent>
						</Card>
					)}

					{!currentGeneration && (
						<div className="text-center py-8 text-muted-foreground">
							<Wand2 className="h-12 w-12 mx-auto mb-4 opacity-50" />
							<p>No content structure generated yet</p>
							<p className="text-sm">Enter a prompt above to get started</p>
						</div>
					)}
				</TabsContent>

				{/* Content Tab */}
				<TabsContent value="content">{renderContentFields()}</TabsContent>

				{/* HTML Tab */}
				<TabsContent value="html" className="space-y-4">
					<Card>
						<CardHeader className="pb-2">
							<CardTitle className="text-sm flex items-center justify-between">
								HTML Template
								<Badge variant="outline">{Object.keys(((currentGeneration?.schema as Record<string, unknown>)?.properties as Record<string, unknown>) || {}).length} fields</Badge>
							</CardTitle>
						</CardHeader>
						<CardContent>
							<Monaco value={currentTemplate} onChange={handleTemplateChange} language="html" height="300px" theme="vs-dark" />
							<p className="text-xs text-muted-foreground mt-2">Use {"{{fieldName}}"} placeholders to insert content values</p>
						</CardContent>
					</Card>

					<Card>
						<CardHeader className="pb-2">
							<CardTitle className="text-sm flex items-center gap-2">
								<Sparkles className="h-4 w-4" />
								AI Assistant
							</CardTitle>
						</CardHeader>
						<CardContent className="space-y-2">
							<div className="flex gap-2">
								<Input
									placeholder="E.g., Make the quote italic and add a shadow..."
									value={assistPrompt}
									onChange={(e: React.ChangeEvent<HTMLInputElement>) => setAssistPrompt(e.target.value)}
									onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
										if (e.key === "Enter" && !e.shiftKey) {
											e.preventDefault();
											handleAssist();
										}
									}}
								/>
								<Button action="edit" entity="smart-block-template" onClick={handleAssist} disabled={isAssisting || !assistPrompt.trim()} size="icon">
									{isAssisting ?
										<Loader2 className="h-4 w-4 animate-spin" />
									:	<Send className="h-4 w-4" />}
								</Button>
							</div>
						</CardContent>
					</Card>
				</TabsContent>

				{/* History Tab */}
				<TabsContent value="history">
					<Card>
						<CardHeader>
							<CardTitle className="text-sm">Generation History</CardTitle>
							<CardDescription>Switch between previous generations or regenerate from a prompt</CardDescription>
						</CardHeader>
						<CardContent>
							<ScrollArea className="h-[300px]">
								<div className="space-y-2">
									{[...(meta.generations || [])].reverse().map((gen: Generation) => (
										<Button
											key={gen.id}
											type="button"
											variant="ghost"
											action="select"
											entity="smart-block-generation"
											className={`w-full h-auto justify-start p-3 rounded-lg border text-left font-normal whitespace-normal transition-colors hover:text-foreground [&_svg]:size-3 ${
												gen.id === meta.currentGenerationId ? "bg-primary/10 border-primary hover:bg-primary/10" : "hover:bg-muted"
											}`}
											onClick={() => handleSwitchGeneration(gen.id)}>
											<div className="w-full flex items-start justify-between gap-2">
												<div className="flex-1 min-w-0">
													<p className="text-sm font-medium truncate">{gen.prompt}</p>
													<p className="text-xs text-muted-foreground">{new Date(gen.createdAt).toLocaleString()}</p>
												</div>
												{gen.id === meta.currentGenerationId && (
													<Badge variant="default" className="shrink-0">
														<Check className="h-3 w-3 mr-1" />
														Active
													</Badge>
												)}
											</div>
										</Button>
									))}
								</div>
							</ScrollArea>
						</CardContent>
					</Card>
				</TabsContent>
			</Tabs>
		</div>
	);
}

// Export for plugin loader
export default SmartBlockEditor;
