//
//  Activity.swift
//  lichunWebsocket
//
//  Activity-related models
//

import Foundation
import Combine

// MARK: - Activity Protocol
protocol ActivityProtocol {
    var id: String { get }
    var title: String { get }
    var image: String { get }
    var type: String { get }
}

// MARK: - Job Level
struct jobLevel: Identifiable, Decodable {
    let id: String
    let level: String
    let salary: Int
    let energy_modifier: Int
}

// MARK: - Activity Record
class ActivityRecord: ObservableObject {
    @Published var id: String
    @Published var type: String
    @Published var location: String
    @Published var dateStarted: Date
    @Published var achievements: [String]
    @Published var focus: String
    @Published var level: jobLevel?
    @Published var performance: Int

    init(id: String, type: String, location: String, dateStarted: Date, focus: String, level: jobLevel?, performance: Int) {
        self.id = id
        self.type = type
        self.location = location
        self.dateStarted = dateStarted
        self.focus = focus
        self.achievements = []
        self.level = level
        self.performance = performance
    }

    func addAchievement(_ achievement: String) {
        achievements.append(achievement)
    }
}

// MARK: - Education Record
class EducationRecord: ActivityRecord {
    @Published var educationLevel: String
    @Published var major: String?
    @Published var minor: String?
    @Published var GPA: Double

    init(id: String, educationLevel: String, location: String, dateStarted: Date, focus: String, GPA: Double, level: jobLevel?, performance: Int) {
        self.educationLevel = educationLevel
        self.major = nil
        self.minor = nil
        self.GPA = GPA
        super.init(id: id, type: "education", location: location, dateStarted: dateStarted, focus: focus, level: level, performance: performance)
    }

    func updateGPA(_ GPA: Double) {
        self.GPA = GPA
    }
}

// MARK: - Activity Types
struct ElementarySchoolClass: ActivityProtocol {
    let id: String
    let title: String
    let image: String
    let type: String
    let description: String
}

struct HighSchoolClass: ActivityProtocol {
    let id: String
    let title: String
    let image: String
    let type: String
    let description: String
}

struct OccupationClass: ActivityProtocol, Decodable {
    let id: String
    let title: String
    let image: String
    let type: String
    let requirements: String
    let description: String
    let hourType: String
    let levels: [jobLevel]
}

struct ExtracurricularClass: ActivityProtocol, Decodable, Equatable {
    let id: String
    let title: String
    let image: String
    let type: String
    let description: String
}

// MARK: - Habit
struct Habit: Decodable, Hashable {
    var name: String
    var description: String
    var type: String
    var habitType: String
    var status: String
    var quitProgress: Int

    enum CodingKeys: String, CodingKey {
        case name
        case description
        case type
        case habitType
        case status
        case quitProgress
        case daysQuit
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)

        name = try values.decode(String.self, forKey: .name)
        description = try values.decode(String.self, forKey: .description)
        type = try values.decode(String.self, forKey: .type)
        habitType = try values.decode(String.self, forKey: .habitType)
        status = try values.decode(String.self, forKey: .status)
        quitProgress = (try? values.decode(Int.self, forKey: .quitProgress))
            ?? (try? values.decode(Int.self, forKey: .daysQuit))
            ?? 0
    }
}
