# ==============================================================================
# Fortress Chat - client engine (libfchatcore.a) + CLI harness + tests
# ==============================================================================
# Mirrors apps/common/Makefile: knows where the repo headers and the user-local
# libsodium headers/libs live. Picked up automatically by the root `make apps`
# / `make apps-test` (which build build/lib/libfortress.a first).
# ==============================================================================

CC := gcc
AR := ar

ROOT_DIR    := ../..
INCLUDE_DIR := $(ROOT_DIR)/include
COMMON_DIR  := ../common
LOCAL_INC   := $(HOME)/.local/include
LOCAL_LIB   := $(HOME)/.local/lib

BUILD_DIR := build
OBJ_DIR   := $(BUILD_DIR)/obj
BIN_DIR   := $(BUILD_DIR)/bin
CORE_LIB  := $(BUILD_DIR)/libfchatcore.a

FORTRESS_LIB := $(ROOT_DIR)/build/lib/libfortress.a
FCCOMMON_LIB := $(COMMON_DIR)/build/libfccommon.a

CFLAGS := -std=c11
CFLAGS += -I core -I $(COMMON_DIR) -I $(COMMON_DIR)/tests -I $(INCLUDE_DIR) -I $(LOCAL_INC)
CFLAGS += -Wall -Wextra -Werror -O2
CFLAGS += -fstack-protector-strong -D_FORTIFY_SOURCE=2
CFLAGS += $(EXTRA_CFLAGS)

LDFLAGS := -L $(LOCAL_LIB) $(EXTRA_LDFLAGS)
LIBS    := -lsodium -lpthread -lcrypto -lm -lz

CORE_SOURCES := core/fchat.c core/fchat_store.c
CORE_OBJECTS := $(patsubst core/%.c,$(OBJ_DIR)/%.o,$(CORE_SOURCES))

ALL_LIBS := $(CORE_LIB) $(FCCOMMON_LIB) $(FORTRESS_LIB)

CLI_BIN   := $(BIN_DIR)/fortress-chat-cli

# --- TUI (fortress-chat, the ncurses client) --------------------------------
# Wide ncurses headers/libs live under the user-local prefix (already on the
# include/lib search paths via LOCAL_INC/LOCAL_LIB). setlocale + -lncursesw give
# UTF-8-correct rendering.
TUI_BIN        := $(BIN_DIR)/fortress-chat
TUI_MODEL_OBJ  := $(OBJ_DIR)/tui_model.o
TUI_OBJ        := $(OBJ_DIR)/tui.o
TUI_TEST_BIN   := $(BIN_DIR)/tui_test
NCURSES_LIBS   := -lncursesw

TEST_NAMES := test_crypto test_persist test_net test_features
TEST_BINS  := $(patsubst %,$(BIN_DIR)/%,$(TEST_NAMES))
MOCK_OBJ   := $(OBJ_DIR)/mock_server.o

.PHONY: all clean test dirs common

all: dirs common $(CORE_LIB) $(CLI_BIN) $(TUI_BIN)

dirs:
	@mkdir -p $(OBJ_DIR) $(BIN_DIR)

# Ensure the shared common library exists (idempotent; also lets this Makefile
# build standalone via `make -C apps/client`).
common:
	@$(MAKE) -C $(COMMON_DIR) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" EXTRA_LDFLAGS="$(EXTRA_LDFLAGS)"

$(CORE_LIB): $(CORE_OBJECTS)
	@echo "[AR] $@"
	@$(AR) rcs $@ $^

$(OBJ_DIR)/%.o: core/%.c
	@echo "[CC] $<"
	@$(CC) $(CFLAGS) -c -o $@ $<

$(OBJ_DIR)/mock_server.o: tests/mock_server.c
	@echo "[CC] $<"
	@$(CC) $(CFLAGS) -c -o $@ $<

$(CLI_BIN): cli/main.c $(ALL_LIBS)
	@echo "[LD] $@"
	@$(CC) $(CFLAGS) -o $@ cli/main.c $(ALL_LIBS) $(LDFLAGS) $(LIBS)

# TUI objects (add -I tui for tui_model.h)
$(TUI_MODEL_OBJ): tui/tui_model.c tui/tui_model.h
	@echo "[CC] $<"
	@$(CC) $(CFLAGS) -I tui -c -o $@ $<

$(TUI_OBJ): tui/tui.c tui/tui_model.h
	@echo "[CC] $<"
	@$(CC) $(CFLAGS) -I tui -c -o $@ $<

$(TUI_BIN): $(TUI_OBJ) $(TUI_MODEL_OBJ) $(ALL_LIBS)
	@echo "[LD] $@"
	@$(CC) $(CFLAGS) -o $@ $(TUI_OBJ) $(TUI_MODEL_OBJ) $(ALL_LIBS) \
		$(LDFLAGS) $(NCURSES_LIBS) $(LIBS)

# TUI model unit test (pure logic, no curses/engine)
$(TUI_TEST_BIN): tui/tui_test.c $(TUI_MODEL_OBJ)
	@echo "[LD] test $@"
	@$(CC) $(CFLAGS) -I tui -o $@ tui/tui_test.c $(TUI_MODEL_OBJ) $(LDFLAGS)

$(BIN_DIR)/%: tests/%.c $(MOCK_OBJ) $(ALL_LIBS)
	@echo "[LD] test $@"
	@$(CC) $(CFLAGS) -o $@ $< $(MOCK_OBJ) $(ALL_LIBS) $(LDFLAGS) $(LIBS)

test: all $(TEST_BINS) $(TUI_TEST_BIN)
	@echo "Running fchat client tests..."
	@for t in $(TEST_BINS) $(TUI_TEST_BIN); do \
		echo "=== $$t ==="; \
		$$t || exit 1; \
	done
	@echo "All fchat client tests passed!"

clean:
	@rm -rf $(BUILD_DIR)
