import * as i0 from '@angular/core';
import { InjectionToken, Inject, Optional, Injectable } from '@angular/core';
import { SdUtilities } from '@sd-angular/core/utilities';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';

const SD_STORAGE_CONFIG = new InjectionToken('storage.configuration');

/* eslint-disable @typescript-eslint/no-explicit-any */
class SdStorageService {
    configuration;
    // Dùng Map để quản lý bộ nhớ tốt hơn Record
    #memoryCache = new Map();
    #subjects = new Map();
    constructor(configuration) {
        this.configuration = configuration;
    }
    create(key, option) {
        if (!key)
            throw new Error('Key is required');
        // 1. Xử lý Key
        let hashKey;
        if (typeof key === 'string') {
            hashKey = key;
        }
        else if (typeof key === 'object') {
            hashKey = SdUtilities.hash(key);
        }
        else {
            throw new Error('Invalid key type');
        }
        if (this.configuration?.key) {
            hashKey = this.configuration.key(hashKey);
        }
        // 2. Init Subject: Đọc dữ liệu từ Storage ngay lập tức để Subject có giá trị đúng
        if (!this.#subjects.has(hashKey)) {
            const existingData = this.#internalGet(hashKey, option);
            // Fix Type: as T | undefined
            this.#subjects.set(hashKey, new BehaviorSubject(existingData ?? option?.default));
        }
        const subject = this.#subjects.get(hashKey);
        // 3. Define Helpers
        const get = () => {
            const val = this.#internalGet(hashKey, option);
            return (val ?? option?.default);
        };
        const set = (data) => {
            this.#internalSet(hashKey, data, option);
            subject.next(data);
        };
        const has = () => {
            return this.#internalGet(hashKey, option) !== undefined;
        };
        const remove = () => {
            this.#internalRemove(hashKey, option);
            subject.next(undefined);
        };
        // Hàm dọn dẹp bộ nhớ (quan trọng)
        const destroy = () => {
            subject.complete();
            this.#subjects.delete(hashKey);
            this.#memoryCache.delete(hashKey);
        };
        return {
            get,
            set,
            has,
            remove,
            // @ts-ignore: Bổ sung vào interface nếu cần
            destroy,
            subject: subject,
            observer: subject.asObservable().pipe(map(() => get())),
        };
    }
    // --- PRIVATE CORE LOGIC ---
    /**
     * Helper xác định loại Storage đang dùng
     */
    #getStorage(option) {
        return option?.type === 'session' ? sessionStorage : localStorage;
    }
    /**
     * Đọc dữ liệu: Memory -> Storage -> Parse
     */
    #internalGet(key, option) {
        // 1. Check Memory (Nhanh nhất)
        let entry = this.#memoryCache.get(key);
        // 2. Check Storage (Nếu memory chưa có hoặc mới F5)
        if (!entry) {
            const storage = this.#getStorage(option);
            const raw = storage.getItem(key);
            if (raw) {
                try {
                    const parsed = JSON.parse(raw);
                    // Convert string date back to Date object nếu cần
                    entry = {
                        data: parsed.data,
                        createdOn: new Date(parsed.createdOn)
                    };
                    // Sync ngược vào RAM
                    this.#memoryCache.set(key, entry);
                }
                catch (e) {
                    console.warn('Storage parse error', e);
                    this.#internalRemove(key, option); // Dữ liệu lỗi -> Xóa
                }
            }
        }
        if (!entry)
            return undefined;
        return this.#deepClone(entry.data);
    }
    /**
     * Ghi dữ liệu: Memory -> Storage
     */
    #internalSet(key, data, option) {
        const clonedData = this.#deepClone(data);
        const entry = {
            data: clonedData,
            createdOn: new Date(),
        };
        // 1. Lưu Memory
        this.#memoryCache.set(key, entry);
        // 2. Lưu Storage
        const storage = this.#getStorage(option);
        try {
            storage.setItem(key, JSON.stringify(entry));
        }
        catch (e) {
            console.error('Storage quota exceeded', e);
        }
    }
    /**
     * Xóa dữ liệu
     */
    #internalRemove(key, option) {
        this.#memoryCache.delete(key);
        const storage = this.#getStorage(option);
        storage.removeItem(key);
    }
    /**
     * Deep Clone an toàn
     */
    #deepClone(val) {
        if (val === undefined || val === null)
            return val;
        return JSON.parse(JSON.stringify(val));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdStorageService, deps: [{ token: SD_STORAGE_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdStorageService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdStorageService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [SD_STORAGE_CONFIG]
                }, {
                    type: Optional
                }] }] });

/**
 * Generated bundle index. Do not edit.
 */

export { SD_STORAGE_CONFIG, SdStorageService };
//# sourceMappingURL=sd-angular-core-services-storage.mjs.map
