/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core.model;

import static de.srsoftware.umbrella.core.constants.Field.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;

import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.json.JSONObject;

public final class Sender implements Mappable {
	private String name;
	private String bankAccount;
	private String taxNumber;
	private String court;
	private final Set<String> dirtyFields = new HashSet<>();

	public Sender(String name, String bankAccount, String taxNumber, String court) {
		this.name = name;
		this.bankAccount = bankAccount;
		this.taxNumber = taxNumber;
		this.court = court;
	}

	public String bankAccount() {
		return bankAccount;
	}

	public void clean() {
		dirtyFields.clear();
	}

	public String court() {
		return court;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == this) return true;
		if (obj == null || obj.getClass() != this.getClass()) return false;
		var that = (Sender) obj;
		return Objects.equals(this.name, that.name) &&
				Objects.equals(this.bankAccount, that.bankAccount) &&
				Objects.equals(this.taxNumber, that.taxNumber) &&
				Objects.equals(this.court, that.court);
	}

	@Override
	public int hashCode() {
		return Objects.hash(name, bankAccount, taxNumber, court);
	}

	public boolean isDirty() {
		return !dirtyFields.isEmpty();
	}


	public String name() {
		return name;
	}

	public static Sender of(JSONObject json) throws UmbrellaException {
		if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingField(NAME);
		if (!json.has(BANK_ACCOUNT) || !(json.get(BANK_ACCOUNT) instanceof String bankAccount)) throw missingField(BANK_ACCOUNT);
		if (!json.has(TAX_ID) || !(json.get(TAX_ID) instanceof String taxId)) throw missingField(TAX_ID);
		if (!json.has(COURT) || !(json.get(COURT) instanceof String court)) throw missingField(COURT);
		return new Sender(name,bankAccount,taxId,court);
	}

	public void patch(JSONObject json) {
		for (var key : json.keySet()){
			switch (key){
				case BANK_ACCOUNT: bankAccount = json.getString(key); break;
				case NAME: 		   name = json.getString(key); break;
				case COURT:        court = json.getString(key); break;
				case TAX_ID:       taxNumber = json.getString(key); break;
				default: key = null;
			}
			if (key != null) dirtyFields.add(key);
		}
	}

	public String taxNumber() {
		return taxNumber;
	}

	@Override
	public Map<String, Object> toMap() {
		return Map.of(
				BANK_ACCOUNT, bankAccount,
				COURT, court,
				NAME, name,
				TAX_ID, taxNumber
		);
	}

	@Override
	public String toString() {
		return "Sender[" +
				"name=" + name + ", " +
				"bankAccount=" + bankAccount + ", " +
				"taxNumber=" + taxNumber + ", " +
				"court=" + court + ']';
	}

}
