import Foundation

// MARK: - Auth

struct LoginRequest: Encodable {
    let email: String
    let password: String
}

struct LoginResponse: Decodable {
    let token: String
    let name: String
    let isPremium: Bool
}

struct UserProfile: Decodable {
    let id: Int
    let name: String
    let email: String
    let realName: String?
    let rolle: String?
    let isPremium: Bool?
    // Backend bool-konvertiert nur is_premium; is_founder/is_partner kommen
    // als SQLite-Int 0/1 zurück — deshalb hier Int? statt Bool?.
    let isFounder: Int?
    let isPartner: Int?
    let founderNumber: Int?
    let subscriptionTier: String?
    let avatarUrl: String?
    let wohnort: String?
    let bio: String?

    var isFounderFlag: Bool { isFounder == 1 }
    var isPartnerFlag: Bool { isPartner == 1 }
}

// MARK: - Dogs

struct Dog: Decodable, Identifiable {
    let id: Int
    let name: String
    let rasse: String?
    let fotoUrl: String?
    let geburtstag: String?
}

// MARK: - Routes

struct GPSPoint: Codable, Hashable {
    let lat: Double
    let lon: Double
    let alt: Double?
}

struct RouteListItem: Decodable, Identifiable {
    let id: Int
    let userId: Int
    let name: String
    let beschreibung: String?
    let distanzKm: Double?
    let dauerMin: Int?
    let createdAt: String?
    let previewTrack: [GPSPoint]
    let fotoUrls: [String]?
    let userName: String?
    let isPublic: Bool?
}

struct RouteDetail: Decodable, Identifiable {
    let id: Int
    let userId: Int
    let name: String
    let beschreibung: String?
    let distanzKm: Double?
    let dauerMin: Int?
    let gpsTrack: [GPSPoint]
    let fotoUrls: [String]?
    let createdAt: String?
    let userName: String?
    let dogIds: [Int]?
}

struct RouteCreateBody: Encodable {
    let name: String
    let gpsTrack: [GPSPoint]
    let distanzKm: Double
    let dauerMin: Int
    let dogIds: [Int]
    let isPublic: Bool
}

// MARK: - Expenses

struct Expense: Decodable, Identifiable {
    let id: Int
    let dogId: Int?
    let kategorie: String
    let betrag: Double
    let datum: String
    let notiz: String?
    let dogName: String?
}

struct ExpenseCreateBody: Encodable {
    let dogId: Int?
    let kategorie: String
    let betrag: Double
    let datum: String
    let notiz: String?
}

// MARK: - Gassi-Zeiten

struct GassiZeit: Decodable, Identifiable {
    let id: Int
    let dogId: Int?
    let wochentage: [String]
    let uhrzeit: String
    let ortName: String?
    let lat: Double?
    let lon: Double?
    let radiusM: Int?
    let notiz: String?
    let aktiv: Int?
    let distanceM: Int?
    let isMine: Bool?
    let userName: String?
    let dogName: String?
    let dogRasse: String?
}

struct GassiZeitCreateBody: Encodable {
    let dogId: Int?
    let wochentage: [String]
    let uhrzeit: String
    let ortName: String?
    let lat: Double?
    let lon: Double?
    let radiusM: Int
    let notiz: String?
}

// MARK: - Poison

struct PoisonAlert: Decodable, Identifiable {
    let id: Int
    let lat: Double
    let lon: Double
    let beschreibung: String?
    let typ: String?
    let distanzM: Int?
    let fotoUrl: String?
    let melderName: String?
    let createdAt: String?
}

struct PoisonCreateBody: Encodable {
    let lat: Double
    let lon: Double
    let beschreibung: String?
    let typ: String
}

// MARK: - Lost Dogs

struct LostDog: Decodable, Identifiable {
    let id: Int
    let name: String
    let rasse: String?
    let beschreibung: String
    let lat: Double
    let lon: Double
    let distanzM: Int?
    let fotoUrl: String?
    let melderName: String?
    let createdAt: String?
}

struct LostDogCreateBody: Encodable {
    let name: String
    let rasse: String?
    let beschreibung: String
    let lat: Double
    let lon: Double
    let dogId: Int?
}

// MARK: - Weather

struct WeatherForecast: Decodable {
    let days: [WeatherDay]
}

struct WeatherDay: Decodable, Identifiable {
    let date: String
    let wday: String?
    let weathercode: Int?
    let desc: String?
    let icon: String?
    let tempMax: Double?
    let tempMin: Double?
    let precipProb: Int?
    let precipSum: Double?
    let windKmh: Double?
    let uvIndex: Double?
    let sunrise: String?
    let sunset: String?
    let asphaltTemp: Double?
    let zecken: String?

    var id: String { date }
}

/// Patch body for PATCH /api/routes/{id}. Only non-nil fields are encoded.
struct RouteUpdateBody: Encodable {
    var name: String?
    var beschreibung: String?
    var isPublic: Bool?

    enum CodingKeys: String, CodingKey {
        case name
        case beschreibung
        case isPublic
    }

    func encode(to encoder: Encoder) throws {
        var c = encoder.container(keyedBy: CodingKeys.self)
        try c.encodeIfPresent(name, forKey: .name)
        try c.encodeIfPresent(beschreibung, forKey: .beschreibung)
        try c.encodeIfPresent(isPublic, forKey: .isPublic)
    }
}
