import Foundation

public struct TransferSchedule: Codable, Equatable {
    public var period: TransferPeriod?
    public var waitPeriod: String?
    public var fullPeriodRequired: Bool?
    public var dayOfWeek: Int?
    public var weekOfMonth: Int?
    public var dayOfMonth: Int?
    public var weeklyClosingDay: Int?
    public var weeklyPayoutDay: Int?
}

public enum TransferPeriod: String, Codable {
    case weekly = "weekly"
    case biweekly = "biweekly"
    case monthly = "monthly"
    case semiMonthly = "semi_monthly"
}

public enum TransferStatus: String, Codable {
    case created
    case approved
    case processing
    case paid
    case cancelled
    case failed
}

public struct Transfer: BaseModel {
    public var id: String
    public var bankAccountId: String
    public var amount: Int
    public var currency: String
    public var amountFormatted: Double
    public var status: TransferStatus
    public var errorCode: String?
    public var errorText: String?
    public var metadata: Metadata
    public var note: String?
    public var createdOn: Date
    public var from: String
    public var to: String

    enum CodingKeys: String, CodingKey {
        case id
        case bankAccountId
        case amount
        case currency
        case amountFormatted
        case status
        case errorCode
        case errorText
        case note
        case createdOn
        case from
        case to
    }

    public init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decode(String.self, forKey: .id)
        bankAccountId = try values.decode(String.self, forKey: .bankAccountId)
        amount = try values.decode(Int.self, forKey: .amount)
        currency = try values.decode(String.self, forKey: .currency)
        amountFormatted = try values.decode(Double.self, forKey: .amountFormatted)
        status = try values.decode(TransferStatus.self, forKey: .status)
        errorCode = try values.decodeIfPresent(String.self, forKey: .errorCode)
        errorText = try values.decodeIfPresent(String.self, forKey: .errorText)
        note = try values.decodeIfPresent(String.self, forKey: .note)
        createdOn = try values.decode(Date.self, forKey: .createdOn)
        from = try values.decode(String.self, forKey: .from)
        to = try values.decode(String.self, forKey: .to)

        let literalValues = try decoder.container(keyedBy: UnivapayCodingKey.self)
        let metadataKey = UnivapayCodingKey.makeKey(forName: "metadata", literalKeyNames: true)
        metadata = try literalValues.decode(Metadata.self, forKey: metadataKey)
    }
}
