import Dexie, { type Table } from 'dexie';

import type { key_val } from '$lib/stores/ae_stores';

// li = list
// kv = key value list
// json = JSON string
// ux = user experience (mode)
// LLM = Large Language Model (AI)
// Updated 2025-03-15

export interface Journal {
	id: string; // actually "id_random"
	journal_id: string;

	// Essentially this is a change log of journals
	snapshot_id?: string; // This is the original journal ID. If deleted, then delete all children journals.
	previous_id?: null | string; // This is the old or parent journal ID
	next_id?: null | string; // This is the new or child journal ID

	external_id?: null | string;
	import_id?: null | string;
	code?: null | string;

	for_type?: null | string;
	for_id?: null | string;

	// template?: null|boolean; // Is this a template journal? If true, it can be used to create new journals.

	type_code?: null | string;

	account_id?: null | string; // Owner account of the journal
	person_id?: null | string; // Owner person of the journal
	// event_id?: null|string; // Assign to an event???
	// location_id?: null|string; // Assign to a location???

	name: string; // or the title
	short_name?: null | string; // Short name for the journal, if any. Used for display purposes.
	summary?: null | string; // LLM (AI) generated summary...???
	outline?: null | string; // LLM (AI) generated outline...???

	description?: null | string;
	description_md_html?: null | string; // Markdown converted to HTML based on description. Uses marked or similar library for conversion.
	description_md_html_alt?: null | string; // Markdown converted to HTML based on description. Uses marked or similar library for conversion.
	description_html?: null | string;
	description_json?: null | string;

	start_datetime?: null | Date;
	end_datetime?: null | Date;
	timezone?: null | string;

	alert?: null | boolean; // LLM (AI) generated summary...???
	alert_msg?: null | string; // LLM (AI) generated summary...???

	sort_by?: null | string; // This is the sort by field
	sort_by_desc?: null | string; // This is the sort by field description

	cfg_json?: null | key_val; // This is the configuration JSON for the journal

	data_json?: null | key_val; // We always need to store something extra...

	ux_mode?: null | string; // 'mobile' or 'desktop'

	// This only allows for basic access to the data.
	passcode_read?: null | string; // For LLM (AI) generated summary...???
	passcode_read_expire?: null | Date;
	passcode_write?: null | string;
	passcode_write_expire?: null | Date;

	passcode?: null | string; // For Journal Entry encryption password
	passcode_timeout?: null | number; // Timeout in seconds

	private_passcode?: null | string; // Combine with the Journal passcode for Journal Entry encryption password

	auth_key?: null | string; // For Journal authorization without sign in

	enable: null | boolean;
	hide?: null | boolean;
	archive?: null | boolean; // Archive the journal
	archive_on?: null | Date;
	priority?: null | boolean;
	sort?: null | number;
	group?: null | string;
	notes?: null | string;
	created_on: Date;
	updated_on?: null | Date;

	// Generated fields for sorting locally only
	tmp_sort_1?: null | string;
	tmp_sort_2?: null | string;
	tmp_sort_3?: null | string;

	combined_passcode?: null | string; // For Journal Entry encryption password

	// Additional fields for convenience (database views)
	file_count?: null | number; // Only files directly under a journal
	journal_file_id_li_json?: null | string;

	// One person
	person__given_name?: null | string;
	person__family_name?: null | string;
	person__full_name?: null | string;
	person__primary_email?: null | string;
	person__passcode?: null | string;

	// JSON formatted key value pairs for multiple people: {id: name, email, etc.}
	person__kv_json?: null | string;

	journal_name?: null | string;

	journal_location_code?: null | string;
	journal_location_name?: null | string;

	journal_entry_count?: null | number;

	// A key value list of the entries
	journal_entry_kv?: null | key_val;
	journal_entry_li?: null | [];
	// A key value list of the files
	journal_file_kv?: null | key_val;
	journal_file_li?: null | [];

	// journal_collection_id?: null|string; // For a collection of journals?

	// Future standard fields!!!
	obj_id?: null | string;
	obj_ext_uid?: null | string; // Probably not needed for journals
	obj_ext_id?: null | string; // Probably not needed for journals
	obj_import_id?: null | string; // Probably not needed for journals
	obj_code?: null | string;
	obj_account_id?: null | string;
	obj_passcode?: null | string;
	obj_type?: null | string; // Should always be 'journal' in this case
	obj_type_ver_id?: null | string; // The ID from the table for the object type
	obj_name?: null | string;
	obj_summary?: null | string; // LLM (AI) generated summary...???
	obj_outline?: null | string; // LLM (AI) generated outline...???
	obj_description?: null | string; // Probably not needed for journals
	obj_enable?: null | boolean;
	obj_enable_on?: null | Date;
	obj_archive_on?: null | Date;
	obj_hide?: null | boolean;
	obj_priority?: null | number;
	obj_sort?: null | number;
	obj_group?: null | string;
	obj_cfg_json?: null | string;
	obj_notes?: null | string;
	obj_created_on?: Date;
	obj_updated_on?: null | Date;
}

export const journal_field_li = [
	'id',
	'journal_id',
	'snapshot_id',
	'previous_id',
	'next_id',
	'external_id',
	'import_id',
	'code',
	'for_type',
	'for_id',
	'type_code',
	'account_id',
	'person_id',
	'name',
	'short_name',
	'summary',
	'outline',
	'description',
	'description_md_html',
	'description_md_html_alt',
	'description_html',
	'description_json',
	'start_datetime',
	'end_datetime',
	'timezone',
	'alert',
	'alert_msg',
	'sort_by',
	'sort_by_desc',
	'cfg_json',
	'data_json',
	'ux_mode',
	'passcode_read',
	'passcode_read_expire',
	'passcode_write',
	'passcode_write_expire',
	'passcode_timeout',
	'private_passcode',
	'auth_key',
	'enable',
	'hide',
	'archive', // Archive the journal
	'archive_on', // Archive date
	'priority', // Priority flag
	'sort', // Sort order
	'group', // Group name
	'notes', // Notes about the journal
	'created_on', // Creation date
	'updated_on', // Last updated date

	'tmp_sort_1', // Temporary sort field 1
	'tmp_sort_2', // Temporary sort field 2
	'tmp_sort_3', // Temporary sort field 3

	'combined_passcode', // For Journal Entry encryption password
	'file_count', // Only files directly under a journal
	'journal_file_id_li_json', // JSON string of file IDs
	'person__given_name', // Person's given name
	'person__family_name', // Person's family name
	'person__full_name', // Person's full name
	'person__primary_email', // Person's primary email
	'person__passcode', // Person's passcode
	'person__kv_json', // JSON formatted key value pairs for multiple people
	'journal_name', // Journal name
	'journal_location_code', // Journal location code
	'journal_location_name', // Journal location name
	'journal_entry_count', // Count of journal entries
	'journal_entry_kv', // Key value list of the entries
	'journal_entry_li', // List of journal entries
	'journal_file_kv', // Key value list of the files
	'journal_file_li', // List of journal files

	'obj_id', // Object ID
	'obj_ext_uid', // External UID
	'obj_ext_id', // External ID
	'obj_import_id', // Import ID
	'obj_code', // Object code
	'obj_account_id', // Object account ID
	'obj_passcode', // Object passcode
	'obj_type', // Object type
	'obj_type_ver_id', // Object type version ID
	'obj_name', // Object name
	'obj_summary', // Object summary
	'obj_outline', // Object outline
	'obj_description', // Object description
	'obj_enable', // Object enable flag
	'obj_enable_on', // Object enable date
	'obj_archive_on', // Object archive date
	'obj_hide', // Object hide flag
	'obj_priority', // Object priority
	'obj_sort', // Object sort order
	'obj_group', // Object group name
	'obj_cfg_json', // Object configuration JSON
	'obj_notes', // Object notes
	'obj_created_on', // Object creation date
	'obj_updated_on' // Object last updated date
];

// Updated 2025-04-02
export interface Journal_Entry {
	id: string; // actually "id_random"
	journal_entry_id: string;

	journal_id: string; // This is the parent journal ID. If deleted, then delete all children journal entries.

	// Essentially this is a change log of journal entries
	snapshot_id?: string; // This is the original journal ID. If deleted, then delete all children journal entries.
	previous_id?: null | string; // This is the old or parent journal ID
	next_id?: null | string; // This is the new or child journal ID

	external_id?: null | string;
	import_id?: null | string;
	code?: null | string;

	for_type?: null | string;
	for_id?: null | string;

	template?: null | boolean; // Is this a template journal entry? If true, it can be used to create new journal entries.

	activity_code?: null | string;
	category_code?: null | string;
	topic_code?: null | string;
	type_code?: null | string;
	tags?: null | string; // Comma separated tags

	journal_entry_type?: null | string; // This is the type of journal entry

	account_id?: null | string; // Owner account of the journal
	person_id?: null | string; // Owner person of the journal
	// event_id?: null|string; // Assign to an event???
	// location_id?: null|string; // Assign to a location???

	public?: null | boolean;
	private?: null | boolean;
	personal?: null | boolean;
	professional?: null | boolean;

	name: string; // or the title
	short_name?: null | string; // Short name for the journal entry, if any. Used for display purposes. Most likely for the templates list.
	summary?: null | string; // LLM (AI) generated summary...???
	outline?: null | string; // LLM (AI) generated outline...???
	// description?: null|string; // This is the description of the journal entry

	content?: null | string;
	content_md_html?: null | string; // Markdown converted to HTML based on content. Uses marked or similar library for conversion.
	content_md_html_alt?: null | string; // Markdown converted to HTML based on content. Uses marked or similar library for conversion.
	content_html?: null | string;
	content_json?: null | string;
	content_encrypted?: null | string; // This is the encrypted content of the journal entry

	history?: null | string; // This is the history of the journal entry; a log
	history_encrypted?: null | string; // This is the encrypted history of the journal entry

	passcode_hash?: null | string; // This is the passcode hash for the journal entry to look up the passcode

	start_datetime?: null | Date;
	end_datetime?: null | Date;
	timezone?: null | string;
	seconds?: null | number; // Duration in seconds

	location?: null | string; // Location of the journal entry
	latitude?: null | number; // Latitude of the journal entry
	longitude?: null | number; // Longitude of the journal entry

	billable?: null | boolean; // Is this billable?
	bill_to?: null | string; // Who to bill for this journal entry
	bill_rate?: null | number; // Rate to bill for this journal entry
	billable_minutes?: null | number; // Billable minutes for this journal entry

	alert?: null | boolean; // LLM (AI) generated summary...???
	alert_msg?: null | string; // LLM (AI) generated summary...???

	parent_id?: null | string; // This is the parent journal entry ID. If deleted, then delete all children journal entries.
	related_entry_id_li?: null | key_val; // List of related journal entry IDs

	// cfg_json?: null|key_val; // This is the configuration JSON for the journal entry
	data_json?: null | key_val; // We always need to store something extra...

	// This only allows for basic access to the content.
	passcode_read?: null | string; // For LLM (AI) generated summary...???
	passcode_read_expire?: null | Date;
	passcode_write?: null | string;
	passcode_write_expire?: null | Date;

	enable: null | boolean;
	hide?: null | boolean;
	priority?: null | boolean;
	sort?: null | number;
	group?: null | string;
	notes?: null | string;
	created_on: Date;
	updated_on?: null | Date;

	// Generated fields for sorting locally only
	tmp_sort_1?: null | string;
	tmp_sort_2?: null | string;
	tmp_sort_3?: null | string;

	// Additional fields for convenience (database views)
	file_count?: null | number; // Only files directly under a journal
	journal_file_id_li_json?: null | string;

	journal_code?: null | string; // This is the code for the journal entry
	journal_name?: null | string; // This is the name for the journal entry

	// One person
	person__given_name?: null | string;
	person__family_name?: null | string;
	person__full_name?: null | string;
	person__primary_email?: null | string;
	person__passcode?: null | string;

	// JSON formatted key value pairs for multiple people: {id: name, email, etc.}
	person__kv_json?: null | string;

	// A key value list of the files
	journal_file_kv?: null | key_val;
	journal_file_li?: null | [];

	// journal_collection_id?: null|string; // For a collection of journal entries?

	// Future standard fields!!!
	obj_id?: null | string;
	obj_ext_uid?: null | string; // Probably not needed for journal entries
	obj_ext_id?: null | string; // Probably not needed for journal entries
	obj_import_id?: null | string; // Probably not needed for journal entries
	obj_code?: null | string;
	obj_account_id?: null | string;
	obj_passcode?: null | string;
	obj_type?: null | string; // Should always be 'journal' in this case
	obj_type_ver_id?: null | string; // The ID from the table for the object type
	obj_name?: null | string;
	obj_summary?: null | string; // LLM (AI) generated summary...???
	obj_outline?: null | string; // LLM (AI) generated outline...???
	obj_description?: null | string; // Probably not needed for journal entries
	obj_enable?: null | boolean;
	obj_enable_on?: null | Date;
	obj_archive_on?: null | Date;
	obj_hide?: null | boolean;
	obj_priority?: null | number;
	obj_sort?: null | number;
	obj_group?: null | string;
	obj_cfg_json?: null | string;
	obj_notes?: null | string;
	obj_created_on?: Date;
	obj_updated_on?: null | Date;
}

export const journal_entry_field_li = [
	'id',
	'journal_entry_id',
	'journal_id',
	'code',
	'for_type',
	'for_id',
	'template',
	'activity_code',
	'category_code',
	'topic_code',
	'type_code',
	'tags',
	'journal_entry_type',
	'account_id',
	'person_id',
	'public',
	'private',
	'personal',
	'professional',
	'name',
	'short_name',
	'summary',
	'outline',
	'content',
	'content_md_html',
	'content_md_html_alt',
	'content_html',
	'content_json',
	'content_encrypted',
	'history',
	'history_encrypted',
	'passcode_hash',
	'start_datetime',
	'end_datetime',
	'timezone',
	'seconds',
	'location',
	'latitude',
	'longitude',
	'billable',
	'bill_to',
	'bill_rate',
	'billable_minutes',
	'alert',
	'alert_msg',
	'parent_id',
	'related_entry_id_li',
	'data_json',
	'passcode_read',
	'passcode_read_expire',
	'passcode_write',
	'passcode_write_expire',
	'enable',
	'hide',
	'priority',
	'sort',
	'group',
	'notes',
	'created_on',
	'updated_on',

	'tmp_sort_1',
	'tmp_sort_2',
	'tmp_sort_3',

	'file_count',
	'journal_file_id_li_json',
	'journal_code',
	'journal_name',
	'person__given_name',
	'person__family_name',
	'person__full_name',
	'person__primary_email',
	'person__passcode',
	'person__kv_json',
	'journal_file_kv',
	'journal_file_li',

	'obj_id',
	'obj_ext_uid',
	'obj_ext_id',
	'obj_import_id',
	'obj_code',
	'obj_account_id',
	'obj_passcode',
	'obj_type',
	'obj_type_ver_id',
	'obj_name',
	'obj_summary',
	'obj_outline',
	'obj_description',
	'obj_enable',
	'obj_enable_on',
	'obj_archive_on',
	'obj_hide',
	'obj_priority',
	'obj_sort',
	'obj_group',
	'obj_cfg_json',
	'obj_notes',
	'obj_created_on',
	'obj_updated_on'
];

// Updated 2024-06-10
export class MySubClassedDexie extends Dexie {
	// We just tell the typing system this is the case
	journal!: Table<Journal>;
	journal_entry!: Table<Journal_Entry>;

	constructor() {
		super('ae_journals_db');
		this.version(4).stores({
			journal: `
                id, journal_id,
                code,
                account_id,
                person_id,
                conference, type,
                name,
                start_datetime, end_datetime,
                timezone,
                tmp_sort_1, tmp_sort_2, tmp_sort_3,
                enable, hide, priority, sort, group, created_on, updated_on`,
			journal_entry: `
                id, journal_entry_id,
                journal_id,
                code,
                account_id,
                template,
                name,
                start_datetime, end_datetime,
                timezone,
                tmp_sort_1, tmp_sort_2, tmp_sort_3,
                enable, hide, priority, sort, group, created_on, updated_on`
		});
	}
}

export const db_journals = new MySubClassedDexie();
