import { printArgPath } from "./print-arg-path.js";
import type { BaseContext } from "koa";
import type { ComponentArgument, TableData } from "@sealcode/jdd";
import { ComponentArguments, Enum, Image, List, Structured, Table } from "@sealcode/jdd";
import { ComponentInputStructured } from "./component-input-structured.js";
import type { StatefulPage } from "@sealcode/sealgen";
import type { ComponentPreviewActions } from "./component-preview-actions.js";
import type { Readable } from "node:stream";
import { ComponentInputList } from "./component-input-list.js";
import type { JDDPageState } from "./jdd-page.js";
import { ComponentInputEnum } from "./component-input-enum.js";
import { ComponentInputImage } from "./component-input-image.js";
import { ComponentInputTable } from "./component-input-table.js";
import { TempstreamJSX } from "tempstream";
import type { FilePointer } from "@sealcode/file-manager";
import { is, predicates } from "@sealcode/ts-predicates";

export const actionName = "Components";
const absoluteUrlPattern = "http(s?)(://)((www.)?)(([^.]+).)?([a-zA-z0-9-_]+)";

export function ComponentInput<State extends JDDPageState, T>({
	ctx,
	state,
	arg_path,
	arg,
	value,
	page,
}: {
	state: State;
	ctx: BaseContext;
	arg_path: string[];
	arg: ComponentArgument<T>;
	value: T;
	page: StatefulPage<JDDPageState, typeof ComponentPreviewActions>;
}): Readable | Promise<Readable> {
	if (value === undefined) {
		value = arg.getEmptyValue();
	}
	if (arg instanceof List) {
		// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
		return ComponentInputList({
			ctx,
			state,
			arg_path,
			arg,
			// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
			value: value as T[],
			page,
		});
	}

	const argType = arg.getTypeName();
	const isUrlAbsolute =
		arg instanceof ComponentArguments.URL && arg.urlType === "absolute";
	const inputType = isUrlAbsolute ? "url" : "text";

	if (arg instanceof Structured) {
		return ComponentInputStructured({
			ctx,
			state,
			arg_path,
			arg,
			// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
			value: value as Record<string, unknown>,
			page,
		});
	}

	if (arg instanceof Enum) {
		return ComponentInputEnum({
			state,
			arg_path,
			arg,
			// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
			value: value as string,
			onchange: page.rerender(),
		});
	}

	if (arg instanceof Image) {
		return ComponentInputImage({
			ctx,
			state,
			arg_path,
			arg,
			// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
			value: value as FilePointer,
			page,
		});
	}

	if (arg instanceof Table) {
		return ComponentInputTable({
			ctx,
			state,
			arg_path,
			arg,
			// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
			value: value as TableData<unknown, unknown>,
			page,
		});
	}

	return (
		<div>
			<label>
				{arg_path.at(-1) || ""}
				{argType == "markdown" ? (
					<textarea
						name={`$${printArgPath(arg_path)}`}
						onblur={page.rerender()}
						cols="40"
					>
						{is(value, predicates.string) ? value : ""}
					</textarea>
				) : (
					<input
						type={inputType}
						name={`$${printArgPath(arg_path)}`}
						value={is(value, predicates.string) ? value : ""}
						size="40"
						pattern={isUrlAbsolute ? absoluteUrlPattern : undefined}
					/>
				)}
			</label>
		</div>
	);
}
