import Foundation

// MARK: - App Group bridge (extension side)
//
// KEEP IN SYNC with PortfolioJournal/Utilities/SharedQuickUpdate.swift — same
// UserDefaults suite, same keys, same JSON shapes. Duplicated here so the
// extension stays self-contained (no Core Data, no app-target sources).

struct ExtSourceInfo: Codable, Identifiable {
    let id: UUID
    let name: String
    let latestValue: Double
    let currencyCode: String
    var updatedThisMonth: Bool
}

struct ExtPendingUpdate: Codable {
    let sourceId: UUID
    let amount: Double
    let capturedAt: Date
}

enum ExtSharedStore {
    static let appGroupIdentifier = "group.com.alexandrevazquez.portfoliojournal"
    private static let mirrorKey = "sharedSourceMirror"
    private static let queueKey = "pendingQuickUpdates"

    private static var defaults: UserDefaults? {
        UserDefaults(suiteName: appGroupIdentifier)
    }

    static func readMirror() -> [ExtSourceInfo] {
        guard let data = defaults?.data(forKey: mirrorKey),
              let decoded = try? JSONDecoder().decode([ExtSourceInfo].self, from: data) else { return [] }
        return decoded
    }

    static func appendPending(_ update: ExtPendingUpdate) {
        var queue: [ExtPendingUpdate] = []
        if let data = defaults?.data(forKey: queueKey),
           let decoded = try? JSONDecoder().decode([ExtPendingUpdate].self, from: data) {
            queue = decoded
        }
        queue.append(update)
        if let data = try? JSONEncoder().encode(queue) {
            defaults?.set(data, forKey: queueKey)
        }
        // Mark the source as updated so the next share preselects the following one.
        var mirror = readMirror()
        if let idx = mirror.firstIndex(where: { $0.id == update.sourceId }) {
            mirror[idx].updatedThisMonth = true
            if let data = try? JSONEncoder().encode(mirror) {
                defaults?.set(data, forKey: mirrorKey)
            }
        }
    }
}

// MARK: - Amount parsing (locale-tolerant)

enum ExtAmountParser {
    /// Parses strings like "12.345,67 €", "$1,234.56", "1234,5" into a Decimal.
    static func parse(_ raw: String) -> Decimal? {
        // Strip everything except digits and separators.
        let cleaned = raw.filter { $0.isNumber || $0 == "." || $0 == "," }
        guard !cleaned.isEmpty else { return nil }

        let lastDot = cleaned.lastIndex(of: ".")
        let lastComma = cleaned.lastIndex(of: ",")

        var normalized = cleaned
        switch (lastDot, lastComma) {
        case let (dot?, comma?):
            // Both present: the LAST one is the decimal separator.
            if dot > comma {
                normalized = cleaned.replacingOccurrences(of: ",", with: "")
            } else {
                normalized = cleaned.replacingOccurrences(of: ".", with: "")
                    .replacingOccurrences(of: ",", with: ".")
            }
        case (nil, let comma?):
            // Only commas: decimal if the trailing group isn't exactly 3 digits.
            let trailing = cleaned.distance(from: cleaned.index(after: comma), to: cleaned.endIndex)
            if trailing == 3 && cleaned.filter({ $0 == "," }).count > 0 && cleaned.count > 4 {
                normalized = cleaned.replacingOccurrences(of: ",", with: "")
            } else {
                normalized = cleaned.replacingOccurrences(of: ",", with: ".")
            }
        case (let dot?, nil):
            // Only dots: decimal if the trailing group isn't exactly 3 digits.
            let trailing = cleaned.distance(from: cleaned.index(after: dot), to: cleaned.endIndex)
            if trailing == 3 && cleaned.filter({ $0 == "." }).count > 1 {
                normalized = cleaned.replacingOccurrences(of: ".", with: "")
            }
        case (nil, nil):
            break
        }

        guard let value = Decimal(string: normalized, locale: Locale(identifier: "en_US_POSIX")),
              value > 0 else { return nil }
        return value
    }
}
