// FontStore.swift
// Observable store that tracks the active terminal font and point size, and
// persists both values across launches via UserDefaults.

import Foundation
import UIKit
import Combine

private let kFontIdKey   = "terminal.font"
private let kFontSizeKey = "terminal.fontSize"
private let kDefaultSize: CGFloat = 11

@MainActor
public final class FontStore: ObservableObject {

    // MARK: Singleton

    public static let shared = FontStore()

    // MARK: Published state

    @Published public private(set) var current: TerminalFont
    @Published public private(set) var size: CGFloat

    // MARK: Available fonts (ordered: default first)

    public let available: [TerminalFont] = [.sfMono, .menlo, .jetBrainsMono]

    // MARK: Init

    private init() {
        // Restore point size (clamped to a sane range).
        // If stored value is the old default (13pt), migrate to new default (11pt).
        let storedSize = UserDefaults.standard.object(forKey: kFontSizeKey) as? CGFloat
        if storedSize == 13 { UserDefaults.standard.removeObject(forKey: kFontSizeKey) }
        let effectiveStored = storedSize == 13 ? nil : storedSize
        size = effectiveStored.map { max(8, min(32, $0)) } ?? kDefaultSize

        // Restore selected font id.
        let all: [TerminalFont] = [.sfMono, .menlo, .jetBrainsMono]
        if let savedId = UserDefaults.standard.string(forKey: kFontIdKey),
           let saved = all.first(where: { $0.id == savedId }) {
            current = saved
        } else {
            current = .sfMono
        }
    }

    // MARK: Public API

    /// Makes `font` the active font and persists the choice.
    public func select(_ font: TerminalFont) {
        current = font
        UserDefaults.standard.set(font.id, forKey: kFontIdKey)
    }

    /// Sets the point size (clamped to 8–32 pt) and persists it.
    public func setSize(_ newSize: CGFloat) {
        let clamped = max(8, min(32, newSize))
        size = clamped
        UserDefaults.standard.set(clamped, forKey: kFontSizeKey)
    }

    // MARK: Derived helpers

    /// Returns the current font scaled to the current point size.
    public var scaledFont: UIFont {
        current.uiFont.withSize(size)
    }
}
