import { createFetch, createSchema } from "@better-fetch/fetch"
import { z } from "zod"
import {
	AnalyticsChatResponseSchema,
	AnalyticsMemoryResponseSchema,
	AnalyticsUsageResponseSchema,
	BulkDeleteMemoriesResponseSchema,
	BulkDeleteMemoriesSchema,
	ConnectionResponseSchema,
	CreateProjectSchema,
	DeleteProjectResponseSchema,
	DeleteProjectSchema,
	DocumentsWithMemoriesQuerySchema,
	DocumentsWithMemoriesResponseSchema,
	ListContainerTagsResponseSchema,
	ListMemoriesResponseSchema,
	ListProjectsResponseSchema,
	MemoryAddSchema,
	MemoryResponseSchema,
	MigrateMCPRequestSchema,
	MigrateMCPResponseSchema,
	ProjectSchema,
	SearchRequestSchema,
	SearchResponseSchema,
	type SearchResult,
	SettingsRequestSchema,
} from "../validation/api"

// Settings response schema - this is custom to console (not in shared validation)
const SettingsResponseSchema = z.object({
	message: z.string(),
	settings: z.object({
		excludeItems: z.array(z.string().min(1).max(20)).optional(),
		filterPrompt: z.string().min(1).max(750).optional(),
		includeItems: z.array(z.string().min(1).max(20)).optional(),
		shouldLLMFilter: z.boolean().optional(),
	}),
})

// Analytics request schema - custom to console
const AnalyticsRequestSchema = z.object({
	from: z.string().datetime().optional(),
	limit: z.number().int().min(1).max(100).default(20),
	page: z.number().int().min(1).default(1),
	period: z.enum(["24h", "7d", "30d", "all"]).optional(),
	to: z.string().datetime().optional(),
})

// Waitlist response schema
const WaitlistStatusResponseSchema = z.object({
	inWaitlist: z.boolean(),
	accessGranted: z.boolean(),
	createdAt: z.string().datetime(),
})

export const apiSchema = createSchema({
	"@get/analytics/chat": {
		output: AnalyticsChatResponseSchema,
		query: AnalyticsRequestSchema,
	},
	"@get/analytics/memory": {
		output: AnalyticsMemoryResponseSchema,
		query: AnalyticsRequestSchema,
	},

	// Analytics operations
	"@get/analytics/usage": {
		output: AnalyticsUsageResponseSchema,
		query: AnalyticsRequestSchema,
	},

	// Connection operations - Add missing endpoints
	"@post/connections/:provider": {
		input: z.object({
			containerTags: z.array(z.string()).optional(),
			documentLimit: z.number().int().min(1).max(10000).optional(),
			metadata: z
				.record(z.union([z.string(), z.number(), z.boolean()]))
				.optional()
				.nullable(),
			redirectUrl: z.string().optional(),
		}),
		output: z.object({
			authLink: z.string(),
			expiresIn: z.string(),
			id: z.string(),
			redirectsTo: z.string().optional(),
		}),
		params: z.object({
			provider: z.enum(["google-drive", "notion", "onedrive"]),
		}),
	},

	"@post/connections/list": {
		input: z.object({
			containerTags: z.array(z.string()).optional(),
		}),
		output: z.array(ConnectionResponseSchema),
	},

	"@get/connections": {
		output: z.array(ConnectionResponseSchema),
		query: z
			.object({
				endUserId: z.string().optional(),
			})
			.optional(),
	},

	// Connection operations
	"@get/connections/:connectionId": {
		output: ConnectionResponseSchema,
		params: z.object({ connectionId: z.string() }),
	},

	"@delete/connections/:connectionId": {
		output: z.object({
			id: z.string(),
			provider: z.string(),
		}),
		params: z.object({ connectionId: z.string() }),
		query: z.object({
			deleteDocuments: z.boolean().optional(),
		}),
	},

	// Settings operations
	"@get/settings": {
		output: z.object({ settings: z.object({}).passthrough() }),
	},
	"@patch/settings": {
		input: SettingsRequestSchema,
		output: SettingsResponseSchema,
	},
	// Memory operations
	"@post/documents": {
		input: MemoryAddSchema,
		output: MemoryResponseSchema,
	},
	"@post/documents/list": {
		body: z
			.object({
				limit: z.number().optional(),
				page: z.number().optional(),
				status: z.string().optional(),
				containerTags: z.array(z.string()).optional(),
			})
			.optional(),
		output: ListMemoriesResponseSchema,
	},
	"@post/documents/documents": {
		input: DocumentsWithMemoriesQuerySchema,
		output: DocumentsWithMemoriesResponseSchema,
	},
	"@post/documents/documents/by-ids": {
		input: z.object({
			ids: z.array(z.string()),
			by: z.enum(["id", "customId"]).optional(),
			containerTags: z.array(z.string()).optional(),
		}),
		output: DocumentsWithMemoriesResponseSchema,
	},
	"@post/documents/migrate-mcp": {
		input: MigrateMCPRequestSchema,
		output: MigrateMCPResponseSchema,
	},

	"@get/documents/:id": {
		output: z.any(),
	},

	// Delete a memory
	"@delete/documents/:id": {
		output: z.any(), // 204 No-Content
		params: z.object({ id: z.string() }),
	},

	// Bulk delete memories
	"@delete/documents/bulk": {
		body: BulkDeleteMemoriesSchema,
		output: BulkDeleteMemoriesResponseSchema,
	},

	// Search operations
	"@post/search": {
		input: SearchRequestSchema,
		output: SearchResponseSchema,
	},

	// Project operations
	"@get/projects": {
		output: ListProjectsResponseSchema,
	},
	"@get/container-tags/list": {
		output: ListContainerTagsResponseSchema,
	},
	"@post/projects": {
		input: CreateProjectSchema,
		output: ProjectSchema,
	},
	"@delete/projects/:projectId": {
		input: DeleteProjectSchema,
		output: DeleteProjectResponseSchema,
		params: z.object({
			projectId: z.string(),
		}),
	},

	// MCP operations
	"@get/mcp/has-login": {
		output: z.object({ previousLogin: z.boolean() }),
	},

	// Waitlist operations
	"@get/waitlist/status": {
		output: WaitlistStatusResponseSchema,
	},

	"@post/emails/welcome/pro": {
		input: z.object({
			email: z.string(),
			firstName: z.string(),
		}),
		output: z.object({
			message: z.string(),
		}),
	},
})

export const $fetch = createFetch({
	baseURL: `${process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"}/v3`,
	credentials: "include",
	retry: {
		attempts: 3,
		delay: 100,
		type: "linear",
	},
	schema: apiSchema,
})

// Re-export types that might be used elsewhere
export type { SearchResult }
