import {
	OpenServiceSessionStore,
	CloseServiceSessionStore,
	RevertServiceSessionStore,
	OpenProjectSessionStore,
	CloseProjectSessionStore,
	RevertProjectSessionStore,
	AddServiceTaskStore,
	RemoveServiceTaskStore,
	AddProjectTaskStore,
	RemoveProjectTaskStore,
	CreateServiceNoteStore,
	UpdateServiceNoteStore,
	RemoveServiceNoteStore,
	CreateProjectNoteStore,
	UpdateProjectNoteStore,
	RemoveProjectNoteStore,
	UpdateServicePhotoStore,
	RemoveServicePhotoStore,
	UpdateProjectPhotoStore,
	RemoveProjectPhotoStore,
	UpdateServiceVideoStore,
	RemoveServiceVideoStore,
	UpdateProjectVideoStore,
	RemoveProjectVideoStore
} from '$houdini';
import type {
	OpenServiceSession$input,
	OpenServiceSession$result,
	CloseServiceSession$input,
	CloseServiceSession$result,
	OpenProjectSession$input,
	OpenProjectSession$result,
	CloseProjectSession$input,
	CloseProjectSession$result,
	AddServiceTask$result,
	RemoveServiceTask$result,
	AddProjectTask$result,
	RemoveProjectTask$result,
	CreateServiceNote$result,
	UpdateServiceNote$result,
	CreateProjectNote$result,
	UpdateProjectNote$result,
	ServiceSessionNoteInput,
	ServiceSessionNoteUpdateInput,
	ProjectSessionNoteInput,
	ProjectSessionNoteUpdateInput,
	ServiceSessionImageUpdateInput,
	ProjectSessionImageUpdateInput,
	ServiceSessionVideoUpdateInput,
	ProjectSessionVideoUpdateInput,
	UpdateServicePhoto$result,
	UpdateProjectPhoto$result,
	UpdateServiceVideo$result,
	UpdateProjectVideo$result
} from '$houdini';

const API_BASE_URL = import.meta.env.VITE_API_URL || 'https://api.example.com';

// Upload response types
export interface UploadPhotoResponse {
	id: string;
	title: string;
	notes: string;
	contentType: string;
	width: number;
	height: number;
	image: string;
	thumbnail: string;
	createdAt: string;
	uploadedById: string | null;
	internal: boolean;
	serviceSessionId?: string;
	projectSessionId?: string;
}

export interface UploadVideoResponse {
	id: string;
	title: string;
	notes: string;
	contentType: string;
	width: number;
	height: number;
	durationSeconds: number;
	fileSizeBytes: number;
	video: string;
	thumbnail: string;
	createdAt: string;
	uploadedById: string | null;
	internal: boolean;
	serviceSessionId?: string;
	projectSessionId?: string;
}

// Service Session functions
export type OpenServiceSessionInput = OpenServiceSession$input['input'];
export type ServiceSession = OpenServiceSession$result['openServiceSession'];

export async function openServiceSession(input: OpenServiceSessionInput): Promise<ServiceSession> {
	const store = new OpenServiceSessionStore();
	const { data, errors } = await store.mutate({ input });

	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to open service session');
	}

	const session = data?.openServiceSession;
	if (!session) {
		throw new Error('No service session returned by the server');
	}

	return session;
}

export type CloseServiceSessionInput = CloseServiceSession$input['input'];
export type ClosedServiceSession = CloseServiceSession$result['closeServiceSession'];

export async function closeServiceSession(
	input: CloseServiceSessionInput
): Promise<ClosedServiceSession> {
	const store = new CloseServiceSessionStore();
	const { data, errors } = await store.mutate({ input });

	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to close service session');
	}

	const session = data?.closeServiceSession;
	if (!session) {
		throw new Error('No service session returned by the server');
	}

	return session;
}

export async function revertServiceSession(serviceId: string): Promise<boolean> {
	const store = new RevertServiceSessionStore();
	const { data, errors } = await store.mutate({ input: { serviceId } });

	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to revert service session');
	}

	return data?.revertServiceSession ?? false;
}

// Project Session functions
export type OpenProjectSessionInput = OpenProjectSession$input['input'];
export type ProjectSession = OpenProjectSession$result['openProjectSession'];

export async function openProjectSession(input: OpenProjectSessionInput): Promise<ProjectSession> {
	const store = new OpenProjectSessionStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to open project session');
	}
	const session = data?.openProjectSession;
	if (!session) {
		throw new Error('No project session returned by the server');
	}
	return session;
}

export type CloseProjectSessionInput = CloseProjectSession$input['input'];
export type ClosedProjectSession = CloseProjectSession$result['closeProjectSession'];

export async function closeProjectSession(
	input: CloseProjectSessionInput
): Promise<ClosedProjectSession> {
	const store = new CloseProjectSessionStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to close project session');
	}
	const session = data?.closeProjectSession;
	if (!session) {
		throw new Error('No project session returned by the server');
	}
	return session;
}

export async function revertProjectSession(projectId: string): Promise<boolean> {
	const store = new RevertProjectSessionStore();
	const { data, errors } = await store.mutate({ input: { projectId } });

	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to revert project session');
	}

	return data?.revertProjectSession ?? false;
}

// Service Task functions
export type AddServiceTaskResult = AddServiceTask$result['addTaskCompletion'];

export async function addServiceTask(
	serviceId: string,
	taskId: string,
	notes?: string
): Promise<AddServiceTaskResult> {
	const store = new AddServiceTaskStore();
	const { data, errors } = await store.mutate({ serviceId, taskId, notes });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to add service task');
	}
	const session = data?.addTaskCompletion;
	if (!session) {
		throw new Error('No session returned by the server');
	}
	return session;
}

export type RemoveServiceTaskResult = RemoveServiceTask$result['removeTaskCompletion'];

export async function removeServiceTask(
	serviceId: string,
	taskId: string
): Promise<RemoveServiceTaskResult> {
	const store = new RemoveServiceTaskStore();
	const { data, errors } = await store.mutate({ serviceId, taskId });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove service task');
	}
	const session = data?.removeTaskCompletion;
	if (!session) {
		throw new Error('No session returned by the server');
	}
	return session;
}

// Project Task functions
export type AddProjectTaskResult = AddProjectTask$result['addProjectTaskCompletion'];

export async function addProjectTask(
	projectId: string,
	taskId: string,
	notes?: string
): Promise<AddProjectTaskResult> {
	const store = new AddProjectTaskStore();
	const { data, errors } = await store.mutate({ projectId, taskId, notes });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to add project task');
	}
	const session = data?.addProjectTaskCompletion;
	if (!session) {
		throw new Error('No session returned by the server');
	}
	return session;
}

export type RemoveProjectTaskResult = RemoveProjectTask$result['removeProjectTaskCompletion'];

export async function removeProjectTask(
	projectId: string,
	taskId: string
): Promise<RemoveProjectTaskResult> {
	const store = new RemoveProjectTaskStore();
	const { data, errors } = await store.mutate({ projectId, taskId });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove project task');
	}
	const session = data?.removeProjectTaskCompletion;
	if (!session) {
		throw new Error('No session returned by the server');
	}
	return session;
}

// Service Note functions
export type CreateServiceNoteResult = CreateServiceNote$result['createServiceSessionNote'];

export async function createServiceNote(
	input: ServiceSessionNoteInput
): Promise<CreateServiceNoteResult> {
	const store = new CreateServiceNoteStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to create service note');
	}
	const note = data?.createServiceSessionNote;
	if (!note) {
		throw new Error('No note returned by the server');
	}
	return note;
}

export type UpdateServiceNoteResult = UpdateServiceNote$result['updateServiceSessionNote'];

export async function updateServiceNote(
	input: ServiceSessionNoteUpdateInput
): Promise<UpdateServiceNoteResult> {
	const store = new UpdateServiceNoteStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to update service note');
	}
	const note = data?.updateServiceSessionNote;
	if (!note) {
		throw new Error('No note returned by the server');
	}
	return note;
}

export async function removeServiceNote(id: string): Promise<void> {
	const store = new RemoveServiceNoteStore();
	const { data, errors } = await store.mutate({ id });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove service note');
	}
	if (!data?.deleteServiceSessionNote) {
		throw new Error('Failed to delete service note');
	}
}

// Project Note functions
export type CreateProjectNoteResult = CreateProjectNote$result['createProjectSessionNote'];

export async function createProjectNote(
	input: ProjectSessionNoteInput
): Promise<CreateProjectNoteResult> {
	const store = new CreateProjectNoteStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to create project note');
	}
	const note = data?.createProjectSessionNote;
	if (!note) {
		throw new Error('No note returned by the server');
	}
	return note;
}

export type UpdateProjectNoteResult = UpdateProjectNote$result['updateProjectSessionNote'];

export async function updateProjectNote(
	input: ProjectSessionNoteUpdateInput
): Promise<UpdateProjectNoteResult> {
	const store = new UpdateProjectNoteStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to update project note');
	}
	const note = data?.updateProjectSessionNote;
	if (!note) {
		throw new Error('No note returned by the server');
	}
	return note;
}

export async function removeProjectNote(id: string): Promise<void> {
	const store = new RemoveProjectNoteStore();
	const { data, errors } = await store.mutate({ id });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove project note');
	}
	if (!data?.deleteProjectSessionNote) {
		throw new Error('Failed to delete project note');
	}
}

// Service Photo functions
export async function uploadServicePhoto(
	file: File,
	sessionId: string,
	title?: string,
	notes?: string,
	internal: boolean = true
): Promise<UploadPhotoResponse> {
	const formData = new FormData();
	formData.append('file', file);
	formData.append('sessionId', sessionId);
	formData.append('title', title || file.name);
	formData.append('notes', notes || '');
	formData.append('internal', String(internal));

	const response = await fetch(`${API_BASE_URL}/v1/api/upload/photo/service/`, {
		method: 'POST',
		credentials: 'include',
		body: formData
	});

	if (!response.ok) {
		const errorData = await response.json().catch(() => ({ detail: '' }));
		throw new Error(errorData.detail || `Upload failed: ${response.status} ${response.statusText}`);
	}

	return response.json();
}

export type UpdateServicePhotoResult = UpdateServicePhoto$result['updateServiceSessionImage'];

export async function updateServicePhoto(
	input: ServiceSessionImageUpdateInput
): Promise<UpdateServicePhotoResult> {
	const store = new UpdateServicePhotoStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to update service photo');
	}
	const photo = data?.updateServiceSessionImage;
	if (!photo) {
		throw new Error('No photo returned by the server');
	}
	return photo;
}

export async function removeServicePhoto(id: string): Promise<void> {
	const store = new RemoveServicePhotoStore();
	const { data, errors } = await store.mutate({ id });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove service photo');
	}
	if (!data?.deleteServiceSessionImage) {
		throw new Error('Failed to delete service photo');
	}
}

// Project Photo functions
export async function uploadProjectPhoto(
	file: File,
	sessionId: string,
	title?: string,
	notes?: string,
	internal: boolean = true
): Promise<UploadPhotoResponse> {
	const formData = new FormData();
	formData.append('file', file);
	formData.append('sessionId', sessionId);
	formData.append('title', title || file.name);
	formData.append('notes', notes || '');
	formData.append('internal', String(internal));

	const response = await fetch(`${API_BASE_URL}/v1/api/upload/photo/project/`, {
		method: 'POST',
		credentials: 'include',
		body: formData
	});

	if (!response.ok) {
		const errorData = await response.json().catch(() => ({ detail: '' }));
		throw new Error(errorData.detail || `Upload failed: ${response.status} ${response.statusText}`);
	}

	return response.json();
}

export type UpdateProjectPhotoResult = UpdateProjectPhoto$result['updateProjectSessionImage'];

export async function updateProjectPhoto(
	input: ProjectSessionImageUpdateInput
): Promise<UpdateProjectPhotoResult> {
	const store = new UpdateProjectPhotoStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to update project photo');
	}
	const photo = data?.updateProjectSessionImage;
	if (!photo) {
		throw new Error('No photo returned by the server');
	}
	return photo;
}

export async function removeProjectPhoto(id: string): Promise<void> {
	const store = new RemoveProjectPhotoStore();
	const { data, errors } = await store.mutate({ id });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove project photo');
	}
	if (!data?.deleteProjectSessionImage) {
		throw new Error('Failed to delete project photo');
	}
}

// Service Video functions
export async function uploadServiceVideo(
	file: File,
	sessionId: string,
	title?: string,
	notes?: string,
	internal: boolean = true
): Promise<UploadVideoResponse> {
	const formData = new FormData();
	formData.append('file', file);
	formData.append('sessionId', sessionId);
	formData.append('title', title || file.name);
	formData.append('notes', notes || '');
	formData.append('internal', String(internal));

	const response = await fetch(`${API_BASE_URL}/v1/api/upload/video/service/`, {
		method: 'POST',
		credentials: 'include',
		body: formData
	});

	if (!response.ok) {
		const errorData = await response.json().catch(() => ({ detail: '' }));
		throw new Error(errorData.detail || `Upload failed: ${response.status} ${response.statusText}`);
	}

	return response.json();
}

export type UpdateServiceVideoResult = UpdateServiceVideo$result['updateServiceSessionVideo'];

export async function updateServiceVideo(
	input: ServiceSessionVideoUpdateInput
): Promise<UpdateServiceVideoResult> {
	const store = new UpdateServiceVideoStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to update service video');
	}
	const video = data?.updateServiceSessionVideo;
	if (!video) {
		throw new Error('No video returned by the server');
	}
	return video;
}

export async function removeServiceVideo(id: string): Promise<void> {
	const store = new RemoveServiceVideoStore();
	const { data, errors } = await store.mutate({ id });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove service video');
	}
	if (!data?.deleteServiceSessionVideo) {
		throw new Error('Failed to delete service video');
	}
}

// Project Video functions
export async function uploadProjectVideo(
	file: File,
	sessionId: string,
	title?: string,
	notes?: string,
	internal: boolean = true
): Promise<UploadVideoResponse> {
	const formData = new FormData();
	formData.append('file', file);
	formData.append('sessionId', sessionId);
	formData.append('title', title || file.name);
	formData.append('notes', notes || '');
	formData.append('internal', String(internal));

	const response = await fetch(`${API_BASE_URL}/v1/api/upload/video/project/`, {
		method: 'POST',
		credentials: 'include',
		body: formData
	});

	if (!response.ok) {
		const errorData = await response.json().catch(() => ({ detail: '' }));
		throw new Error(errorData.detail || `Upload failed: ${response.status} ${response.statusText}`);
	}

	return response.json();
}

export type UpdateProjectVideoResult = UpdateProjectVideo$result['updateProjectSessionVideo'];

export async function updateProjectVideo(
	input: ProjectSessionVideoUpdateInput
): Promise<UpdateProjectVideoResult> {
	const store = new UpdateProjectVideoStore();
	const { data, errors } = await store.mutate({ input });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to update project video');
	}
	const video = data?.updateProjectSessionVideo;
	if (!video) {
		throw new Error('No video returned by the server');
	}
	return video;
}

export async function removeProjectVideo(id: string): Promise<void> {
	const store = new RemoveProjectVideoStore();
	const { data, errors } = await store.mutate({ id });
	if (errors?.length) {
		const message = errors.map((e) => e.message || 'Unknown error').join('; ');
		throw new Error(message || 'Failed to remove project video');
	}
	if (!data?.deleteProjectSessionVideo) {
		throw new Error('Failed to delete project video');
	}
}
