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

import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
import static de.srsoftware.umbrella.core.constants.Constants.CLASS;
import static de.srsoftware.umbrella.core.constants.Field.*;
import static de.srsoftware.umbrella.core.constants.Path.MENU;
import static de.srsoftware.umbrella.core.constants.Text.*;
import static de.srsoftware.umbrella.core.constants.Text.USERS;
import static java.text.MessageFormat.format;

import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Mappable;
import de.srsoftware.tools.Path;
import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.constants.Module;
import de.srsoftware.umbrella.core.constants.Text;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.io.IOException;
import java.util.*;
import org.json.JSONObject;

public class SettingsService extends BaseHandler {

	private final Configuration config;

	public SettingsService(Configuration config) {
		this.config = config;
	}

	@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 MENU -> getMenuSettings(user.get(), ex);
				case null, default -> super.doGet(path, ex);
			};
		} catch (UmbrellaException e) {
			return send(ex, e);
		}
	}

	private record MenuEntry(int pos, String module, String clazz, String title) implements Mappable {
		public static MenuEntry of(int pos, String module){
			return new MenuEntry(pos, module, module, module);
		}

		public static MenuEntry of(int pos, String module, String title){
			return new MenuEntry(pos,module,module,title);
		}
		public static MenuEntry of(int pos, String module, String clazz, String title){
			return new MenuEntry(pos,module,clazz,title);
		}

		@Override
		public Map<String, Object> toMap() {
			return Map.of(MODULE,module,CLASS,clazz,TITLE,title);
		}
	}
	private boolean getMenuSettings(UmbrellaUser user, HttpExchange ex) throws IOException {
		Optional<JSONObject> modules = config.get("umbrella.modules");
		if (modules.isEmpty()) throw UmbrellaException.missingConfig("umbrella.modules");

		var entries = new ArrayList<MenuEntry>();
		entries.add(MenuEntry.of(1, Module.USER, USERS));
		entries.add(MenuEntry.of(2, Module.COMPANY, COMPANIES));
		entries.add(MenuEntry.of(3, Module.PROJECT,Text.PROJECTS));
		entries.add(MenuEntry.of(4,Module.TASK,Text.TASKS));
		entries.add(MenuEntry.of(5,Module.TAGS));
		entries.add(MenuEntry.of(6,Module.DOCUMENT,"doc",Text.DOCUMENTS));
		entries.add(MenuEntry.of(7,Module.BOOKMARK,"mark",BOOKMARKS));
		entries.add(MenuEntry.of(8,Module.NOTES,"note",Text.NOTES));
		entries.add(MenuEntry.of(9,Module.FILES,"file", FILES));
		entries.add(MenuEntry.of(10,Module.TIME, Text.TIMETRACKING));
		entries.add(MenuEntry.of(11,Module.WIKI));
		entries.add(MenuEntry.of(12,Module.CONTACT, CONTACTS));
		entries.add(MenuEntry.of(13,Module.STOCK));
		entries.add(MenuEntry.of(14,Module.MESSAGE, MESSAGES));
		entries.add(MenuEntry.of(15,Module.POLL,Text.POLLS));
		entries.add(MenuEntry.of(16,Module.ACCOUNTING,Text.ACCOUNTING));

		for (var i=0; i<entries.size(); i++){
			var entry = entries.get(i);
			var key = format("umbrella.modules.{0}.menuIndex",entry.module);
			Optional<Integer> val = config.get(key);
			if (val.isEmpty()) {
				key = format("umbrella.modules.{0}.menu_index",entry.module);
				val = config.get(key);
			}
			if (val.isPresent()) {
				var index = val.get();
				if (index<0) {
					entries.remove(i);
					i--;
					continue;
				} else {
					entry = MenuEntry.of(index,entry.module,entry.clazz,entry.title);
					entries.set(i,entry);
				}
			}
			key = format("umbrella.modules.{0}.baseUrl",entry.module);
			Optional<String> baseUrl = config.get(key);
			if (baseUrl.isPresent()) {
				entry = MenuEntry.of(entry.pos,baseUrl.get(), entry.clazz,entry.title);
				entries.set(i,entry);
			}
		}
		var list = entries.stream().sorted((a,b) -> a.pos - b.pos)
				.map(MenuEntry::toMap).toList();
		return sendContent(ex,list);
	}
}