//
//  AppScenicQueueStore.swift
//  suixinkan
//

import Foundation

/// 管理当前账号的景区排队打卡点、播报和设置缓存。
final class AppScenicQueueStore {

    private enum Key: String, CaseIterable {
        case punchSpotId = "scenic_queue_punch_spot_id"
        case punchSpotName = "scenic_queue_punch_spot_name"
        case remark = "scenic_queue_remark"
        case settingsSnapshot = "scenic_queue_settings_snapshot"
        case useOfflineTTS = "scenic_queue_offline_tts_v1"
        case presetVoices = "scenic_queue_preset_voices_v1"
    }

    private let defaults: UserDefaults
    private let session: AppSessionStore

    /// 使用指定持久化容器和会话创建景区排队存储。
    init(defaults: UserDefaults, session: AppSessionStore) {
        self.defaults = defaults
        self.session = session
    }

    /// 已保存打卡点 ID。
    var punchSpotId: String {
        get {
            guard let key = scenicKey(.punchSpotId) else { return "" }
            return defaults.string(forKey: key) ?? ""
        }
        set {
            guard let key = scenicKey(.punchSpotId) else { return }
            defaults.set(newValue, forKey: key)
        }
    }

    /// 已保存打卡点名称。
    var punchSpotName: String {
        get { spotString(for: .punchSpotName) }
        set { setSpotString(newValue, for: .punchSpotName) }
    }

    /// 自定义播报文案。
    var remark: String {
        get { spotString(for: .remark) }
        set { setSpotString(newValue, for: .remark) }
    }

    /// 是否优先使用离线 TTS。
    var useOfflineTTS: Bool {
        get {
            guard let key = scenicKey(.useOfflineTTS),
                  defaults.object(forKey: key) != nil else { return true }
            return defaults.bool(forKey: key)
        }
        set {
            guard let key = scenicKey(.useOfflineTTS) else { return }
            defaults.set(newValue, forKey: key)
        }
    }

    /// 当前账号是否已经保存有效打卡点。
    func hasPunchSpotSaved() -> Bool {
        let id = punchSpotId.trimmingCharacters(in: .whitespacesAndNewlines)
        return Int64(id).map { $0 > 0 } ?? false
    }

    /// 保存排队设置快照。
    func saveSettingsSnapshot(_ snapshot: ScenicQueueSettingsSnapshot) {
        guard let key = spotKey(.settingsSnapshot),
              let data = try? JSONEncoder().encode(snapshot) else { return }
        defaults.set(data, forKey: key)
    }

    /// 读取排队设置快照。
    func settingsSnapshot() -> ScenicQueueSettingsSnapshot? {
        guard let key = spotKey(.settingsSnapshot),
              let data = defaults.data(forKey: key) else { return nil }
        return try? JSONDecoder().decode(ScenicQueueSettingsSnapshot.self, from: data)
    }

    /// 保存排队预设播报文案，最多 5 条。
    func savePresetVoices(_ voices: [String]) {
        guard let key = spotKey(.presetVoices) else { return }
        let normalized = voices
            .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
            .filter { !$0.isEmpty }
            .prefix(5)
        defaults.set(Array(normalized), forKey: key)
    }

    /// 读取排队预设播报文案。
    func presetVoices() -> [String] {
        guard let key = spotKey(.presetVoices) else { return [] }
        return defaults.stringArray(forKey: key) ?? []
    }

    /// 清除当前账号的景区排队缓存。
    func clear(accountScope: String) {
        guard !accountScope.isEmpty else { return }
        let scenicPrefix = "\(accountScope)_scenic_"
        let suffixes = Key.allCases.map { "_\($0.rawValue)" }
        defaults.dictionaryRepresentation().keys
            .filter { key in
                key.hasPrefix(scenicPrefix) && suffixes.contains(where: key.hasSuffix)
            }
            .forEach { defaults.removeObject(forKey: $0) }
    }

    private func scenicKey(_ key: Key) -> String? {
        session.scenicScopedKey(key.rawValue)
    }

    private func spotKey(_ key: Key) -> String? {
        session.scenicSpotScopedKey(key.rawValue, spotId: punchSpotId)
    }

    private func spotString(for key: Key) -> String {
        guard let scopedKey = spotKey(key) else { return "" }
        return defaults.string(forKey: scopedKey) ?? ""
    }

    private func setSpotString(_ value: String, for key: Key) {
        guard let scopedKey = spotKey(key) else { return }
        defaults.set(value, forKey: scopedKey)
    }
}
