import axios from "axios";
import configureStore from "redux-mock-store";
import thunk from "redux-thunk";
import { ThemeProvider } from "styled-components";

import "@testing-library/jest-dom";

import PageConnectedField from "@ax/components/ConfigPanel/Form/ConnectedField/PageConnectedField";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";

import { cleanup, fireEvent, render, screen } from "../../../../../../../config/jest/test-utils";

// Mocks configuration

beforeEach(() => {
	cleanup();
});

jest.mock("axios");
const mockedAxios = axios as jest.MockedFunction<typeof axios>;

// Mock @ax/schemas
jest.mock("@ax/schemas", () => ({
	getPageSchemas: jest.fn(() => ({})),
	getFixedSchemas: jest.fn(() => ({})),
}));

// Mock @ax/containers/PageEditor
jest.mock("@ax/containers/PageEditor", () => ({
	pageEditorActions: {
		updateEditorContent: jest.fn((_editorID: number, _key: string | string[], _value: any) => {
			return (dispatch: any, getState: any) => {
				const state = getState();
				dispatch({
					type: "pageEditor/SET_EDITOR_CONTENT",
					payload: { editorContent: state.pageEditor.editorContent || {} },
				});
				dispatch({
					type: "pageEditor/SET_SELECTED_PAGE_CONTENT",
					payload: { selectedContent: state.pageEditor.selectedContent || {} },
				});
			};
		}),
		overwriteHeaderConfig: jest.fn(() => ({
			type: "pageEditor/OVERWRITE_HEADER_CONFIG",
			payload: {},
		})),
		setCurrentPageName: jest.fn(() => ({
			type: "pageEditor/SET_CURRENT_PAGE_NAME",
			payload: {},
		})),
		getPageBreadcrumb: jest.fn(() => (dispatch: any) => {
			dispatch({
				type: "pageEditor/SET_BREADCRUMB",
				payload: {},
			});
		}),
		deleteError: jest.fn(() => ({
			type: "pageEditor/DELETE_ERROR",
			payload: {},
		})),
	},
}));

// Configuración de datos (store & props)

const middlewares: any = [thunk];
const mockStore = configureStore(middlewares);

const initialStore = {
	pageEditor: {
		selectedContent: {
			title: {
				component: "Page",
				templateType: "default",
			},
			template: {
				type: "template",
				templateType: "BasicTemplate",
				heroSection: {
					component: "Section",
					name: "Hero Section",
					modules: [],
					sectionPosition: 1,
					editorID: 2,
					parentEditorID: 1,
					key: "heroSection",
				},
				editorID: 1,
				parentEditorID: 0,
			},
		},
		errors: [{}],
	},
	sites: {
		currentSitePages: [
			{
				editorID: 1,
			},
		],
		themeElements: null,
	},
	app: {
		lang: { locale: "es-ES", id: 0 },
	},
	dataPacks: {
		templates: [{ id: "default" }, { id: "BasicTemplate" }],
		activated: [],
	},
	menu: {
		savedMenus: null,
	},
	navigationActions: {
		// Aquí usamos un jest.fn() simple placeholder si es necesario,
		// o podemos omitirlo si el componente no lo llama directamente desde el state
		updateEditorContent: jest.fn(),
	},
};

const defaultProps = {
	field: {
		title: "Name",
		key: "parent",
		type: "TextField",
		mandatory: true,
		modifiable: true,
		autoComplete: "a",
		slugTo: "la",
	},
	schema: {
		title: "Header",
		component: "Header",
		type: "header",
		configTabs: [
			{
				title: "content",
				fields: [
					{
						title: "Name",
						key: "title",
						type: "TextField",
						mandatory: true,
						autoComplete: "a",
					},
				],
			},
		],
		schemaType: "module",
	},
	componentType: "page",
	isPage: true,
	isGlobal: true,
	selectedTab: "content",
	theme: "default-theme",
};

const templateProps = {
	field: {
		title: "Name",
		key: "template",
		type: "template",
		modifiable: true,
	},
	schema: {
		title: "Header",
		component: "Header",
		type: "header",
		config: [
			{
				title: "Template Options",
				key: "templateOptions",
				type: "TextField",
			},
		],
		configTabs: [
			{
				title: "content",
				fields: [
					{
						title: "Name",
						key: "title",
						type: "TextField",
						mandatory: true,
					},
				],
			},
		],
		schemaType: "template",
	},
	isPage: true,
	isGlobal: true,
	selectedTab: "config",
	theme: "default-theme",
	isForm: false,
};

const data = {
	data: [],
	status: 200,
	statusText: "Ok",
	headers: {},
	config: {},
};

mockedAxios.mockResolvedValue(data);

describe("PageConnectedField component rendering", () => {
	it("should render PageConnectedField", () => {
		const store = mockStore(initialStore);

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<PageConnectedField {...defaultProps} />
			</ThemeProvider>,
			{ store },
		);

		// It's loading Field -> FieldContainer with a TextField
		const textFieldContainer = screen.getByTestId("text-field-container");
		expect(textFieldContainer).toBeTruthy();
	});

	it("should render the TemplateManager", () => {
		const store = mockStore(initialStore);

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<PageConnectedField {...templateProps} />
			</ThemeProvider>,
			{ store },
		);

		const templateTitles = screen.getAllByText("Template Options");
		expect(templateTitles).toHaveLength(1); // Title and label
		const titleElement = templateTitles[0]; // First one should be the title
		expect(titleElement.tagName).toBe("P");
	});

	it("should call getPageBreadCrumb", () => {
		// Clonamos para no mutar el original en otros tests si corren en paralelo/secuencia
		const props = { ...defaultProps, field: { ...defaultProps.field, key: "parent" } };

		const localStoreState = {
			...initialStore,
			pageEditor: {
				...initialStore.pageEditor,
				selectedEditorID: 1,
				selectedContent: {
					type: "TextField",
					isHome: false,
					component: "Image",
				},
				editorContent: {
					isHome: false,
					editorContent: {
						headerConfig: {},
					},
				},
			},
		};

		const store = mockStore(localStoreState);
		const component = (
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<PageConnectedField {...props} />
			</ThemeProvider>
		);

		render(component, { store });

		// It's loading Field -> FieldContainer with a TextField
		const inputComponent = screen.getByTestId<HTMLInputElement>("input-component");
		expect(inputComponent).toBeTruthy();
		fireEvent.change(inputComponent, { target: { value: "value" } });

		expect(store.getActions()).toContainEqual({
			payload: { editorContent: localStoreState.pageEditor.editorContent },
			type: "pageEditor/SET_EDITOR_CONTENT",
		});
	});

	it("should call updateEditorContent if key is title and isPageTitle", () => {
		const props = { ...defaultProps, field: { ...defaultProps.field, key: "title" } };
		const localStoreState = {
			...initialStore,
			pageEditor: {
				...initialStore.pageEditor,
				selectedEditorID: 1,
				selectedContent: {
					type: "TextField",
					isHome: false,
					component: "Page",
				},
				editorContent: {
					isHome: false,
					editorContent: {
						headerConfig: {},
					},
				},
			},
		};

		const store = mockStore(localStoreState);
		const component = (
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<PageConnectedField {...props} />
			</ThemeProvider>
		);

		render(component, { store });

		const inputComponent = screen.getByTestId<HTMLInputElement>("input-component");
		expect(inputComponent).toBeTruthy();
		fireEvent.change(inputComponent, { target: { value: "value" } });
		expect(store.getActions()).toContainEqual({
			payload: { editorContent: localStoreState.pageEditor.editorContent },
			type: "pageEditor/SET_EDITOR_CONTENT",
		});
	});

	it("should call updateEditorContent if key is file and isComponentImage", () => {
		const props = { ...defaultProps, field: { ...defaultProps.field, key: "file" } };
		const localStoreState = {
			...initialStore,
			pageEditor: {
				...initialStore.pageEditor,
				selectedEditorID: 1,
				selectedContent: {
					type: "TextField",
					isHome: false,
					component: "Image",
				},
				editorContent: {
					isHome: false,
					editorContent: {
						headerConfig: {},
					},
				},
			},
		};

		const store = mockStore(localStoreState);
		const component = (
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<PageConnectedField {...props} />
			</ThemeProvider>
		);

		render(component, { store });

		// It's loading Field -> FieldContainer with a TextField
		const inputComponent = screen.getByTestId<HTMLInputElement>("input-component");
		expect(inputComponent).toBeTruthy();
		fireEvent.change(inputComponent, { target: { value: "value" } });
		expect(store.getActions()).toContainEqual({
			payload: { editorContent: localStoreState.pageEditor.editorContent },
			type: "pageEditor/SET_EDITOR_CONTENT",
		});
	});

	it("should call updateEditorContent if key is slugTo is present", () => {
		const props = {
			...defaultProps,
			field: {
				...defaultProps.field,
				key: "file",
				slugTo: "value",
			},
		};

		const localStoreState = {
			...initialStore,
			pageEditor: {
				...initialStore.pageEditor,
				selectedEditorID: 1,
				selectedContent: {
					type: "TextField",
					isHome: false,
					component: "Image",
				},
				editorContent: {
					isHome: false,
					editorContent: {
						headerConfig: {},
					},
				},
			},
		};

		const store = mockStore(localStoreState);
		const component = (
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<PageConnectedField {...props} />
			</ThemeProvider>
		);

		render(component, { store });

		// It's loading Field -> FieldContainer with a TextField
		const inputComponent = screen.getByTestId<HTMLInputElement>("input-component");
		expect(inputComponent).toBeTruthy();
		fireEvent.change(inputComponent, { target: { value: "value" } });
		expect(store.getActions()).toContainEqual({
			payload: { editorContent: localStoreState.pageEditor.editorContent },
			type: "pageEditor/SET_EDITOR_CONTENT",
		});
	});
});
