import SwiftUI
import SwiftData

@MainActor
final class DishViewModel: ObservableObject {
    @Published var name: String = ""
    @Published var descriptionText: String = ""
    @Published var selectedTagIds: Set<UUID> = []
    @Published var showTagSelector: Bool = false
    @Published var showDeleteAlert: Bool = false
    @Published var showAssignedDeleteAlert: Bool = false

    var editingDish: Dish?

    var isEditing: Bool { editingDish != nil }

    var isValid: Bool {
        !name.trimmingCharacters(in: .whitespaces).isEmpty
    }

    func loadDish(_ dish: Dish) {
        editingDish = dish
        name = dish.name
        descriptionText = dish.descriptionText ?? ""
        selectedTagIds = Set(dish.tagIds)
    }

    func reset() {
        editingDish = nil
        name = ""
        descriptionText = ""
        selectedTagIds = []
    }

    func save(context: ModelContext) {
        let trimmedName = name.trimmingCharacters(in: .whitespaces)
        guard !trimmedName.isEmpty else { return }

        if let dish = editingDish {
            dish.name = trimmedName
            dish.descriptionText = descriptionText.isEmpty ? nil : descriptionText
            dish.tagIds = Array(selectedTagIds)
        } else {
            let dish = Dish(
                name: trimmedName,
                descriptionText: descriptionText.isEmpty ? nil : descriptionText,
                tagIds: Array(selectedTagIds)
            )
            context.insert(dish)
        }

        try? context.save()
        reset()
    }

    func deleteDish(context: ModelContext) -> Bool {
        guard let dish = editingDish else { return false }

        if isDishAssignedInCurrentWeek(dishId: dish.id, context: context) {
            showAssignedDeleteAlert = true
            return false
        }

        context.delete(dish)
        try? context.save()
        reset()
        return true
    }

    func canDelete(currentPlan: WeekPlan?) -> Bool {
        guard let dish = editingDish, let plan = currentPlan else { return true }
        return !plan.slots.contains { $0.dishId == dish.id }
    }

    private func isDishAssignedInCurrentWeek(dishId: UUID, context: ModelContext) -> Bool {
        let currentWeekStart = Date().startOfWeek()
        let descriptor = FetchDescriptor<WeekPlan>(
            predicate: #Predicate<WeekPlan> { plan in
                plan.weekStartDate == currentWeekStart
            }
        )

        guard let currentPlan = try? context.fetch(descriptor).first else {
            return false
        }

        return currentPlan.slots.contains { $0.dishId == dishId }
    }
}
