// resources/js/utils/RequestData.js
import { useHashKeyCache } from '../composables/useHashKeyCache.js';

/**
 * Modern implementation of the RequestData pattern.
 * Supports method chaining and integration with HashKeyCache.
 */
export class RequestData {
    constructor(withHashCheck = false) {
        this._url = '';
        this._type = 'GET';
        this._data = null;
        this._success = null;
        this._error = null;
        this._fromVarCache = false;
        this._withHashCheck = withHashCheck;
        this._hashCache = useHashKeyCache();
    }

    /** Set the request URL */
    url(u) {
        this._url = u;
        return this;
    }

    /** Set the HTTP method (GET, POST, etc.) */
    type(t) {
        this._type = t.toUpperCase();
        return this;
    }

    /** Set the request payload */
    data(d) {
        this._data = d;
        return this;
    }

    /** Set the success callback */
    success(callback) {
        this._success = callback;
        return this;
    }

    /** Set the error callback */
    error(callback) {
        this._error = callback;
        return this;
    }

    /** Enable or disable cache-first behavior */
    fromVarCache(bool) {
        this._fromVarCache = bool;
        return this;
    }

    /** Execute the request */
    async go() {
        if (!this._url) {
            console.error('[RequestData] URL is missing');
            return;
        }

        // 1. Check HashKey/Payload in URL first if applicable
        const urlMatch = this._hashCache.parseHashUrl(this._url);
        if (urlMatch.type !== 'none' && urlMatch.data) {
            if (this._success) this._success(urlMatch.data, urlMatch.value);
            return;
        }

        // 2. Check Var Cache (in-memory) if requested
        if (this._fromVarCache) {
            const cachedData = this._hashCache.getHashData(this._url);
            if (cachedData) {
                if (this._success) this._success(cachedData);
                // Revalidate in background (Stale-While-Revalidate pattern)
                this._fetchFromServer(true); 
                return;
            }
        }

        // 3. Perform network request
        return this._fetchFromServer();
    }

    /** Internal fetch implementation */
    async _fetchFromServer(background = false) {
        try {
            const options = {
                method: this._type,
                headers: {
                    'Accept': 'application/json',
                }
            };

            if (this._data && (this._type === 'POST' || this._type === 'PUT')) {
                options.headers['Content-Type'] = 'application/json';
                options.body = JSON.stringify(this._data);
            }

            const response = await fetch(this._url, options);
            if (!response.ok) throw new Error(`HTTP ${response.status}`);

            const result = await response.json();

            // Update cache
            if (this._fromVarCache) {
                this._hashCache.setHashData(this._url, result);
            }

            // If background revalidation found non-identical data, you might want to call success again
            // or use Pinia to update the UI reactively.
            if (this._success) {
                // For simplicity, we call success again if it's a background fetch 
                // but usually you want a way to avoid jitter if data is the same.
                this._success(result);
            }

            return result;
        } catch (err) {
            if (!background && this._error) {
                this._error(err);
            }
            if (background) {
                console.warn('[RequestData] Background revalidation failed:', err);
            }
        }
    }
}

/** Wrapper function for easier instantiation */
export function request(withHashCheck = false) {
    return new RequestData(withHashCheck);
}
