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

import static de.srsoftware.tools.Optionals.emptyIfNull;
import static de.srsoftware.umbrella.core.constants.Constants.FALLBACK_LANG;
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.*;
import org.json.JSONObject;

public final class Customer implements Mappable {
	private String id;
	private String name;
	private String email;
	private String taxNumber;
	private String language;
	private final Set<String> dirtyFields = new HashSet<>();

	public Customer(String id, String name, String email, String taxNumber, String language) {
		this.id = id;
		this.name = name;
		this.email = email;
		this.taxNumber = taxNumber;
		this.language = language;
	}

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

	public String email() {
		return email;
	}

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

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

	public String id() {
		return id;
	}

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

	public String language(){
		return language;
	}

	public String name() {
		return name;
	}

	public static Customer of(JSONObject json) throws UmbrellaException {
		if (!json.has(ID) || !(json.get(ID) instanceof String id)) throw missingField(ID);
		if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingField(NAME);
		if (!json.has(EMAIL) || !(json.get(EMAIL) instanceof String email)) throw missingField(EMAIL);
		var taxId = json.has(TAX_ID) && json.get(TAX_ID) instanceof String tid ? tid : null;
		var lang = json.has(LANGUAGE) && json.get(LANGUAGE) instanceof String l ? l : FALLBACK_LANG;
		return new Customer(id,name,email,taxId,lang);
	}

	public void patch(JSONObject json) {
		for (var key : json.keySet()){
			switch (key){
				case ID:     id = json.getString(key); break;
				case NAME: name = json.getString(key); break;
				case EMAIL:   email = json.getString(key); break;
				case TAX_ID: taxNumber = json.getString(key); break;
				default: key = null;
			}
			if (key != null) dirtyFields.add(key);
		}
	}

	public String shortName(){
		var lines = name.split("\n");
		var result = lines[0];
		if (lines.length>1 && !lines[1].matches(".*\\d.*")) result += " "+lines[1];
		return result;
	}

	public String taxNumber() {
		return taxNumber;
	}

	@Override
	public Map<String, Object> toMap() {
		var map = new HashMap<String,Object>();
		map.put("id", id);
		map.put("name", name);
		map.put("email", email);
		map.put("tax_id", emptyIfNull(taxNumber));
		return map;
	}
}
