"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_APP_CONFIG = exports.APP_CONFIG_STORAGE_KEY = void 0;
exports.fetchAppConfigFromServer = fetchAppConfigFromServer;
exports.saveAppConfigToServer = saveAppConfigToServer;
exports.saveAutomationNotificationPreferenceToServer = saveAutomationNotificationPreferenceToServer;
exports.syncAppConfigFromServer = syncAppConfigFromServer;
exports.getStoredAppConfig = getStoredAppConfig;
exports.setStoredAppConfig = setStoredAppConfig;
exports.updateStoredAppConfig = updateStoredAppConfig;
exports.useAppConfig = useAppConfig;
exports.describeAutoReceiveSchedule = describeAutoReceiveSchedule;
exports.getWeeklyScheduleOptions = getWeeklyScheduleOptions;
var react_1 = require("react");
var clientIdentity_1 = require("./clientIdentity");
var notificationIdentity_1 = require("./notificationIdentity");
exports.APP_CONFIG_STORAGE_KEY = 'work-server.app-config';
var APP_CONFIG_EVENT = 'work-server:app-config';
var APP_CONFIG_API_PATH = '/app-config';
var AUTOMATION_NOTIFICATION_PREFERENCE_API_PATH = '/notifications/preferences/automation';
var APP_CONFIG_REQUEST_TIMEOUT_MS = 8000;
var cachedConfig = null;
var cachedRawConfig = null;
exports.DEFAULT_APP_CONFIG = {
    chat: {
        maxContextMessages: 12,
        maxContextChars: 3200,
        codexLiveMaxExecutionSeconds: 600,
        codexLiveIdleTimeoutSeconds: 180,
        receiveRoomNotifications: true,
    },
    automation: {
        autoRefreshEnabled: true,
        autoRefreshIntervalSeconds: 5,
        autoReceiveScheduleType: 'interval',
        autoReceiveIntervalSeconds: 30,
        autoReceiveDailyTime: '09:00',
        autoReceiveWeeklyDay: 'mon',
        autoReceiveWeeklyTime: '09:00',
        notifyOnAutomationStart: true,
        notifyOnAutomationProgress: true,
        notifyOnAutomationCompletion: true,
        notifyOnAutomationRelease: true,
        notifyOnAutomationMain: true,
        notifyOnAutomationFailure: true,
        notifyOnAutomationRestart: true,
        notifyOnAutomationIssueResolved: true,
    },
    worklogAutomation: {
        autoCreateDailyWorklog: false,
        dailyCreateTime: '18:00',
        repeatRequestEnabled: false,
        repeatIntervalMinutes: 60,
        includeScreenshots: true,
        includeChangedFiles: true,
        includeCommandLogs: true,
        template: 'detailed',
    },
    planDefaults: {
        jangsingProcessingRequired: true,
        autoDeployToMain: true,
        openEditorAfterCreate: true,
    },
    planCost: {
        baseCostPerMillionTokens: 10000,
        retryCostMultiplierPercent: 15,
        hourlyCostMultiplierPercent: 0,
        timeCostUnit: 'hour',
        attentionCostThresholdMultiplier: 1,
        warningCostThresholdMultiplier: 2,
        highCostThresholdMultiplier: 4,
    },
    gestureShortcuts: {
        openSearch: 'Mod+K',
        openWindowSearch: 'Mod+Shift+K',
    },
};
var WEEKLY_DAY_LABELS = {
    mon: '월요일',
    tue: '화요일',
    wed: '수요일',
    thu: '목요일',
    fri: '금요일',
    sat: '토요일',
    sun: '일요일',
};
var AUTOMATION_NOTIFICATION_KEYS = [
    'notifyOnAutomationStart',
    'notifyOnAutomationProgress',
    'notifyOnAutomationCompletion',
    'notifyOnAutomationRelease',
    'notifyOnAutomationMain',
    'notifyOnAutomationFailure',
    'notifyOnAutomationRestart',
    'notifyOnAutomationIssueResolved',
];
function clampIntervalSeconds(value, fallback) {
    if (!Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(3600, Math.max(1, Math.round(value)));
}
function normalizeTimeValue(value, fallback) {
    if (/^\d{2}:\d{2}$/.test(value)) {
        return value;
    }
    return fallback;
}
function normalizeScheduleType(value) {
    if (value === 'daily' || value === 'weekly') {
        return value;
    }
    return 'interval';
}
function normalizeWeeklyDay(value) {
    if (value && value in WEEKLY_DAY_LABELS) {
        return value;
    }
    return exports.DEFAULT_APP_CONFIG.automation.autoReceiveWeeklyDay;
}
function normalizeWorklogTemplate(value) {
    if (value === 'simple') {
        return 'simple';
    }
    return 'detailed';
}
function normalizeShortcutValue(value, fallback) {
    var trimmed = value === null || value === void 0 ? void 0 : value.trim();
    if (!trimmed) {
        return fallback;
    }
    return trimmed
        .split('+')
        .map(function (token) { return token.trim(); })
        .filter(Boolean)
        .join('+');
}
function normalizePlanCostValue(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(1000000, Math.max(100, Math.round(value)));
}
function normalizePlanCostMultiplierValue(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(100, Math.max(0.1, Math.round(value * 10) / 10));
}
function normalizePlanCostPercentValue(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(500, Math.max(0, Math.round(value)));
}
function normalizePlanCostTimeUnit(value) {
    if (value === 'minute' || value === 'second') {
        return value;
    }
    return 'hour';
}
function normalizeChatContextMessageLimit(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(50, Math.max(1, Math.round(value)));
}
function normalizeChatContextCharLimit(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(20000, Math.max(500, Math.round(value)));
}
function normalizeCodexLiveMaxExecutionSeconds(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(7200, Math.max(60, Math.round(value)));
}
function normalizeCodexLiveIdleTimeoutSeconds(value, fallback) {
    if (value === undefined || !Number.isFinite(value)) {
        return fallback;
    }
    return Math.min(3600, Math.max(30, Math.round(value)));
}
function normalizeBooleanValue(value, fallback) {
    if (typeof value !== 'boolean') {
        return fallback;
    }
    return value;
}
function normalizeConfig(raw) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
    var chat = raw === null || raw === void 0 ? void 0 : raw.chat;
    var automation = raw === null || raw === void 0 ? void 0 : raw.automation;
    var worklogAutomation = raw === null || raw === void 0 ? void 0 : raw.worklogAutomation;
    var planDefaults = raw === null || raw === void 0 ? void 0 : raw.planDefaults;
    var planCost = raw === null || raw === void 0 ? void 0 : raw.planCost;
    var gestureShortcuts = raw === null || raw === void 0 ? void 0 : raw.gestureShortcuts;
    return {
        chat: {
            maxContextMessages: normalizeChatContextMessageLimit(chat === null || chat === void 0 ? void 0 : chat.maxContextMessages, exports.DEFAULT_APP_CONFIG.chat.maxContextMessages),
            maxContextChars: normalizeChatContextCharLimit(chat === null || chat === void 0 ? void 0 : chat.maxContextChars, exports.DEFAULT_APP_CONFIG.chat.maxContextChars),
            codexLiveMaxExecutionSeconds: normalizeCodexLiveMaxExecutionSeconds(chat === null || chat === void 0 ? void 0 : chat.codexLiveMaxExecutionSeconds, exports.DEFAULT_APP_CONFIG.chat.codexLiveMaxExecutionSeconds),
            codexLiveIdleTimeoutSeconds: normalizeCodexLiveIdleTimeoutSeconds(chat === null || chat === void 0 ? void 0 : chat.codexLiveIdleTimeoutSeconds, exports.DEFAULT_APP_CONFIG.chat.codexLiveIdleTimeoutSeconds),
            receiveRoomNotifications: normalizeBooleanValue(chat === null || chat === void 0 ? void 0 : chat.receiveRoomNotifications, exports.DEFAULT_APP_CONFIG.chat.receiveRoomNotifications),
        },
        automation: {
            autoRefreshEnabled: (_a = automation === null || automation === void 0 ? void 0 : automation.autoRefreshEnabled) !== null && _a !== void 0 ? _a : exports.DEFAULT_APP_CONFIG.automation.autoRefreshEnabled,
            autoRefreshIntervalSeconds: clampIntervalSeconds((_b = automation === null || automation === void 0 ? void 0 : automation.autoRefreshIntervalSeconds) !== null && _b !== void 0 ? _b : exports.DEFAULT_APP_CONFIG.automation.autoRefreshIntervalSeconds, exports.DEFAULT_APP_CONFIG.automation.autoRefreshIntervalSeconds),
            autoReceiveScheduleType: normalizeScheduleType(automation === null || automation === void 0 ? void 0 : automation.autoReceiveScheduleType),
            autoReceiveIntervalSeconds: clampIntervalSeconds((_c = automation === null || automation === void 0 ? void 0 : automation.autoReceiveIntervalSeconds) !== null && _c !== void 0 ? _c : exports.DEFAULT_APP_CONFIG.automation.autoReceiveIntervalSeconds, exports.DEFAULT_APP_CONFIG.automation.autoReceiveIntervalSeconds),
            autoReceiveDailyTime: normalizeTimeValue((_d = automation === null || automation === void 0 ? void 0 : automation.autoReceiveDailyTime) !== null && _d !== void 0 ? _d : exports.DEFAULT_APP_CONFIG.automation.autoReceiveDailyTime, exports.DEFAULT_APP_CONFIG.automation.autoReceiveDailyTime),
            autoReceiveWeeklyDay: normalizeWeeklyDay(automation === null || automation === void 0 ? void 0 : automation.autoReceiveWeeklyDay),
            autoReceiveWeeklyTime: normalizeTimeValue((_e = automation === null || automation === void 0 ? void 0 : automation.autoReceiveWeeklyTime) !== null && _e !== void 0 ? _e : exports.DEFAULT_APP_CONFIG.automation.autoReceiveWeeklyTime, exports.DEFAULT_APP_CONFIG.automation.autoReceiveWeeklyTime),
            notifyOnAutomationStart: (_f = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationStart) !== null && _f !== void 0 ? _f : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationStart,
            notifyOnAutomationProgress: (_g = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationProgress) !== null && _g !== void 0 ? _g : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationProgress,
            notifyOnAutomationCompletion: (_h = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationCompletion) !== null && _h !== void 0 ? _h : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationCompletion,
            notifyOnAutomationRelease: (_j = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationRelease) !== null && _j !== void 0 ? _j : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationRelease,
            notifyOnAutomationMain: (_k = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationMain) !== null && _k !== void 0 ? _k : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationMain,
            notifyOnAutomationFailure: (_l = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationFailure) !== null && _l !== void 0 ? _l : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationFailure,
            notifyOnAutomationRestart: (_m = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationRestart) !== null && _m !== void 0 ? _m : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationRestart,
            notifyOnAutomationIssueResolved: (_o = automation === null || automation === void 0 ? void 0 : automation.notifyOnAutomationIssueResolved) !== null && _o !== void 0 ? _o : exports.DEFAULT_APP_CONFIG.automation.notifyOnAutomationIssueResolved,
        },
        worklogAutomation: {
            autoCreateDailyWorklog: (_p = worklogAutomation === null || worklogAutomation === void 0 ? void 0 : worklogAutomation.autoCreateDailyWorklog) !== null && _p !== void 0 ? _p : exports.DEFAULT_APP_CONFIG.worklogAutomation.autoCreateDailyWorklog,
            dailyCreateTime: normalizeTimeValue((_q = worklogAutomation === null || worklogAutomation === void 0 ? void 0 : worklogAutomation.dailyCreateTime) !== null && _q !== void 0 ? _q : exports.DEFAULT_APP_CONFIG.worklogAutomation.dailyCreateTime, exports.DEFAULT_APP_CONFIG.worklogAutomation.dailyCreateTime),
            repeatRequestEnabled: false,
            repeatIntervalMinutes: exports.DEFAULT_APP_CONFIG.worklogAutomation.repeatIntervalMinutes,
            includeScreenshots: (_r = worklogAutomation === null || worklogAutomation === void 0 ? void 0 : worklogAutomation.includeScreenshots) !== null && _r !== void 0 ? _r : exports.DEFAULT_APP_CONFIG.worklogAutomation.includeScreenshots,
            includeChangedFiles: (_s = worklogAutomation === null || worklogAutomation === void 0 ? void 0 : worklogAutomation.includeChangedFiles) !== null && _s !== void 0 ? _s : exports.DEFAULT_APP_CONFIG.worklogAutomation.includeChangedFiles,
            includeCommandLogs: (_t = worklogAutomation === null || worklogAutomation === void 0 ? void 0 : worklogAutomation.includeCommandLogs) !== null && _t !== void 0 ? _t : exports.DEFAULT_APP_CONFIG.worklogAutomation.includeCommandLogs,
            template: normalizeWorklogTemplate(worklogAutomation === null || worklogAutomation === void 0 ? void 0 : worklogAutomation.template),
        },
        planDefaults: {
            jangsingProcessingRequired: (_u = planDefaults === null || planDefaults === void 0 ? void 0 : planDefaults.jangsingProcessingRequired) !== null && _u !== void 0 ? _u : exports.DEFAULT_APP_CONFIG.planDefaults.jangsingProcessingRequired,
            autoDeployToMain: (_v = planDefaults === null || planDefaults === void 0 ? void 0 : planDefaults.autoDeployToMain) !== null && _v !== void 0 ? _v : exports.DEFAULT_APP_CONFIG.planDefaults.autoDeployToMain,
            openEditorAfterCreate: (_w = planDefaults === null || planDefaults === void 0 ? void 0 : planDefaults.openEditorAfterCreate) !== null && _w !== void 0 ? _w : exports.DEFAULT_APP_CONFIG.planDefaults.openEditorAfterCreate,
        },
        planCost: {
            baseCostPerMillionTokens: normalizePlanCostValue(planCost === null || planCost === void 0 ? void 0 : planCost.baseCostPerMillionTokens, exports.DEFAULT_APP_CONFIG.planCost.baseCostPerMillionTokens),
            retryCostMultiplierPercent: normalizePlanCostPercentValue(planCost === null || planCost === void 0 ? void 0 : planCost.retryCostMultiplierPercent, exports.DEFAULT_APP_CONFIG.planCost.retryCostMultiplierPercent),
            hourlyCostMultiplierPercent: normalizePlanCostPercentValue(planCost === null || planCost === void 0 ? void 0 : planCost.hourlyCostMultiplierPercent, exports.DEFAULT_APP_CONFIG.planCost.hourlyCostMultiplierPercent),
            timeCostUnit: normalizePlanCostTimeUnit(planCost === null || planCost === void 0 ? void 0 : planCost.timeCostUnit),
            attentionCostThresholdMultiplier: normalizePlanCostMultiplierValue(planCost === null || planCost === void 0 ? void 0 : planCost.attentionCostThresholdMultiplier, exports.DEFAULT_APP_CONFIG.planCost.attentionCostThresholdMultiplier),
            warningCostThresholdMultiplier: normalizePlanCostMultiplierValue(planCost === null || planCost === void 0 ? void 0 : planCost.warningCostThresholdMultiplier, exports.DEFAULT_APP_CONFIG.planCost.warningCostThresholdMultiplier),
            highCostThresholdMultiplier: normalizePlanCostMultiplierValue(planCost === null || planCost === void 0 ? void 0 : planCost.highCostThresholdMultiplier, exports.DEFAULT_APP_CONFIG.planCost.highCostThresholdMultiplier),
        },
        gestureShortcuts: {
            openSearch: normalizeShortcutValue(gestureShortcuts === null || gestureShortcuts === void 0 ? void 0 : gestureShortcuts.openSearch, exports.DEFAULT_APP_CONFIG.gestureShortcuts.openSearch),
            openWindowSearch: normalizeShortcutValue(gestureShortcuts === null || gestureShortcuts === void 0 ? void 0 : gestureShortcuts.openWindowSearch, exports.DEFAULT_APP_CONFIG.gestureShortcuts.openWindowSearch),
        },
    };
}
function pickAutomationNotificationSettings(automation) {
    return AUTOMATION_NOTIFICATION_KEYS.reduce(function (picked, key) {
        picked[key] = automation[key];
        return picked;
    }, {});
}
function mergeAutomationNotificationSettings(config, automation) {
    if (!automation) {
        return config;
    }
    return normalizeConfig(__assign(__assign({}, config), { automation: __assign(__assign({}, config.automation), automation) }));
}
function getCurrentAppOrigin() {
    if (typeof window === 'undefined') {
        return '';
    }
    return window.location.origin;
}
function getCurrentAppDomain() {
    if (typeof window === 'undefined') {
        return '';
    }
    return window.location.hostname;
}
function emitConfigChange() {
    if (typeof window === 'undefined') {
        return;
    }
    window.dispatchEvent(new Event(APP_CONFIG_EVENT));
}
function resolveAppConfigApiBaseUrl() {
    if (import.meta.env.VITE_WORK_SERVER_URL) {
        return import.meta.env.VITE_WORK_SERVER_URL;
    }
    return '/api';
}
function resolveAppConfigFallbackBaseUrl() {
    if (typeof window === 'undefined') {
        return null;
    }
    var hostname = window.location.hostname;
    var isLocalWorkServerHost = hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '0.0.0.0';
    if (!isLocalWorkServerHost) {
        return null;
    }
    var fallbackUrl = new URL(window.location.origin);
    fallbackUrl.port = '3100';
    fallbackUrl.pathname = '/api';
    fallbackUrl.search = '';
    fallbackUrl.hash = '';
    return fallbackUrl.toString().replace(/\/+$/, '');
}
var APP_CONFIG_API_BASE_URL = resolveAppConfigApiBaseUrl();
var APP_CONFIG_FALLBACK_BASE_URL = resolveAppConfigFallbackBaseUrl();
var AppConfigApiError = /** @class */ (function (_super) {
    __extends(AppConfigApiError, _super);
    function AppConfigApiError(message, status) {
        var _this = _super.call(this, message) || this;
        _this.name = 'AppConfigApiError';
        _this.status = status;
        return _this;
    }
    return AppConfigApiError;
}(Error));
function requestAppConfigOnce(baseUrl, path, init) {
    return __awaiter(this, void 0, void 0, function () {
        var headers, hasBody, method, controller, timeoutId, appOrigin, appDomain, response, error_1, text, payload, contentType, text;
        var _a, _b, _c, _d;
        return __generator(this, function (_e) {
            switch (_e.label) {
                case 0:
                    headers = (0, clientIdentity_1.appendClientIdHeader)(init === null || init === void 0 ? void 0 : init.headers);
                    hasBody = (init === null || init === void 0 ? void 0 : init.body) !== undefined && init.body !== null;
                    method = (_b = (_a = init === null || init === void 0 ? void 0 : init.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : 'GET';
                    controller = new AbortController();
                    timeoutId = setTimeout(function () { return controller.abort(); }, APP_CONFIG_REQUEST_TIMEOUT_MS);
                    if (hasBody && !headers.has('Content-Type')) {
                        headers.set('Content-Type', 'application/json');
                    }
                    appOrigin = getCurrentAppOrigin();
                    appDomain = getCurrentAppDomain();
                    if (appOrigin && !headers.has('X-App-Origin')) {
                        headers.set('X-App-Origin', appOrigin);
                    }
                    if (appDomain && !headers.has('X-App-Domain')) {
                        headers.set('X-App-Domain', appDomain);
                    }
                    _e.label = 1;
                case 1:
                    _e.trys.push([1, 3, , 4]);
                    return [4 /*yield*/, fetch("".concat(baseUrl).concat(path), __assign(__assign({}, init), { headers: headers, signal: controller.signal, cache: (_c = init === null || init === void 0 ? void 0 : init.cache) !== null && _c !== void 0 ? _c : (method === 'GET' ? 'no-store' : undefined) }))];
                case 2:
                    response = _e.sent();
                    return [3 /*break*/, 4];
                case 3:
                    error_1 = _e.sent();
                    clearTimeout(timeoutId);
                    if (error_1 instanceof DOMException && error_1.name === 'AbortError') {
                        throw new AppConfigApiError('서버 응답이 지연됩니다.', 408);
                    }
                    throw error_1;
                case 4:
                    clearTimeout(timeoutId);
                    if (!!response.ok) return [3 /*break*/, 6];
                    return [4 /*yield*/, response.text()];
                case 5:
                    text = _e.sent();
                    try {
                        payload = JSON.parse(text);
                        throw new AppConfigApiError(payload.message || '요청 처리에 실패했습니다.', response.status);
                    }
                    catch (_f) {
                        throw new AppConfigApiError(text || '요청 처리에 실패했습니다.', response.status);
                    }
                    _e.label = 6;
                case 6:
                    contentType = (_d = response.headers.get('content-type')) !== null && _d !== void 0 ? _d : '';
                    if (!!contentType.toLowerCase().includes('application/json')) return [3 /*break*/, 8];
                    return [4 /*yield*/, response.text()];
                case 7:
                    text = _e.sent();
                    throw new AppConfigApiError(text ? '서버 응답이 JSON이 아닙니다.' : '서버 응답을 확인할 수 없습니다.', 502);
                case 8: return [2 /*return*/, response.json()];
            }
        });
    });
}
function requestAppConfig(path, init) {
    return __awaiter(this, void 0, void 0, function () {
        var error_2, shouldRetryWithFallback;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 2, , 3]);
                    return [4 /*yield*/, requestAppConfigOnce(APP_CONFIG_API_BASE_URL, path, init)];
                case 1: return [2 /*return*/, _a.sent()];
                case 2:
                    error_2 = _a.sent();
                    shouldRetryWithFallback = APP_CONFIG_FALLBACK_BASE_URL &&
                        APP_CONFIG_FALLBACK_BASE_URL !== APP_CONFIG_API_BASE_URL &&
                        (error_2 instanceof AppConfigApiError
                            ? error_2.status === 404 || error_2.status === 408 || error_2.status === 502
                            : error_2 instanceof Error && /404|not found|Failed to fetch|Load failed|NetworkError/i.test(error_2.message));
                    if (!shouldRetryWithFallback) {
                        throw error_2;
                    }
                    return [2 /*return*/, requestAppConfigOnce(APP_CONFIG_FALLBACK_BASE_URL, path, init)];
                case 3: return [2 /*return*/];
            }
        });
    });
}
function fetchAppConfigFromServer() {
    return __awaiter(this, void 0, void 0, function () {
        var response, config, preference, _a;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    _b.trys.push([0, 3, , 4]);
                    return [4 /*yield*/, requestAppConfig(APP_CONFIG_API_PATH)];
                case 1:
                    response = _b.sent();
                    config = normalizeConfig(response.config);
                    return [4 /*yield*/, fetchAutomationNotificationPreferenceFromServer()];
                case 2:
                    preference = _b.sent();
                    return [2 /*return*/, mergeAutomationNotificationSettings(config, preference)];
                case 3:
                    _a = _b.sent();
                    return [2 /*return*/, null];
                case 4: return [2 /*return*/];
            }
        });
    });
}
function fetchAutomationNotificationPreferenceFromServer() {
    return __awaiter(this, void 0, void 0, function () {
        var target, query, response, _a;
        var _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    _c.trys.push([0, 2, , 3]);
                    target = (0, notificationIdentity_1.getAutomationNotificationPreferenceTarget)();
                    query = target ? "?".concat(new URLSearchParams(target).toString()) : '';
                    return [4 /*yield*/, requestAppConfig("".concat(AUTOMATION_NOTIFICATION_PREFERENCE_API_PATH).concat(query))];
                case 1:
                    response = _c.sent();
                    return [2 /*return*/, (_b = response.automation) !== null && _b !== void 0 ? _b : null];
                case 2:
                    _a = _c.sent();
                    return [2 /*return*/, null];
                case 3: return [2 /*return*/];
            }
        });
    });
}
function saveAppConfigToServer(config) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestAppConfig(APP_CONFIG_API_PATH, {
                        method: 'PUT',
                        body: JSON.stringify({ config: config }),
                    })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, normalizeConfig(response.config)];
            }
        });
    });
}
function saveAutomationNotificationPreferenceToServer(config) {
    return __awaiter(this, void 0, void 0, function () {
        var target, response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    target = (0, notificationIdentity_1.getAutomationNotificationPreferenceTarget)();
                    return [4 /*yield*/, requestAppConfig(AUTOMATION_NOTIFICATION_PREFERENCE_API_PATH, {
                            method: 'PUT',
                            body: JSON.stringify(__assign(__assign({}, (target !== null && target !== void 0 ? target : {})), { automation: pickAutomationNotificationSettings(config.automation) })),
                        })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, mergeAutomationNotificationSettings(config, response.automation)];
            }
        });
    });
}
function syncAppConfigFromServer() {
    return __awaiter(this, void 0, void 0, function () {
        var config;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, fetchAppConfigFromServer()];
                case 1:
                    config = _a.sent();
                    if (!config) {
                        return [2 /*return*/, false];
                    }
                    setStoredAppConfig(config);
                    return [2 /*return*/, true];
            }
        });
    });
}
function getStoredAppConfig() {
    if (typeof window === 'undefined') {
        return exports.DEFAULT_APP_CONFIG;
    }
    try {
        var raw = window.localStorage.getItem(exports.APP_CONFIG_STORAGE_KEY);
        if (!raw) {
            cachedConfig = exports.DEFAULT_APP_CONFIG;
            cachedRawConfig = null;
            return exports.DEFAULT_APP_CONFIG;
        }
        if (raw === cachedRawConfig && cachedConfig) {
            return cachedConfig;
        }
        var normalized = normalizeConfig(JSON.parse(raw));
        cachedConfig = normalized;
        cachedRawConfig = raw;
        return normalized;
    }
    catch (_a) {
        cachedConfig = exports.DEFAULT_APP_CONFIG;
        cachedRawConfig = null;
        return exports.DEFAULT_APP_CONFIG;
    }
}
function setStoredAppConfig(config) {
    if (typeof window === 'undefined') {
        return;
    }
    var normalized = normalizeConfig(config);
    var raw = JSON.stringify(normalized);
    cachedConfig = normalized;
    cachedRawConfig = raw;
    window.localStorage.setItem(exports.APP_CONFIG_STORAGE_KEY, raw);
    emitConfigChange();
}
function updateStoredAppConfig(updater) {
    var current = getStoredAppConfig();
    var next = updater(current);
    setStoredAppConfig(next);
}
function subscribeToAppConfig(callback) {
    if (typeof window === 'undefined') {
        return function () { return undefined; };
    }
    var handleChange = function () {
        callback();
    };
    window.addEventListener(APP_CONFIG_EVENT, handleChange);
    window.addEventListener('storage', handleChange);
    return function () {
        window.removeEventListener(APP_CONFIG_EVENT, handleChange);
        window.removeEventListener('storage', handleChange);
    };
}
function useAppConfig() {
    return (0, react_1.useSyncExternalStore)(subscribeToAppConfig, getStoredAppConfig, function () { return exports.DEFAULT_APP_CONFIG; });
}
function describeAutoReceiveSchedule(config) {
    var automation = config.automation;
    if (automation.autoReceiveScheduleType === 'daily') {
        return "\uB9E4\uC77C ".concat(automation.autoReceiveDailyTime);
    }
    if (automation.autoReceiveScheduleType === 'weekly') {
        return "\uB9E4\uC8FC ".concat(WEEKLY_DAY_LABELS[automation.autoReceiveWeeklyDay], " ").concat(automation.autoReceiveWeeklyTime);
    }
    return "".concat(automation.autoReceiveIntervalSeconds, "\uCD08\uB9C8\uB2E4");
}
function getWeeklyScheduleOptions() {
    return Object.entries(WEEKLY_DAY_LABELS).map(function (_a) {
        var value = _a[0], label = _a[1];
        return ({
            value: value,
            label: label,
        });
    });
}
