import type {
	BetterAuthClientPlugin,
	BetterAuthPlugin,
} from "@better-auth/core";
import { createAuthEndpoint } from "@better-auth/core/api";
import { atom, computed } from "nanostores";
import * as z from "zod";
import { PACKAGE_VERSION } from "../version";
import { useAuthQuery } from "./query";

const serverPlugin = {
	id: "test",
	version: PACKAGE_VERSION,
	endpoints: {
		test: createAuthEndpoint(
			"/test",
			{
				method: "GET",
				error: z.object({
					code: z.number(),
					message: z.string(),
					test: z.boolean(),
				}),
			},
			async (c) => {
				return {
					data: "test",
				};
			},
		),
		testVirtual: createAuthEndpoint(
			{
				method: "GET",
			},
			async (c) => {
				return {
					data: "test",
				};
			},
		),
		testServerScoped: createAuthEndpoint(
			"/test-server-scoped",
			{
				method: "GET",
				metadata: {
					scope: "server",
				},
			},
			async (c) => {
				return {
					data: "test",
				};
			},
		),
		testHTTPScoped: createAuthEndpoint(
			"/test-http-scoped",
			{
				method: "GET",
				metadata: {
					scope: "http",
				},
			},
			async (c) => {
				return {
					data: "test",
				};
			},
		),
		testNonAction: createAuthEndpoint(
			"/test-non-action",
			{
				method: "GET",
				metadata: {
					isAction: false,
				},
			},
			async (c) => {
				return {
					data: "test",
				};
			},
		),
		testSignOut2: createAuthEndpoint(
			"/test-2/sign-out",
			{
				method: "POST",
			},
			async (c) => {
				return null;
			},
		),
	},
	schema: {
		user: {
			fields: {
				testField: {
					type: "string",
					required: false,
				},
				testField2: {
					type: "number",
					required: false,
				},
				testField3: {
					type: "string",
					returned: false,
				},
				testField4: {
					type: "string",
					defaultValue: "test",
				},
			},
		},
	},
} satisfies BetterAuthPlugin;

export const testClientPlugin = () => {
	const $test = atom(false);
	let testValue = 0;
	const computedAtom = computed($test, () => {
		return testValue++;
	});
	return {
		id: "test" as const,
		version: PACKAGE_VERSION,
		getActions($fetch) {
			return {
				setTestAtom(value: boolean) {
					$test.set(value);
				},
				test: {
					signOut: async () => {},
				},
			};
		},
		getAtoms($fetch) {
			const $signal = atom(false);
			const queryAtom = useAuthQuery<any>($signal, "/test", $fetch, {
				method: "GET",
			});
			return {
				$test,
				$signal,
				computedAtom,
				queryAtom,
			};
		},
		$InferServerPlugin: {} as typeof serverPlugin,
		atomListeners: [
			{
				matcher: (path) => path === "/test",
				signal: "$test",
			},
			{
				matcher: (path) => path === "/test2/sign-out",
				signal: "$sessionSignal",
			},
		],
	} satisfies BetterAuthClientPlugin;
};
export const testClientPlugin2 = () => {
	const $test2 = atom(false);
	let testValue = 0;
	const anotherAtom = computed($test2, () => {
		return testValue++;
	});
	return {
		id: "test",
		version: PACKAGE_VERSION,
		getAtoms($fetch) {
			return {
				$test2,
				anotherAtom,
			};
		},
		atomListeners: [
			{
				matcher: (path) => path === "/test",
				signal: "$test",
			},
			{
				matcher: (path) => path === "/test2/sign-out",
				signal: "$sessionSignal",
			},
		],
	} satisfies BetterAuthClientPlugin;
};

/**
 * Test plugins for verifying deep merge of plugin actions.
 * When multiple plugins return the same top-level action key (e.g., `signIn`),
 * all methods should be merged together instead of the last one overwriting.
 */
export const testDeepMergePluginA = () => {
	return {
		id: "test-deep-merge-a",
		version: PACKAGE_VERSION,
		getActions() {
			return {
				signIn: {
					methodA: async () => ({ success: true, method: "A" }),
				},
			};
		},
	} satisfies BetterAuthClientPlugin;
};

export const testDeepMergePluginB = () => {
	return {
		id: "test-deep-merge-b",
		version: PACKAGE_VERSION,
		getActions() {
			return {
				signIn: {
					methodB: async () => ({ success: true, method: "B" }),
				},
			};
		},
	} satisfies BetterAuthClientPlugin;
};
