import { AkReqResponse, AkReqUploadOptions, AkReq } from '@/uni_modules/ak-req/index.uts'
import type { AkReqOptions } from '@/uni_modules/ak-req/index.uts'
import { toUniError } from '@/utils/utils.uts'

export type AkSupaSignInResult = {
	access_token : string;
	refresh_token : string;
	expires_at : number;
	user : UTSJSONObject | null;
	token_type ?: string;
	expires_in ?: number;
	raw : UTSJSONObject;
}

// Count 选项枚举
export type CountOption = 'exact' | 'planned' | 'estimated';

// 定义查询选项类型，兼容 UTS
export type AkSupaSelectOptions = {
	limit ?: number;
	order ?: string;
	getcount ?: string;  // 保持向后兼容
	count ?: CountOption; // 新增：更清晰的 count 选项
	head ?: boolean;     // 新增：head 模式，只返回元数据
	columns ?: string;
	single ?: boolean; // 新增，支持 single-object
	rangeFrom ?: number; // 新增：range 分页起始位置
	rangeTo ?: number;   // 新增：range 分页结束位置
};

// 新增：order方法参数类型
export type OrderOptions = {
	ascending ?: boolean;
};

// 新增类型定义，便于 getSession 返回类型复用
export type AkSupaSessionInfo = {
	session : AkSupaSignInResult | null;
	user : UTSJSONObject | null;
};

// 链式请求构建器
// 强类型条件定义
type AkSupaCondition = {
	field : string; // 已经 encodeURIComponent 过
	op : string;
	value : any;
	logic : string; // 'and' | 'or'
};

export class AkSupaQueryBuilder {
	private _supa : AkSupa;
	private _table : string;
	private _filter : UTSJSONObject | null = null;
	private _options : AkSupaSelectOptions = {};
	private _values : UTSJSONObject | Array<UTSJSONObject> | null = null;
	private _single : boolean = false;
	private _conditions : Array<AkSupaCondition> = [];
	private _nextLogic : string = 'and';
	// 新增：记录当前操作类型
	private _action : 'select' | 'insert' | 'update' | 'delete' | 'rpc' | null = null;
	private _orString : string | null = null; // 新增：支持 or 字符串
	private _rpcFunction : string | null = null;
	private _rpcParams : UTSJSONObject | null = null;
	private _page : number = 1; // 新增：当前页码

	constructor(supa : AkSupa, table : string) {
		this._supa = supa;
		this._table = table;
	}

	// 链式条件方法
	eq(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'eq', value); }
	neq(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'neq', value); }
	gt(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'gt', value); }
	gte(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'gte', value); }
	lt(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'lt', value); }
	lte(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'lte', value); }
	like(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'like', value); }
	ilike(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'ilike', value); }
	in(field : string, value : any[]) : AkSupaQueryBuilder { return this._addCond(field, 'in', value); }
	is(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'is', value); }
	contains(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'cs', value); }
	containedBy(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'cd', value); }
	not(field : string, value : any) : AkSupaQueryBuilder { return this._addCond(field, 'not', value); }

	and() : AkSupaQueryBuilder { this._nextLogic = 'and'; return this; }
	or(str ?: string) : AkSupaQueryBuilder {
		if (typeof str == 'string') {
			this._orString = str;
		} else {
			this._nextLogic = 'or';
		}
		return this;
	}

	private _addCond(afield : string, op : string, value : any) : AkSupaQueryBuilder {
		//console.log('add cond:', op, afield, value)
		const field = encodeURIComponent(afield)!!
		this._conditions.push({ field, op, value, logic: this._nextLogic });
		//console.log(this._conditions)
		this._nextLogic = 'and';
		return this;
	}

	// 支持原有 where 方式
	where(filter : UTSJSONObject) : AkSupaQueryBuilder {
		this._filter = filter;
		return this;
	}

	page(page : number) : AkSupaQueryBuilder {
		this._page = page;
		// 如果已设置 limit，则自动设置 range
		let limit = 0;
		if (typeof this._options.limit == 'number') {
			limit = this._options.limit ?? 0;
		}
		if (limit > 0) {
			const from = (page - 1) * limit;
			const to = from + limit - 1;
			this.range(from, to);
		}
		return this;
	}
	limit(limit : number) : AkSupaQueryBuilder {
		this._options.limit = limit;
		// 总是为 limit 设置对应的 range，确保限制生效
		const from = (this._page - 1) * limit;
		const to = from + limit - 1;
		this.range(from, to);
		return this;
	}

	order(order : string, options ?: OrderOptions) : AkSupaQueryBuilder {
		if (options != null && options.ascending == false) {
			this._options.order = order + '.desc';
		} else {
			this._options.order = order + '.asc';
		}
		return this;
	}
	columns(columns : string) : AkSupaQueryBuilder {
		this._options.columns = columns;
		return this;
	}

	// 新增：专门的 count 方法
	count(option : CountOption = 'exact') : AkSupaQueryBuilder {
		this._options.count = option;
		this._options.head = true;  // count 操作默认使用 head 模式
		return this;
	}

	// 新增：便捷的 count 方法
	countExact() : AkSupaQueryBuilder {
		return this.count('exact');
	}

	countEstimated() : AkSupaQueryBuilder {
		return this.count('estimated');
	}

	countPlanned() : AkSupaQueryBuilder {
		return this.count('planned');
	}

	// 新增：head 模式方法
	head(enable : boolean = true) : AkSupaQueryBuilder {
		this._options.head = enable;
		return this;
	}

	values(values : UTSJSONObject) : AkSupaQueryBuilder {
		this._values = values;
		return this;
	}
	single() : AkSupaQueryBuilder {
		this._single = true;
		return this;
	}
	range(from : number, to : number) : AkSupaQueryBuilder {
		this._options.rangeFrom = from;
		this._options.rangeTo = to;
		//console.log('设置 range:', from, 'to', to);
		return this;
	}
	// 将 _conditions 强类型直接转换为 Supabase/PostgREST 查询字符串（不再用 UTSJSONObject 做中转）
	private _buildFilter() : string | null {
		if (this._conditions.length == 0 && (this._orString==null || this._orString == "")) {
			// 兼容 where(filter) 方式
			if (this._filter == null) return null;
			// 兼容旧的 UTSJSONObject filter
			return buildSupabaseFilterQuery(this._filter);
		}

		// 先分组 and/or，全部用 AkSupaCondition 强类型
		const ands: AkSupaCondition[] = [];
		const ors: AkSupaCondition[] = [];
		for (const c of this._conditions) {
			if (c.logic == "or") {
				ors.push(c);
			} else {
				ands.push(c);
			}
		}

		const params: string[] = [];
		// 处理 and 条件
		for (const cond of ands) {
			const k = cond.field;
			const op = cond.op;
			const val = cond.value;
			if ((op == 'in' || op == 'not.in') && Array.isArray(val)) {
				params.push(`${k}=${op}.(${val.map(x => typeof x == 'object' ? encodeURIComponent(JSON.stringify(x)) : encodeURIComponent(x.toString())).join(',')})`);
			} else if (op == 'is' && (val == null || val == 'null')) {
				params.push(`${k}=is.null`);
			} else {
				const opvalstr: string = (typeof val == 'object') ? JSON.stringify(val) : (val as string);
				params.push(`${k}=${op}.${encodeURIComponent(opvalstr)}`);
			}
		}
		// 处理 or 条件
		if (ors.length > 0) {
			const orStr = ors.map(o => {
				const k = o.field;
				const op = o.op;
				const val = o.value;
				if (op == "in" && Array.isArray(val)) {
					return `${k}.in.(${val.map(x => encodeURIComponent(x as string)).join(",")})`;
				}
				if (op == "is" && (val == null)) {
					return `${k}.is.null`;
				}
				return `${k}.${op}.${encodeURIComponent(val as string)}`;
			}).join(",");
			params.push(`or=(${orStr})`);
		}
		if (this._orString!=null && this._orString !== "") {
			params.push(`or=(${encodeURIComponent(this._orString!!)})`);
		}
		return params.length > 0 ? params.join('&') : null;
	}

	select(columns ?: string, opt ?: UTSJSONObject) : AkSupaQueryBuilder {
		this._action = 'select';
		if (columns != null) {
			this._options.columns = columns;
		}
		if (opt != null) {
			// 合并 opt 到 this._options
			Object.assign(this._options, opt);
		}
		return this;
	}
	insert(values : UTSJSONObject | Array<UTSJSONObject>) : AkSupaQueryBuilder {
		this._action = 'insert';
		// 检查是否为空
		if (Array.isArray(values)) {
			if (values.length == 0) throw toUniError('No values set for insert', 'Insert操作缺少数据');
		} else {
			if (UTSJSONObject.keys(values).length == 0) throw toUniError('No values set for insert', 'Insert操作缺少数据');
		}
		this._values = values;
		return this;
	}
	update(values : UTSJSONObject) : AkSupaQueryBuilder {
		this._action = 'update';
		//console.log('ak update', this._action)
		if (UTSJSONObject.keys(values).length == 0) throw toUniError('No values set for update', '更新操作缺少数据');
		this._values = values;
		//console.log('ak update', values)
		return this;
	}
	delete() : AkSupaQueryBuilder {
		this._action = 'delete';
		//console.log('delete action now')
		const filter = this._buildFilter();
		//console.log(filter)
		if (filter == null) throw toUniError('No filter set for delete', '删除操作缺少筛选条件');
		//console.log('delete action')
		return this;
	}

	rpc(functionName : string, params ?: UTSJSONObject) : AkSupaQueryBuilder {
		this._action = 'rpc';
		this._rpcFunction = functionName;
		this._rpcParams = params;
		return this;
	}
	// 链式请求最终执行方法 - 返回 UTSJSONObject
	async execute() : Promise<AkReqResponse<any>> {
		//console.log('execute')
		const filter = this._buildFilter();
		//console.log('execute', filter)
		let res : any;
		switch (this._action) {
			case 'select': {
				// 传递 single 状态到 options
				if (this._single) {
					this._options.single = true;
					// 如果是 single 请求，自动设置 limit 为 1
					if (this._options.limit == null) {
						this._options.limit = 1;
					}
					//console.log(this._options)
				}				// 保证分页统计
				if (this._options.limit != null) {
					if (this._options.getcount == null && this._options.count == null) {
						this._options.count = 'exact';  // 优先使用新的 count 选项
					}
				}
				res = await this._supa.select(this._table, filter, this._options);
				// 解析 content-range header
				let total = 0;
				let hasmore = false;
				const page = this._page;
				let resdata = res.data
				let limit = 0;
				if (typeof this._options.limit == 'number') {
					limit = this._options.limit ?? 0;
				} else if (Array.isArray(resdata)) {
					limit = resdata.length;
				}
				let contentRange : string | null = null;
				if (res.headers != null) {
					let theheader = res.headers as UTSJSONObject
					if (typeof theheader.get == 'function') {

						contentRange = theheader.get('content-range') as string | null;
					} else if (typeof theheader['content-range'] == 'string') {
						contentRange = theheader['content-range'] as string;
					}
				}
				if (contentRange != null) {
					const match = /\/(\d+)$/.exec(contentRange);
					if (match != null) {
						total = parseInt(match[1] ?? "0");
						hasmore = (page * limit) < total;
					}
				}
				if (total == 0) {
					if (typeof res['count'] == 'number') {
						total = res['count'] as number ?? 0;
					} else if (Array.isArray(resdata)) {
						total = resdata.length;
					} else {
						total = 0;
					}
				}
				if (!hasmore) hasmore = (page * limit) < total;				// 如果是 head 模式，只返回 count 信息
				if (this._options.head == true) {
					return {
						data: null,  // head 模式不返回数据
						total,
						page,
						limit,
						hasmore: false,  // head 模式不需要分页信息
						origin: res,
						status: res.status,
						headers: res.headers,
						error: res.error
					} as AkReqResponse<any>;
				}

				return {
					data: res.data,
					total,
					page,
					limit,
					hasmore,
					origin: res,
					status: res.status,
					headers: res.headers,
					error: res.error
				} as AkReqResponse<any>;
			}
			case 'insert': {
				const insertValues = this._values;
				if (insertValues == null) throw toUniError('No values set for insert', '插入操作缺少数据');
				res = await this._supa.insert(this._table, insertValues);
				break;
			} case 'update': {
				const updateValues = this._values;
				if (updateValues == null) throw toUniError('No values set for update', '更新操作缺少数据');
				if (filter == null) throw toUniError('No filter set for update', '更新操作缺少筛选条件');
				// Update操作只支持单个对象，不支持数组
				if (Array.isArray(updateValues)) throw toUniError('Update does not support array values', '更新操作不支持数组数据');
				res = await this._supa.update(this._table, filter, updateValues as UTSJSONObject);
				break;
			}
			case 'delete': {
				if (filter == null) throw toUniError('No filter set for delete', '删除操作缺少筛选条件');
				res = await this._supa.delete(this._table, filter);
				break;
			}
			case 'rpc': {
				if (this._rpcFunction == null) throw toUniError('No RPC function specified', 'RPC调用缺少函数名');
				res = await this._supa.rpc(this._rpcFunction as string, this._rpcParams);
				break;
			}
			default: {
				res = await this._supa.select(this._table, filter, this._options);
			}
		}
		// 保证 data 字段存在（不能赋null，赋空对象或空字符串）
		if (res["data"] == null) res["data"] = {};
		return res;
	}	// 新增：支持类型转换的执行方法
	async executeAs<T = any>() : Promise<AkReqResponse<T | Array<T>>> {
		const result = await this.execute();

		// 如果原始 data 是 null，直接返回 null
		if (result.data == null) {
			const aaa = {
				status: result.status,
				data: null,
				headers: result.headers,
				error: result.error,
				total: result.total,
				page: result.page,
				limit: result.limit,
				hasmore: result.hasmore,
				origin: result.origin
			}
			return aaa;
		}

		// 尝试类型转换
		let convertedData : T | Array<T> | null = null;

		try {
			if (Array.isArray(result.data)) {
				// 处理数组数据
				const dataArray = result.data;
				const convertedArray : Array<T> = [];
				//console.log(convertedArray)
				for (let i = 0; i < dataArray.length; i++) {
					const item = dataArray[i];
					if (item instanceof UTSJSONObject) {
						// #ifdef APP-ANDROID
						// //console.log(item)
						const parsed = item.parse<T>();
						// //console.log('ak parsed')
						// #endif
						// #ifndef APP-ANDROID
						const parsed = item as T;
						// #endif
						if (parsed != null) {
							convertedArray.push(parsed);
						} else {
							console.warn('转换失败，使用原始对象：', item);
							convertedArray.push(item as T);
						}
					} else {
						// 将普通对象转换为 UTSJSONObject 后再 parse
						const jsonObj = new UTSJSONObject(item);
						// #ifdef APP-ANDROID
						const parsed = jsonObj.parse<T>();
						// #endif
						// #ifndef APP-ANDROID
						const parsed = jsonObj as T;
						// #endif
						if (parsed != null) {
							convertedArray.push(parsed);
						}
						else {
							console.warn('转换失败，使用原始对象：', item);
							convertedArray.push(item as T);
						}
					}
				}
				convertedData = convertedArray;

			} else {
				// 处理单个对象
				const convertedArray : Array<T> = [];
				if (result.data instanceof UTSJSONObject) {
					const parsed = result.data.parse<T>();

					if (parsed != null) {
						convertedArray.push(parsed);
					}
					else {
						//console.log('转换失败：', result.data)
					}
				} else {
					const jsonObj = new UTSJSONObject(result.data);
					const parsed = jsonObj.parse<T>();
					if (parsed != null) {
						convertedArray.push(parsed);
					}
					else {
						//console.log('转换失败：', result.data)
					}
				}
				convertedData = convertedArray;
			}
		} catch (e) {
			console.warn('数据类型转换失败，使用原始数据:', e);
			console.log(result.data)
			// 转换失败时，使用原始数据
			convertedData = result.data as T | Array<T>;
		}
		result.data = convertedData
		const aaa = result as AkReqResponse<T | Array<T>
		// const aaa = {
		// 	status: result.status,
		// 	data: convertedData,
		// 	headers: result.headers,
		// 	error: result.error,
		// 	total: result.total,
		// 	page: result.page,
		// 	limit: result.limit,
		// 	hasmore: result.hasmore,
		// 	origin: result.origin
		// } 
		return aaa;

	}
}

// 新增：链式 Storage 上传
export class AkSupaStorageUploadBuilder {
	private _supa : AkSupa;
	private _bucket : string = '';
	private _path : string = '';
   private _file : string = '';
	private _options : UTSJSONObject = {};

	constructor(supa : AkSupa, bucket : string) {
		this._supa = supa;
		this._bucket = bucket;
	}

	path(path : string) : AkSupaStorageUploadBuilder {
		this._path = path;
		return this;
	}

   file(file : string) : AkSupaStorageUploadBuilder {
		this._file = file;
		return this;
	}

	options(options : UTSJSONObject) : AkSupaStorageUploadBuilder {
		this._options = options;
		return this;
	}
	async upload() : Promise<AkReqResponse<any>> {
   if (this._bucket == '' || this._path == '' || this._file == '') {
			throw toUniError('bucket, path, file are required', '上传文件缺少必要参数');
		}
		const url = `${this._supa.baseUrl}/storage/v1/object/${this._bucket}/${this._path}`;
		const apikey = this._supa.apikey;
		// 适配 uni.uploadFile
		const uploadOptions : AkReqUploadOptions = {
			url,
			filePath: this._file, // 这里假设 file 是本地路径
			name: 'file', // 默认字段名
			headers: {},
			apikey,
			formData: this._options
		};
		return await AkReq.upload(uploadOptions);
	}
}

// 新增：明确的 StorageBucket 类，支持链式 upload
class AkSupaStorageBucket {
	private supa : AkSupa;
	private bucket : string;
	constructor(supa : AkSupa, bucket : string) {
		this.supa = supa;
		this.bucket = bucket;
	}
	async upload(path : string, filePath : string, options ?: UTSJSONObject) : Promise<AkReqResponse<any>> {
		const url = `${this.supa.baseUrl}/storage/v1/object/${this.bucket}/${path}`;
		let headers : UTSJSONObject = { apikey: this.supa.apikey };
		const formData : UTSJSONObject = {};
		if (options != null && typeof options == 'object') {
			if (typeof options.get == 'function' && options.get('x-upsert') != null) {
				headers['x-upsert'] = options.get('x-upsert');
			}
			const keys = UTSJSONObject.keys(options);
			for (let i = 0; i < keys.length; i++) {
				const k = keys[i];
				if (k != 'x-upsert') formData[k] = options.get(k);
			}
		}
		const token = AkReq.getToken();
		if (token != null && !(token == '')) {
			headers['Authorization'] = `Bearer ${token}`;
		}
		return await AkReq.upload({
			url,
			filePath,
			name: 'file',
			apikey: this.supa.apikey,
			formData,
			headers
		});
	}
}

export class AkSupaStorageApi {
	private _supa : AkSupa;
	constructor(supa : AkSupa) {
		this._supa = supa;
	}
	from(bucket : string) : AkSupaStorageBucket {
		return new AkSupaStorageBucket(this._supa, bucket);
	}
}

export class AkSupa {
	baseUrl : string;
	apikey : string;
	session : AkSupaSignInResult | null = null;
	user : UTSJSONObject | null = null;
	storage : AkSupaStorageApi;

	constructor(baseUrl : string, apikey : string) {
		this.baseUrl = baseUrl;
		this.apikey = apikey;
		this.storage = new AkSupaStorageApi(this);
	}

	async resetPassword(email : string) : Promise<boolean> {
		const res = await AkReq.request({
			url: this.baseUrl + '/auth/v1/recover',
			method: 'POST',
			headers: {
				apikey: this.apikey,
				'Content-Type': 'application/json'
			} as UTSJSONObject,
			data: { email } as UTSJSONObject,
			contentType: 'application/json'
		}, false);

		// Supabase returns 200 when the reset email is sent successfully
		return res.status == 200;
	}
	async signOut() {
		this.session = null
		this.user = null
	}
	async signIn(email : string, password : string) : Promise<AkSupaSignInResult> {
		// 提前检查 apikey 配置是否为占位符，避免发送无效请求导致 401
		if (this.apikey == null || this.apikey.trim() === '' || this.apikey === 'your-anon-key') {
			throw new Error('Supabase 配置错误：请在 ak/config.uts 中设置 SUPA_KEY（当前为占位符）');
		}
		const res = await AkReq.request({
			url: this.baseUrl + '/auth/v1/token?grant_type=password',
			method: 'POST',
			headers: {
				apikey: this.apikey,
				'Content-Type': 'application/json'
			} as UTSJSONObject,
			data: { email, password } as UTSJSONObject,
			contentType: 'application/json'
		}, false);
		// 如果响应不是 2xx（例如 401），提取后端错误信息并抛出，便于上层显示具体原因
		const status = res.status ?? 0;
		if (!(status >= 200 && status < 400)) {
			let msg = 'user.login.login_failed';
			try {
				if (res.data != null) {
					const obj = new UTSJSONObject(res.data);
					msg = obj.getString('message') ?? obj.getString('error') ?? obj.getString('msg') ?? obj.getString('description') ?? obj.getString('error_description') ?? msg;
				}
			} catch (e) {
				// ignore
			}
			throw new Error(msg);
		}
		// 解析成功的返回体
		let data: UTSJSONObject;
		try {
			data = new UTSJSONObject(res.data);
		} catch (e) {
			data = new UTSJSONObject({});
		}
		const access_token = data.getString('access_token') ?? '';
		const refresh_token = data.getString('refresh_token') ?? '';
		const expires_at = data.getNumber('expires_at') ?? 0;
		const user = data.getJSON('user');
		AkReq.setToken(access_token, refresh_token, expires_at);
		const session : AkSupaSignInResult = {
			access_token: access_token,
			refresh_token: refresh_token,
			expires_at: expires_at,
			user: user,
			token_type: data.getString('token_type') ?? '',
			expires_in: data.getNumber('expires_in') ?? 0,
			raw: data
		};
		this.session = session;
		this.user = user;
		return session;
	}

	/**
	 * 获取当前 session 和 user
	 */
	getSession() : AkSupaSessionInfo {
		return {
			session: this.session,
			user: this.user
		};
	}

	async signUp(email : string, password : string) : Promise<UTSJSONObject> {
		const res = await AkReq.request({
			url: this.baseUrl + '/auth/v1/signup',
			method: 'POST',
			headers: {
				apikey: this.apikey,
				'Content-Type': 'application/json'
			} as UTSJSONObject,
			data: { email, password } as UTSJSONObject,
			contentType: 'application/json'
		}, false);
		return res.data as UTSJSONObject;
	}


	/**
	 * 查询表数据（GET方式，支持多条件、limit等，filter自动转为supabase风格query）
	 * filter 支持：
	 *   { usr_id: { lt: 800 }, name: { ilike: '%foo%' }, status: 'active', age: { gte: 18, lte: 30 } }
	 *   操作符支持 eq, neq, lt, lte, gt, gte, like, ilike, in, is, not, contains, containedBy, range, fts, plfts, phfts, wfts
	 */
async select(table : string, filter ?: string | null, options ?: AkSupaSelectOptions) : Promise<AkReqResponse<any>> {
	let url = this.baseUrl + '/rest/v1/' + table;
	let headers = {
		apikey: this.apikey,
		'Content-Type': 'application/json',
		Authorization: `Bearer ${AkReq.getToken() ?? ''}`
	} as UTSJSONObject;
	let params : string[] = [];
	if (options != null) {
		if (options.columns != null && !(options.columns == "")) params.push('select=' + encodeURIComponent(options.columns ?? ""));
		if (options.limit != null) {
			params.push('limit=' + options.limit);
			//console.log('设置 limit 参数:', options.limit);
		}
		if (options.order != null && !(options.order == "")) params.push('order=' + encodeURIComponent(options.order ?? ""));
		if (options.rangeFrom != null && options.rangeTo != null) {
			headers['Range'] = `${options.rangeFrom}-${options.rangeTo}`;
			headers['Range-Unit'] = 'items';
			//console.log('设置 Range 头部:', `${options.rangeFrom}-${options.rangeTo}`);
		}

		// 向后兼容：支持旧的 getcount 参数
		let countOption = options.count ?? options.getcount;
		if (countOption != null) {
			headers['Prefer'] = `count=${countOption}`;
		}
		// 新增：head 模式支持
		if (options.head == true) {
			//console.log('使用 head 模式，只返回元数据');
			// HEAD 请求用于只获取 count，不返回数据
			if (headers['Prefer'] != null) {
				headers['Prefer'] = (headers['Prefer'] as string) + ',return=minimal';
			} else {
				headers['Prefer'] = 'return=minimal';
			}
		}

		if (options.single == true) {
			//console.log('使用 single() 模式');
			if (headers['Prefer'] != null) {
				headers['Prefer'] = (headers['Prefer'] as string) + ',return=representation,single-object';
			} else {
				headers['Prefer'] = 'return=representation,single-object';
			}
		}
	} else {
		params.push('select=*');
	}
	// 直接用 string filter
	if (filter!=null && filter !== "") {
		params.push(filter!!);
	}
	if (params.length > 0) {
		url += '?' + params.join('&');
	}

	//console.log(url)

	// 确定HTTP方法：如果是head模式，使用HEAD方法
	let httpMethod: 'GET' | 'HEAD' = 'GET';
	if (options != null && options.head == true) {
		httpMethod = 'HEAD';
		//console.log('使用 HEAD 方法进行 count 查询');
	}

	let reqOptions : AkReqOptions = {
		url,
		method: httpMethod,
		headers
	};
	return await this.requestWithAutoRefresh(reqOptions);
}

async select_uts(table : string, filter ?: UTSJSONObject | null, options ?: AkSupaSelectOptions) : Promise<AkReqResponse<any>> {
	const filter_str = buildSupabaseFilterQuery(filter)
	return this.select(table,filter_str,options)
}
	/**
	 * 插入表数据
	 * @param table 表名
	 * @param row 插入对象
	 * @returns 插入结果
	 */
	async insert(table : string, row : UTSJSONObject | Array<UTSJSONObject>) : Promise<AkReqResponse<any>> {
		const url = this.baseUrl + '/rest/v1/' + table;
		const headers = {
			apikey: this.apikey,
			'Content-Type': 'application/json',
			Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
			Prefer: 'return=representation'
		} as UTSJSONObject;

		// 如果是数组，直接传递；如果是单个对象，也直接传递
		// Supabase REST API 原生支持两种格式
		let reqOptions : AkReqOptions = {
			url,
			method: 'POST',
			headers,
			data: row, // 可以是单个对象或数组
			contentType: 'application/json'
		};
		return await this.requestWithAutoRefresh(reqOptions);
	}

	/**
	 * 更新表数据
	 * @param table 表名
	 * @param filter 过滤条件对象
	 * @param values 更新内容对象
	 * @returns 更新结果
	 */
async update(table : string, filter : string | null, values : UTSJSONObject) : Promise<AkReqResponse<any>> {
	let url = this.baseUrl + '/rest/v1/' + table;
	if (filter!=null && filter !== "") {
		url += '?' + filter;
	}
	const headers = {
		apikey: this.apikey,
		'Content-Type': 'application/json',
		Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
		Prefer: 'return=representation'
	} as UTSJSONObject;
	let reqOptions : AkReqOptions = {
		url,
		method: 'PATCH',
		headers,
		data: values,
		contentType: 'application/json'
	};
	return await this.requestWithAutoRefresh(reqOptions);
}

	/**
	 * 删除表数据
	 * @param table 表名
	 * @param filter 过滤条件对象
	 * @returns 删除结果
	 */
async delete(table : string, filter : string | null) : Promise<AkReqResponse<any>> {
	let url = this.baseUrl + '/rest/v1/' + table;
	if (filter!=null && filter !== "") {
		url += '?' + filter;
	}
	const headers = {
		apikey: this.apikey,
		'Content-Type': 'application/json',
		Authorization: `Bearer ${AkReq.getToken() ?? ''}`,
		Prefer: 'return=representation'
	} as UTSJSONObject;
	let reqOptions : AkReqOptions = {
		url,
		method: 'DELETE',
		headers,
		contentType: 'application/json'
	};
	return await this.requestWithAutoRefresh(reqOptions);
}

	/**
	 * 调用 Supabase/PostgREST RPC (function)
	 * @param functionName 函数名
	 * @param params 参数对象
	 * @returns AkReqResponse<any>
	 */
	async rpc(functionName : string, params ?: UTSJSONObject) : Promise<AkReqResponse<any>> {
		const url = `${this.baseUrl}/rest/v1/rpc/${functionName}`;
		const headers = {
			apikey: this.apikey,
			'Content-Type': 'application/json',
			Authorization: `Bearer ${AkReq.getToken() ?? ''}`
		} as UTSJSONObject;
		let reqOptions : AkReqOptions = {
			url,
			method: 'POST',
			headers,
			data: params ?? {},
			contentType: 'application/json'
		};
		return await this.requestWithAutoRefresh(reqOptions);
	}
	/**
	 * 兼容 supabase-js 风格
	 * @param tableName 表名
	 */
	from(tableName : string) : AkSupaQueryBuilder {
		return new AkSupaQueryBuilder(this, tableName);
	}
	// AkSupa类内新增：自动刷新session
	async refreshSession() : Promise<boolean> {
		if (this.session == null || this.session?.refresh_token == null) return false;
		try {
			const res = await AkReq.request({
				url: this.baseUrl + '/auth/v1/token?grant_type=refresh_token',
				method: 'POST',
				headers: {
					apikey: this.apikey,
					'Content-Type': 'application/json'
				} as UTSJSONObject,
				data: { refresh_token: this.session?.refresh_token } as UTSJSONObject,
				contentType: 'application/json'
			}, false);
			if (res.status == 200 && (res.data != null)) {
				const data = res.data as UTSJSONObject;
				const access_token = data.getString('access_token') ?? '';
				const refresh_token = data.getString('refresh_token') ?? '';
				const expires_at = data.getNumber('expires_at') ?? 0;
				const user = data.getJSON('user');
				this.session = {
					access_token,
					refresh_token,
					expires_at,
					user,
					token_type: data.getString('token_type') ?? '',
					expires_in: data.getNumber('expires_in') ?? 0,
					raw: data
				};
				this.user = user;
				// 更新本地token
				AkReq.setToken(access_token, refresh_token, expires_at);
				return true;
			}
			return false;
		} catch (e) {
			return false;
		}
	}

	// AkSupa类内新增：自动刷新封装
	async requestWithAutoRefresh(reqOptions : AkReqOptions, isRetry = false) : Promise<AkReqResponse<any>> {
		let res = await AkReq.request(reqOptions, false);
		// JWT过期：Supabase风格
		const isJwtExpired = (res.status == 401); //res != null && res.data != null && typeof res.data == 'object'  && (res.data as UTSJSONObject)?.getString('code') == 'PGRST301';
		// 401未授权
		const isUnauthorized = (res.status == 401);
		if ((isJwtExpired || isUnauthorized) && !isRetry) {
			const ok = await this.refreshSession();
			if (ok) {
				let headers = reqOptions.headers
				if (headers == null) {
					headers = new UTSJSONObject()
				}
				if (typeof headers.set == 'function') {
					headers.set('Authorization', `Bearer ${AkReq.getToken() ?? ''}`)
					reqOptions.headers = headers
				}

				res = await AkReq.request(reqOptions, false);
			} else {
				uni.removeStorageSync('user_id');
				uni.removeStorageSync('token');

				uni.reLaunch({ url: '/pages/user/login' });
				throw toUniError('登录已过期，请重新登录', '用户认证失败');
			}
		}
		return res;
	}
}

// 工具函数：将 UTSJSONObject filter 转为 Supabase/PostgREST 查询字符串
function buildSupabaseFilterQuery(filter : UTSJSONObject | null) : string {
	//console.log(filter)
	if (filter == null) return "";
	// 类型保护：如果不是 UTSJSONObject，自动包裹
	if (typeof filter.get !== 'function') {
		try {
			filter = new UTSJSONObject(filter as any)
		} catch (e) {
			console.warn('filter 不是 UTSJSONObject，且无法转换', filter)
			return ''
		}
	}
	const params : string[] = [];
	const keys : string[] = UTSJSONObject.keys(filter);
	for (let i = 0; i < keys.length; i++) {
		const k = keys[i];
		const v = filter.get(k);
		if (k == 'or' && typeof v == 'string') {
			params.push(`or=(${v})`);
			continue;
		}
		if (v != null && typeof v == 'object' && typeof (v as UTSJSONObject).get == 'function') {
			const vObj = v as UTSJSONObject;
			const opKeys = UTSJSONObject.keys(vObj);
			for (let j = 0; j < opKeys.length; j++) {
				const op = opKeys[j];
				const opVal = vObj.get(op);
				if ((op == 'in' || op == 'not.in') && Array.isArray(opVal)) {
					params.push(`${k}=${op}.(${opVal.map(x => typeof x == 'object' ? encodeURIComponent(JSON.stringify(x)) : encodeURIComponent(x.toString())).join(',')})`);
				} else if (op == 'is' && (opVal == null || opVal == 'null')) {
					params.push(`${k}=is.null`);
				} else {
					const opvalstr : string = (typeof opVal == 'object') ? JSON.stringify(opVal) : (opVal as string);
					params.push(`${k}=${op}.${encodeURIComponent(opvalstr)}`);
				}
			}
		} else if (v != null && typeof v == 'object') {
			const vObj = v as UTSJSONObject;
			const opKeys = UTSJSONObject.keys(vObj);
			for (let j = 0; j < opKeys.length; j++) {
				const op = opKeys[j];
				const opVal = vObj.get(op);
				params.push(`${k}=${op}.${encodeURIComponent(!(opVal == null) ? (typeof opVal == 'object' ? JSON.stringify(opVal) : opVal.toString()) : '')}`);
			}
		} else {
			params.push(`${k}=eq.${encodeURIComponent(!(v == null) ? v.toString() : '')}`);
		}
	}
	return params.join('&');
}

/**
 * 创建 Supabase 客户端实例
 * @param url 项目 URL
 * @param key 项目匿名密钥 (Anon Key)
 */
export function createClient(url : string, key : string) : AkSupa {
	return new AkSupa(url, key);
}

export default AkSupa;