import { type RefObject, type ReactNode, Suspense, useState, useCallback } from 'react';
import { WebSocket } from 'partysocket';
import { MonacoEditor } from '../../../components/monaco-editor/lazy-monaco-editor';
import { motion } from 'framer-motion';
import { RefreshCw } from 'lucide-react';
import { Blueprint } from './blueprint';
import { FileExplorer } from './file-explorer';
import { PreviewIframe } from './preview-iframe';
import { PreviewCompatBanner } from './preview-compat-banner';
import { MarkdownDocsPreview } from './markdown-docs-preview';
import { ViewContainer } from './view-container';
import { ViewHeader } from './view-header';
import { PreviewHeaderActions } from './preview-header-actions';
import { EditorHeaderActions } from './editor-header-actions';
import { Copy } from './copy';
import { DatabaseViewer } from './database-viewer';
import { ArtifactRepoViewerPanel } from './artifact-repo-viewer';
import { featureRegistry } from '@/features';
import type { FileType, BlueprintType, BehaviorType, ModelConfigsInfo, TemplateDetails, ProjectType } from '@/api-types';
import type { ContentDetectionResult } from '../utils/content-detector';
import type { GitHubExportHook } from '@/hooks/use-github-export';
import type { Edit } from '../hooks/use-chat';

interface MainContentPanelProps {
	// View state
	view: 'editor' | 'preview' | 'docs' | 'blueprint' | 'terminal' | 'presentation' | 'database' | 'repo';
	onViewChange: (mode: 'preview' | 'editor' | 'docs' | 'blueprint' | 'presentation' | 'database' | 'repo') => void;

	// Content detection
	hasDocumentation: boolean;
	contentDetection: ContentDetectionResult;

	// Preview state
	projectType: ProjectType;
	previewUrl?: string;
	previewAvailable: boolean;
	showTooltip: boolean;
	shouldRefreshPreview: boolean;
	manualRefreshTrigger: number;
	onManualRefresh: () => void;

	// Blueprint
	blueprint?: BlueprintType | null;

	// Editor state
	activeFile?: FileType;
	allFiles: FileType[];
	edit?: Edit | null;
	onFileClick: (file: FileType) => void;

	// Generation state
	isGenerating: boolean;
	isGeneratingBlueprint: boolean;

	// Model configs
	modelConfigs?: ModelConfigsInfo;
	loadingConfigs: boolean;
	onRequestConfigs: () => void;

	// Git/GitHub actions
	onGitCloneClick: () => void;
	isGitHubExportReady: boolean;
	githubExport: GitHubExportHook;

	// Template metadata
	templateDetails?: TemplateDetails | null;

	// Other
	behaviorType?: BehaviorType;
	websocket?: WebSocket;

	// DB tab (think-behavior only)
	agentId?: string;
	databaseAvailable: boolean;

	// Repo tab (think-behavior only) — read-only Artifacts repository viewer
	repoAvailable: boolean;

	// Refs
	previewRef: RefObject<HTMLIFrameElement | null>;
	editorRef: RefObject<HTMLDivElement | null>;
}

export function MainContentPanel(props: MainContentPanelProps) {
	const {
		view,
		onViewChange,
		hasDocumentation,
		contentDetection,
		projectType,
		previewUrl,
		previewAvailable,
		showTooltip,
		shouldRefreshPreview,
		manualRefreshTrigger,
		onManualRefresh,
		blueprint,
		activeFile,
		allFiles,
		edit,
		onFileClick,
		isGenerating,
		isGeneratingBlueprint,
		modelConfigs,
		loadingConfigs,
		onRequestConfigs,
		onGitCloneClick,
		isGitHubExportReady,
		githubExport,
		behaviorType,
		websocket,
		previewRef,
		editorRef,
		templateDetails,
		agentId,
		databaseAvailable,
		repoAvailable,
	} = props;

	// Think apps surface Clone/GitHub inside the Repo tab, so hide them from the
	// generic preview/editor header to avoid duplication.
	const showHeaderGitActions = !(behaviorType === 'think' && repoAvailable);

	// Feature-specific state management
	const [featureState, setFeatureStateInternal] = useState<Record<string, unknown>>({});
	const setFeatureState = useCallback((key: string, value: unknown) => {
		setFeatureStateInternal(prev => ({ ...prev, [key]: value }));
	}, []);

	const commonHeaderProps = {
		view: view as 'preview' | 'editor' | 'docs' | 'blueprint' | 'presentation' | 'database' | 'repo',
		onViewChange,
		previewAvailable,
		showTooltip,
		hasDocumentation,
		previewUrl,
		projectType,
		databaseAvailable,
		repoAvailable,
	};

	const renderViewWithHeader = (
		centerContent: ReactNode,
		viewContent: ReactNode,
		rightActions?: ReactNode,
		headerOverrides?: Partial<typeof commonHeaderProps>
	) => (
		<ViewContainer>
			<ViewHeader
				{...commonHeaderProps}
				{...headerOverrides}
				centerContent={centerContent}
				rightActions={rightActions}
			/>
			{viewContent}
		</ViewContainer>
	);

	const renderDocsView = () => {
		if (!hasDocumentation) return null;

		const markdownFiles = Object.values(contentDetection.Contents)
			.filter(bundle => bundle.type === 'markdown')
			.flatMap(bundle => bundle.files);

		if (markdownFiles.length === 0) return null;

		return renderViewWithHeader(
			<span className="text-sm font-mono text-text-50/70">Documentation</span>,
			<MarkdownDocsPreview
				files={markdownFiles}
				isGenerating={isGenerating || isGeneratingBlueprint}
			/>
		);
	};

	const renderPreviewView = () => {
		if (!previewUrl) {
			return null;
		}

		// Get feature capabilities to determine preview behavior
		const featureCapabilities = featureRegistry.getCapabilities(projectType);
		const featureDefinition = featureRegistry.getDefinition(projectType);
		const previewTitle = blueprint?.title ?? featureDefinition?.name ?? 'Preview';

		// Check if we should show the refresh button (presentations handle refresh differently)
		const showManualRefresh = featureCapabilities?.hasLiveReload ?? true;

		// Get lazy-loaded preview component from feature registry
		const FeaturePreviewComponent = featureRegistry.getLazyPreviewComponent(projectType);

		// Fallback to default PreviewIframe if no feature-specific component
		const previewContent = FeaturePreviewComponent ? (
			<Suspense
				fallback={
					<div className="flex-1 w-full h-full flex items-center justify-center bg-kumo-base">
						<RefreshCw className="size-6 text-kumo-brand animate-spin" />
					</div>
				}
			>
				<FeaturePreviewComponent
					projectType={projectType}
					behaviorType={behaviorType ?? 'phasic'}
					previewUrl={previewUrl}
					websocket={websocket}
					files={allFiles}
					activeFile={activeFile}
					currentView={view}
					onViewChange={(v) => onViewChange(v as 'preview' | 'editor' | 'docs' | 'blueprint' | 'presentation')}
					templateDetails={templateDetails}
					modelConfigs={modelConfigs}
					blueprint={blueprint}
					previewRef={previewRef}
					editorRef={editorRef}
					shouldRefreshPreview={shouldRefreshPreview}
					manualRefreshTrigger={manualRefreshTrigger}
					onManualRefresh={onManualRefresh}
					featureState={featureState}
					setFeatureState={setFeatureState}
					className="flex-1 w-full h-full border-0"
				/>
			</Suspense>
		) : (
			<PreviewIframe
				src={previewUrl}
				ref={previewRef}
				className="flex-1 w-full h-full border-0"
				title="Preview"
				shouldRefreshPreview={shouldRefreshPreview}
				manualRefreshTrigger={manualRefreshTrigger}
				webSocket={websocket}
			/>
		);

		// Get lazy-loaded header actions component from feature registry
		const FeatureHeaderActionsComponent = featureRegistry.getLazyHeaderActionsComponent(projectType);

		// Fallback to PreviewHeaderActions if no feature-specific component
		const headerActions = FeatureHeaderActionsComponent ? (
			<Suspense fallback={null}>
				<FeatureHeaderActionsComponent
					projectType={projectType}
					behaviorType={behaviorType ?? 'phasic'}
					previewUrl={previewUrl}
					websocket={websocket}
					files={allFiles}
					activeFile={activeFile}
					currentView={view}
					onViewChange={(v) => onViewChange(v as 'preview' | 'editor' | 'docs' | 'blueprint' | 'presentation')}
					templateDetails={templateDetails}
					modelConfigs={modelConfigs}
					blueprint={blueprint}
					previewRef={previewRef}
					editorRef={editorRef}
					shouldRefreshPreview={shouldRefreshPreview}
					manualRefreshTrigger={manualRefreshTrigger}
					onManualRefresh={onManualRefresh}
					featureState={featureState}
					setFeatureState={setFeatureState}
					onGitCloneClick={onGitCloneClick}
					isGitHubExportReady={isGitHubExportReady}
					onGitHubExportClick={githubExport.openModal}
					showGitActions={showHeaderGitActions}
					loadingConfigs={loadingConfigs}
					onRequestConfigs={onRequestConfigs}
				/>
			</Suspense>
		) : (
			<PreviewHeaderActions
				modelConfigs={modelConfigs}
				onRequestConfigs={onRequestConfigs}
				loadingConfigs={loadingConfigs}
				onGitCloneClick={onGitCloneClick}
				isGitHubExportReady={isGitHubExportReady}
				onGitHubExportClick={githubExport.openModal}
				showGitActions={showHeaderGitActions}
				previewRef={previewRef}
			/>
		);

		return renderViewWithHeader(
			<div className="flex min-w-0 items-center gap-2">
				<span
					className="truncate text-sm font-mono text-text-50/70"
					title={previewTitle}
				>
					{previewTitle}
				</span>
				<span className="shrink-0">
					<Copy text={previewUrl} />
				</span>
				{showManualRefresh && (
					<button
						className="shrink-0 p-1 hover:bg-kumo-elevated rounded transition-colors"
						onClick={onManualRefresh}
						title="Refresh preview"
					>
						<RefreshCw className="size-4 text-text-primary/50" />
					</button>
				)}
			</div>,
			<div className="flex flex-1 min-h-0 flex-col">
				<PreviewCompatBanner previewUrl={previewUrl} />
				<div className="relative flex flex-1 min-h-0 flex-col">{previewContent}</div>
			</div>,
			headerActions
		);
	};

	const renderBlueprintView = () =>
		renderViewWithHeader(
			<div className="flex items-center gap-2">
				<span className="text-sm text-text-50/70 font-mono">Blueprint.md</span>
				{previewUrl && <Copy text={previewUrl} />}
			</div>,
			<div className="flex-1 overflow-y-auto bg-kumo-base">
				<div className="py-12 mx-auto">
					<Blueprint
						blueprint={blueprint ?? ({} as BlueprintType)}
						className="w-full max-w-2xl mx-auto"
					/>
				</div>
			</div>
		);

	const renderEditorView = () => {
		// Defensive fallback: show file explorer with empty editor if no activeFile
		if (!activeFile) {
			return renderViewWithHeader(
				<div className="flex items-center gap-2">
					<span className="text-sm font-mono text-text-50/70">Select a file</span>
				</div>,
				<div className="flex-1 relative">
					<div className="absolute inset-0 flex" ref={editorRef}>
						<FileExplorer
							files={allFiles}
							currentFile={undefined}
							onFileClick={onFileClick}
						/>
						<div className="flex-1 flex items-center justify-center bg-kumo-base">
							<span className="text-text-50/50 text-sm">No file selected</span>
						</div>
					</div>
				</div>,
				<EditorHeaderActions
					modelConfigs={modelConfigs}
					onRequestConfigs={onRequestConfigs}
					loadingConfigs={loadingConfigs}
					onGitCloneClick={onGitCloneClick}
					isGitHubExportReady={isGitHubExportReady}
					onGitHubExportClick={githubExport.openModal}
					showGitActions={showHeaderGitActions}
					editorRef={editorRef}
				/>
			);
		}

		return renderViewWithHeader(
			<div className="flex items-center gap-2">
				<span className="text-sm font-mono text-text-50/70">{activeFile.filePath}</span>
				{previewUrl && <Copy text={previewUrl} />}
			</div>,
			<div className="flex-1 relative">
				<div className="absolute inset-0 flex" ref={editorRef}>
					<FileExplorer
						files={allFiles}
						currentFile={activeFile}
						onFileClick={onFileClick}
					/>
					<div className="flex-1">
						<MonacoEditor
							className="h-full"
							path={activeFile.filePath}
							stickToBottom={!!activeFile.isGenerating}
							createOptions={{
								value: activeFile.fileContents || '',
								language: activeFile.language || 'plaintext',
								readOnly: true,
								minimap: { enabled: false },
								lineNumbers: 'on',
								scrollBeyondLastLine: false,
								fontSize: 13,
								automaticLayout: true,
							}}
							find={edit?.filePath === activeFile.filePath ? edit.search : undefined}
							replace={edit?.filePath === activeFile.filePath ? edit.replacement : undefined}
						/>
					</div>
				</div>
			</div>,
			<EditorHeaderActions
				modelConfigs={modelConfigs}
				onRequestConfigs={onRequestConfigs}
				loadingConfigs={loadingConfigs}
				onGitCloneClick={onGitCloneClick}
				isGitHubExportReady={isGitHubExportReady}
				onGitHubExportClick={githubExport.openModal}
				showGitActions={showHeaderGitActions}
				editorRef={editorRef}
			/>
		);
	};

	const renderDatabaseView = () => {
		if (!databaseAvailable || !agentId) return null;
		return renderViewWithHeader(
			<div className="flex items-center gap-2">
				<span className="text-sm font-mono text-text-50/70">Database</span>
			</div>,
			<DatabaseViewer agentId={agentId} enabled={view === 'database'} />,
		);
	};

	const renderRepoView = () => {
		if (!repoAvailable || !agentId) return null;
		return renderViewWithHeader(
			<div className="flex items-center gap-2">
				<span className="text-sm font-mono text-text-50/70">Repository</span>
			</div>,
			<ArtifactRepoViewerPanel
				repoName={agentId}
				enabled={view === 'repo'}
				onGitCloneClick={onGitCloneClick}
				isGitHubExportReady={isGitHubExportReady}
				onGitHubExportClick={githubExport.openModal}
			/>,
		);
	};

	const renderView = () => {
		switch (view) {
			case 'docs':
				return renderDocsView();
			case 'preview':
			case 'presentation': // Presentations now use preview view
				return renderPreviewView();
			case 'blueprint':
				return renderBlueprintView();
			case 'editor':
				return renderEditorView();
			case 'database':
				return renderDatabaseView();
			case 'repo':
				return renderRepoView();
			default:
				return null;
		}
	};

	return (
		<motion.div
			className="flex-1 flex flex-col min-h-0 min-w-0 overflow-hidden"
			initial={{ opacity: 0, scale: 0.84 }}
			animate={{ opacity: 1, scale: 1 }}
			transition={{ duration: 0.3, ease: 'easeInOut' }}
		>
			{renderView()}
		</motion.div>
	);
}
