//
//  DataControllerADD.swift
//  Reflect
//
//  SwiftData CREATE operations.
//

import SwiftData
import Foundation
import os.log

private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.88oakapps.reflect", category: "DataControllerADD")

extension DataController {
    func add(mood: Mood, forDate date: Date, entryType: EntryType) {
        // Delete ALL existing entries for this date (handles duplicates)
        let existing = getAllEntries(byDate: date)
        for entry in existing {
            cleanupPhotoIfNeeded(for: entry)
            modelContext.delete(entry)
        }
        if !existing.isEmpty {
            do {
                try modelContext.save()
            } catch {
                logger.error("Failed to save after deleting existing entries: \(error.localizedDescription)")
            }
        }

        let entry = MoodEntryModel(
            forDate: date,
            mood: mood,
            entryType: entryType
        )

        modelContext.insert(entry)
        AnalyticsManager.shared.track(.moodLogged(mood: mood.rawValue, entryType: String(describing: entryType)))
        saveAndRunDataListeners()
    }

    func fillInMissingDates() {
        let currentOnboarding = UserDefaultsStore.getOnboarding()
        var endDate = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: currentOnboarding)
        // Since it's for views, take away the last date so vote is enabled
        guard let adjustedEndDate = Calendar.current.date(byAdding: .day, value: -1, to: endDate) else {
            logger.error("Failed to calculate adjusted end date")
            return
        }
        endDate = adjustedEndDate

        let descriptor = FetchDescriptor<MoodEntryModel>(
            sortBy: [SortDescriptor(\.forDate, order: .reverse)]
        )

        let entries: [MoodEntryModel]
        do {
            entries = try modelContext.fetch(descriptor)
        } catch {
            logger.error("Failed to fetch entries for fill-in: \(error.localizedDescription)")
            return
        }

        guard let firstEntry = entries.last else { return }

        let allDates: [Date] = Date.dates(from: firstEntry.forDate, toDate: endDate, includingToDate: true).compactMap {
            Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: $0)
        }

        let existingDates: Set<Date> = Set(entries.compactMap {
            Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: $0.forDate)
        })

        let missing = Array(Set(allDates).subtracting(existingDates)).sorted(by: >)

        guard !missing.isEmpty else { return }

        // Batch insert all missing dates without triggering listeners
        for date in missing {
            // Add 12 hours to avoid UTC offset issues
            guard let adjustedDate = Calendar.current.date(byAdding: .hour, value: 12, to: date) else {
                logger.error("Failed to calculate adjusted date for \(date)")
                continue
            }
            let entry = MoodEntryModel(
                forDate: adjustedDate,
                mood: .missing,
                entryType: .filledInMissing
            )
            modelContext.insert(entry)
        }

        // Single save and listener notification at the end
        saveAndRunDataListeners()
        AnalyticsManager.shared.track(.missingEntriesFilled(count: missing.count))
    }

    func fixWrongWeekdays() {
        let data = getData(startDate: Date(timeIntervalSince1970: 0), endDate: Date(), includedDays: [])
        for entry in data {
            entry.weekDay = Calendar.current.component(.weekday, from: entry.forDate)
        }
        saveAndRunDataListeners()
    }

    func removeNoForDates() {
        // Note: With SwiftData's non-optional forDate, this is essentially a no-op
        // Keeping for API compatibility
    }

    /// Batch insert mood entries without per-entry analytics or listener notifications.
    /// Used for CSV import where side effects should fire once at the end.
    func addBatch(entries: [(mood: Mood, date: Date, entryType: EntryType)]) {
        for (mood, date, entryType) in entries {
            let existing = getAllEntries(byDate: date)
            for entry in existing {
                cleanupPhotoIfNeeded(for: entry)
                modelContext.delete(entry)
            }
            let entry = MoodEntryModel(forDate: date, mood: mood, entryType: entryType)
            modelContext.insert(entry)
        }
        saveAndRunDataListeners()
    }
}
