/**
 * Contacts Store - Manages contacts state using Svelte 5 runes
 */

import { contactsApi } from '$lib/api/contacts';
import type { Contact, ContactFilters } from '$lib/api/contacts';

// Default page size for pagination
const DEFAULT_PAGE_SIZE = 50;

// State
let contacts = $state<Contact[]>([]);
let selectedContact = $state<Contact | null>(null);
let loading = $state(false);
let loadingMore = $state(false);
let error = $state<string | null>(null);
let total = $state(0);
let filters = $state<ContactFilters>({});
let hasMore = $state(true);
let currentOffset = $state(0);

export const contactsStore = {
	// Getters
	get contacts() {
		return contacts;
	},
	get selectedContact() {
		return selectedContact;
	},
	get loading() {
		return loading;
	},
	get loadingMore() {
		return loadingMore;
	},
	get error() {
		return error;
	},
	get total() {
		return total;
	},
	get filters() {
		return filters;
	},
	get hasMore() {
		return hasMore;
	},

	/**
	 * Load contacts with optional filters (resets to first page)
	 */
	async loadContacts(newFilters?: ContactFilters) {
		if (newFilters) {
			filters = { ...filters, ...newFilters };
		}

		loading = true;
		error = null;
		currentOffset = 0;

		try {
			const result = await contactsApi.list({
				...filters,
				limit: DEFAULT_PAGE_SIZE,
				offset: 0,
			});
			contacts = result.contacts;
			total = result.total;
			hasMore = contacts.length < total;
			currentOffset = contacts.length;
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to load contacts';
			console.error('Failed to load contacts:', e);
		} finally {
			loading = false;
		}
	},

	/**
	 * Load more contacts (infinite scroll)
	 */
	async loadMore() {
		if (loadingMore || !hasMore) return;

		loadingMore = true;
		error = null;

		try {
			const result = await contactsApi.list({
				...filters,
				limit: DEFAULT_PAGE_SIZE,
				offset: currentOffset,
			});

			const newContacts = result.contacts;
			contacts = [...contacts, ...newContacts];
			total = result.total;
			currentOffset += newContacts.length;
			hasMore = contacts.length < total;
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to load more contacts';
			console.error('Failed to load more contacts:', e);
		} finally {
			loadingMore = false;
		}
	},

	/**
	 * Load a single contact by ID
	 */
	async loadContact(id: string) {
		loading = true;
		error = null;

		try {
			const contact = await contactsApi.get(id);
			selectedContact = contact;
			return contact;
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to load contact';
			console.error('Failed to load contact:', e);
			return null;
		} finally {
			loading = false;
		}
	},

	/**
	 * Create a new contact
	 */
	async createContact(data: Partial<Contact>) {
		loading = true;
		error = null;

		try {
			const contact = await contactsApi.create(data);
			// Add to local state
			contacts = [contact, ...contacts];
			total += 1;
			return contact;
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to create contact';
			console.error('Failed to create contact:', e);
			throw e;
		} finally {
			loading = false;
		}
	},

	/**
	 * Update a contact
	 */
	async updateContact(id: string, data: Partial<Contact>) {
		loading = true;
		error = null;

		try {
			const contact = await contactsApi.update(id, data);
			// Update in local state
			contacts = contacts.map((c) => (c.id === id ? contact : c));
			if (selectedContact?.id === id) {
				selectedContact = contact;
			}
			return contact;
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to update contact';
			console.error('Failed to update contact:', e);
			throw e;
		} finally {
			loading = false;
		}
	},

	/**
	 * Delete a contact
	 */
	async deleteContact(id: string) {
		loading = true;
		error = null;

		try {
			await contactsApi.delete(id);
			// Remove from local state
			contacts = contacts.filter((c) => c.id !== id);
			total -= 1;
			if (selectedContact?.id === id) {
				selectedContact = null;
			}
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to delete contact';
			console.error('Failed to delete contact:', e);
			throw e;
		} finally {
			loading = false;
		}
	},

	/**
	 * Toggle favorite status
	 */
	async toggleFavorite(id: string) {
		try {
			const contact = await contactsApi.toggleFavorite(id);
			// Update in local state
			contacts = contacts.map((c) => (c.id === id ? contact : c));
			if (selectedContact?.id === id) {
				selectedContact = contact;
			}
			return contact;
		} catch (e) {
			console.error('Failed to toggle favorite:', e);
			throw e;
		}
	},

	/**
	 * Toggle archive status
	 */
	async toggleArchive(id: string) {
		try {
			const contact = await contactsApi.toggleArchive(id);
			// Remove from current view if archived/unarchived
			contacts = contacts.filter((c) => c.id !== id);
			total -= 1;
			if (selectedContact?.id === id) {
				selectedContact = null;
			}
			return contact;
		} catch (e) {
			console.error('Failed to toggle archive:', e);
			throw e;
		}
	},

	/**
	 * Clear filters and reload
	 */
	async clearFilters() {
		filters = {};
		await this.loadContacts();
	},

	/**
	 * Set search query
	 */
	setSearch(search: string) {
		filters = { ...filters, search };
	},

	/**
	 * Set tag filter
	 */
	setTagId(tagId: string | undefined) {
		filters = { ...filters, tagId };
	},

	/**
	 * Clear selected contact
	 */
	clearSelected() {
		selectedContact = null;
	},
};
