//
//  DataControllerProtocol.swift
//  Reflect
//
//  Protocol defining the data access interface for mood entries.
//  Enables dependency injection and testability.
//

import Foundation
import SwiftData

// MARK: - Data Controller Protocol

/// Protocol defining read-only data access for mood entries
/// Used by widgets and other components that only need to read data
@MainActor
protocol MoodDataReading {
    /// Get a single entry for a specific date
    func getEntry(byDate date: Date) -> MoodEntryModel?

    /// Get entries within a date range, filtered by weekdays
    func getData(startDate: Date, endDate: Date, includedDays: [Int]) -> [MoodEntryModel]

    /// Get all data organized by year and month
    func splitIntoYearMonth(includedDays: [Int]) -> [Int: [Int: [MoodEntryModel]]]

    /// The earliest entry in the database
    var earliestEntry: MoodEntryModel? { get }

    /// The latest entry in the database
    var latestEntry: MoodEntryModel? { get }
}

/// Protocol defining write operations for mood entries
@MainActor
protocol MoodDataWriting {
    /// Add a new mood entry
    func add(mood: Mood, forDate date: Date, entryType: EntryType)

    /// Update the mood for an existing entry
    @discardableResult
    func update(entryDate: Date, withMood mood: Mood) -> Bool

    /// Update notes for an entry
    @discardableResult
    func updateNotes(forDate date: Date, notes: String?) -> Bool

    /// Update photo for an entry
    @discardableResult
    func updatePhoto(forDate date: Date, photoID: UUID?) -> Bool

    /// Fill in missing dates with placeholder entries
    func fillInMissingDates()

    /// Fix incorrect weekday values
    func fixWrongWeekdays()
}

/// Protocol for data deletion operations
@MainActor
protocol MoodDataDeleting {
    /// Clear all entries from the database
    func clearDB()

    /// Delete entries from the last N days
    func deleteLast(numberOfEntries: Int)
}

/// Protocol for persistence operations
@MainActor
protocol MoodDataPersisting {
    /// Save pending changes
    @discardableResult
    func save() -> Bool

    /// Save and notify listeners
    @discardableResult
    func saveAndRunDataListeners() -> Bool

    /// Add a listener for data changes, returns a token for removal
    @discardableResult
    func addNewDataListener(closure: @escaping (() -> Void)) -> DataController.DataListenerToken

    /// Remove a previously registered data listener
    func removeDataListener(token: DataController.DataListenerToken)
}

/// Combined protocol for full data controller functionality
@MainActor
protocol DataControlling: MoodDataReading, MoodDataWriting, MoodDataDeleting, MoodDataPersisting {}

// MARK: - DataController Conformance

extension DataController: DataControlling {}
