/* © SRSoftware 2025 */
package de.srsoftware.umbrella.contact;

import static de.srsoftware.umbrella.contact.Constants.CONFIG_DATABASE;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
import static de.srsoftware.umbrella.core.Util.mapValues;
import static de.srsoftware.umbrella.core.constants.Path.LIST;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingField;

import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Path;
import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.ModuleRegistry;
import de.srsoftware.umbrella.core.api.ContactService;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Contact;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;

public class ContactModule extends BaseHandler implements ContactService {
	private final ContactDb contactDb;

	public ContactModule(Configuration config) throws UmbrellaException {
		super();
		var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE));
		contactDb = new SqliteDb(connect(dbFile));
		ModuleRegistry.add(this);
	}

	private boolean deleteContact(long id, UmbrellaUser user, HttpExchange ex) throws IOException {
		var contact = contactDb.load(id, user.id());
		contactDb.drop(contact);
		return sendEmptyResponse(200,ex);
	}

	@Override
	public boolean doDelete(Path path, HttpExchange ex) throws IOException {
		addCors(ex);
		try {
			var user = userService().refreshSession(ex);
			if (user.isEmpty()) return unauthorized(ex);
			var head = path.pop();
			try {
				var id = Long.parseLong(head);
				return deleteContact(id, user.get(), ex);
			} catch (Exception ignored){
				return super.doPatch(path,ex);
			}
		} catch (UmbrellaException e) {
			return send(ex,e);
		}
	}

	@Override
	public boolean doGet(Path path, HttpExchange ex) throws IOException {
		addCors(ex);
		try {
			Optional<Token> token = SessionToken.from(ex).map(Token::of);
			var user = userService().loadUser(token);
			if (user.isEmpty()) return unauthorized(ex);
			var head = path.pop();
			return switch (head) {
				case LIST -> getContacts(user.get(),ex);
				case null, default -> super.doGet(path, ex);
			};
		} catch (UmbrellaException e) {
			return send(ex,e);
		}
	}

	@Override
	public boolean doPatch(Path path, HttpExchange ex) throws IOException {
		addCors(ex);
		try {
			var user = userService().refreshSession(ex);
			if (user.isEmpty()) return unauthorized(ex);
			var head = path.pop();
			try {
				var id = Long.parseLong(head);
				return patchContact(id, user.get(), ex);
			} catch (Exception ignored){
				return super.doPatch(path,ex);
			}
		} catch (UmbrellaException e) {
			return send(ex,e);
		}
	}

	@Override
	public boolean doPost(Path path, HttpExchange ex) throws IOException {
		addCors(ex);
		try {
			Optional<Token> token = SessionToken.from(ex).map(Token::of);
			var user = userService().loadUser(token);
			if (user.isEmpty()) return unauthorized(ex);
			var head = path.pop();
			if (head == null) {
				return postNewContact(user.get(),ex);
			}
			return super.doPatch(path,ex);
		} catch (UmbrellaException e) {
			return send(ex,e);
		}
	}


	private boolean getContacts(UmbrellaUser user, HttpExchange ex) throws IOException {
		return sendContent(ex,mapValues(listContactsOf(user)));
	}

	@Override
	public Contact load(long userId, long contactId) {
		return contactDb.load(contactId,userId);
	}

	@Override
	public Map<Long,Contact> listContactsOf(UmbrellaUser user) throws UmbrellaException {
		return contactDb.listContactsOf(user.id());
	}

	private boolean patchContact(long id, UmbrellaUser user, HttpExchange ex) throws IOException {
		var contact = contactDb.load(id, user.id()).patch(json(ex));
		return sendContent(ex,contactDb.save(contact));
	}

	private boolean postNewContact(UmbrellaUser user, HttpExchange ex) throws IOException {
		var contact = new Contact(0,body(ex));
		contact = contactDb.save(contact);
		contactDb.setOwner(user.id(),contact);
		return sendContent(ex,contact);
	}

	@Override
	public Contact save(Contact contact) {
		return contactDb.save(contact);
	}
}
