"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrelloProvider = TrelloProvider;
exports.useTrello = useTrello;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
// Helper to normalize any API card response into our TrelloCard type
function toTrelloCard(c) {
    var _a;
    return {
        id: c.id,
        name: c.name,
        desc: c.desc || "",
        due: (_a = c.due) !== null && _a !== void 0 ? _a : null,
        closed: c.closed,
        url: c.url || "",
        shortLink: c.shortLink || "",
        idList: c.idList || "",
        idBoard: c.idBoard || "",
        idMembers: c.idMembers || [],
        labels: (c.labels || []).map((l) => ({
            id: l.id,
            name: l.name,
            color: l.color,
            idBoard: l.idBoard,
        })),
    };
}
function trelloReducer(state, action) {
    switch (action.type) {
        case "SET_BOARDS":
            return { ...state, boards: action.boards };
        case "SET_CURRENT_BOARD":
            return { ...state, currentBoard: action.board };
        case "SET_LISTS":
            return { ...state, lists: action.lists };
        case "SET_CARDS":
            return {
                ...state,
                cardsByList: { ...state.cardsByList, [action.listId]: action.cards },
            };
        case "SET_ALL_CARDS":
            return { ...state, cardsByList: action.cardsByList };
        case "ADD_CARD": {
            const existing = state.cardsByList[action.listId] || [];
            return {
                ...state,
                cardsByList: {
                    ...state.cardsByList,
                    [action.listId]: [...existing, action.card],
                },
            };
        }
        case "REMOVE_CARD": {
            const existing = state.cardsByList[action.listId] || [];
            return {
                ...state,
                cardsByList: {
                    ...state.cardsByList,
                    [action.listId]: existing.filter((c) => c.id !== action.cardId),
                },
            };
        }
        case "UPDATE_CARD": {
            const listId = action.card.idList;
            const existing = state.cardsByList[listId] || [];
            return {
                ...state,
                cardsByList: {
                    ...state.cardsByList,
                    [listId]: existing.map((c) => c.id === action.card.id ? action.card : c),
                },
            };
        }
        case "MOVE_CARD": {
            const fromCards = (state.cardsByList[action.fromListId] || []).filter((c) => c.id !== action.cardId);
            const toCards = [
                ...(state.cardsByList[action.toListId] || []),
                action.card,
            ];
            return {
                ...state,
                cardsByList: {
                    ...state.cardsByList,
                    [action.fromListId]: fromCards,
                    [action.toListId]: toCards,
                },
            };
        }
        case "ADD_LIST":
            return { ...state, lists: [...state.lists, action.list], cardsByList: { ...state.cardsByList, [action.list.id]: [] } };
        case "SET_MEMBERS":
            return { ...state, members: action.members };
        case "SET_BOARD_LABELS":
            return { ...state, boardLabels: action.labels };
        case "SET_LOADING":
            return { ...state, loading: action.loading };
        case "SET_ERROR":
            return { ...state, error: action.error };
        case "SET_SYNCED":
            return { ...state, lastSynced: new Date() };
        default:
            return state;
    }
}
const initialState = {
    boards: [],
    currentBoard: null,
    lists: [],
    cardsByList: {},
    boardLabels: [],
    members: [],
    loading: false,
    error: null,
    lastSynced: null,
};
const TrelloContext = (0, react_1.createContext)(null);
function TrelloProvider({ children, client, cache, }) {
    const [state, dispatch] = (0, react_1.useReducer)(trelloReducer, initialState);
    const loadBoards = (0, react_1.useCallback)(async () => {
        dispatch({ type: "SET_LOADING", loading: true });
        dispatch({ type: "SET_ERROR", error: null });
        try {
            const boards = await client.members.getMemberBoards({
                id: "me",
                filter: "open",
            });
            dispatch({
                type: "SET_BOARDS",
                boards: boards.map((b) => ({
                    id: b.id,
                    name: b.name,
                    desc: b.desc || "",
                    url: b.url,
                    shortLink: b.shortLink,
                    closed: b.closed,
                })),
            });
        }
        catch (e) {
            dispatch({ type: "SET_ERROR", error: e.message || "Failed to load boards" });
        }
        finally {
            dispatch({ type: "SET_LOADING", loading: false });
        }
    }, [client]);
    const loadBoard = (0, react_1.useCallback)(async (board) => {
        dispatch({ type: "SET_LOADING", loading: true });
        dispatch({ type: "SET_ERROR", error: null });
        dispatch({ type: "SET_CURRENT_BOARD", board });
        try {
            const lists = await client.boards.getBoardLists({
                id: board.id,
                filter: "open",
            });
            const trelloLists = lists.map((l) => ({
                id: l.id,
                name: l.name,
                closed: l.closed,
                idBoard: l.idBoard,
            }));
            dispatch({ type: "SET_LISTS", lists: trelloLists });
            // Load cards for all lists in parallel
            const cardsByList = {};
            await Promise.all(trelloLists.map(async (list) => {
                const cards = await client.lists.getListCards({ id: list.id });
                cardsByList[list.id] = cards.map(toTrelloCard);
            }));
            dispatch({ type: "SET_ALL_CARDS", cardsByList });
            // Load members
            const members = await client.boards.getBoardMembers({ id: board.id });
            dispatch({
                type: "SET_MEMBERS",
                members: members.map((m) => ({
                    id: m.id,
                    username: m.username,
                    fullName: m.fullName,
                    initials: m.initials || "",
                })),
            });
            // Load board labels
            const labels = await client.boards.getBoardLabels({ id: board.id });
            dispatch({
                type: "SET_BOARD_LABELS",
                labels: labels.map((l) => ({
                    id: l.id,
                    name: l.name || "",
                    color: l.color || "",
                    idBoard: l.idBoard || board.id,
                })),
            });
        }
        catch (e) {
            dispatch({
                type: "SET_ERROR",
                error: e.message || "Failed to load board",
            });
        }
        finally {
            dispatch({ type: "SET_LOADING", loading: false });
        }
    }, [client]);
    const createCard = (0, react_1.useCallback)(async (listId, name, opts) => {
        const card = await client.cards.createCard({
            idList: listId,
            name,
            desc: opts === null || opts === void 0 ? void 0 : opts.desc,
            due: opts === null || opts === void 0 ? void 0 : opts.due,
            pos: ((opts === null || opts === void 0 ? void 0 : opts.position) || "bottom"),
        });
        const trelloCard = toTrelloCard(card);
        dispatch({ type: "ADD_CARD", listId, card: trelloCard });
        return trelloCard;
    }, [client]);
    const createList = (0, react_1.useCallback)(async (name) => {
        if (!state.currentBoard) {
            throw new Error("No board selected");
        }
        const list = await client.lists.createList({
            name,
            idBoard: state.currentBoard.id,
            pos: "bottom",
        });
        const trelloList = {
            id: list.id,
            name: list.name,
            closed: list.closed,
            idBoard: list.idBoard,
        };
        dispatch({ type: "ADD_LIST", list: trelloList });
        return trelloList;
    }, [client, state.currentBoard]);
    const moveCard = (0, react_1.useCallback)(async (cardId, fromListId, toListId) => {
        const updated = await client.cards.updateCard({
            id: cardId,
            idList: toListId,
        });
        const card = toTrelloCard(updated);
        dispatch({ type: "MOVE_CARD", cardId, fromListId, toListId, card });
    }, [client]);
    const archiveCard = (0, react_1.useCallback)(async (cardId, listId) => {
        await client.cards.updateCard({ id: cardId, closed: true });
        dispatch({ type: "REMOVE_CARD", listId, cardId });
    }, [client]);
    const deleteCard = (0, react_1.useCallback)(async (cardId, listId) => {
        await client.cards.deleteCard({ id: cardId });
        dispatch({ type: "REMOVE_CARD", listId, cardId });
    }, [client]);
    const updateCard = (0, react_1.useCallback)(async (cardId, updates) => {
        const updated = await client.cards.updateCard({
            id: cardId,
            ...updates,
        });
        const card = toTrelloCard(updated);
        dispatch({ type: "UPDATE_CARD", card });
        return card;
    }, [client]);
    const addLabelToCard = (0, react_1.useCallback)(async (cardId, labelId) => {
        await client.cards.addCardLabel({ id: cardId, value: labelId });
        // Re-fetch card to get updated labels
        const updated = await client.cards.getCard({ id: cardId });
        const card = toTrelloCard(updated);
        dispatch({ type: "UPDATE_CARD", card });
    }, [client]);
    const removeLabelFromCard = (0, react_1.useCallback)(async (cardId, labelId) => {
        await client.cards.deleteCardLabel({ id: cardId, idLabel: labelId });
        // Re-fetch card to get updated labels
        const updated = await client.cards.getCard({ id: cardId });
        const card = toTrelloCard(updated);
        dispatch({ type: "UPDATE_CARD", card });
    }, [client]);
    const addMemberToCard = (0, react_1.useCallback)(async (cardId, memberId) => {
        await client.cards.addCardMember({ id: cardId, value: memberId });
        // Re-fetch card to get updated members
        const updated = await client.cards.getCard({ id: cardId });
        const card = toTrelloCard(updated);
        dispatch({ type: "UPDATE_CARD", card });
    }, [client]);
    const removeMemberFromCard = (0, react_1.useCallback)(async (cardId, memberId) => {
        await client.cards.deleteCardMember({ id: cardId, idMember: memberId });
        // Re-fetch card to get updated members
        const updated = await client.cards.getCard({ id: cardId });
        const card = toTrelloCard(updated);
        dispatch({ type: "UPDATE_CARD", card });
    }, [client]);
    // Helper to re-fetch card with checklists and attachments, then update state
    const refetchCardDetails = (0, react_1.useCallback)(async (cardId) => {
        const [card, checklists, attachments] = await Promise.all([
            client.cards.getCard({ id: cardId }),
            client.cards.getCardChecklists({ id: cardId }),
            client.cards.getCardAttachments({ id: cardId }),
        ]);
        const trelloCard = toTrelloCard(card);
        trelloCard.checklists = checklists.map((cl) => ({
            id: cl.id,
            name: cl.name,
            idCard: cl.idCard,
            pos: cl.pos,
            checkItems: (cl.checkItems || []).map((ci) => ({
                id: ci.id,
                name: ci.name,
                state: ci.state,
                pos: ci.pos,
                idChecklist: ci.idChecklist,
            })),
        }));
        trelloCard.attachments = attachments.map((att) => {
            var _a;
            return ({
                id: att.id,
                name: att.name,
                url: att.url,
                date: att.date,
                mimeType: att.mimeType || "",
                bytes: (_a = att.bytes) !== null && _a !== void 0 ? _a : null,
                isUpload: att.isUpload || false,
                fileName: att.fileName || null,
            });
        });
        dispatch({ type: "UPDATE_CARD", card: trelloCard });
    }, [client]);
    const loadCardDetails = (0, react_1.useCallback)(async (cardId) => {
        await refetchCardDetails(cardId);
    }, [refetchCardDetails]);
    const createChecklist = (0, react_1.useCallback)(async (cardId, name) => {
        await client.cards.createCardChecklist({ id: cardId, name });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const deleteChecklist = (0, react_1.useCallback)(async (cardId, checklistId) => {
        await client.cards.deleteCardChecklist({ id: cardId, idChecklist: checklistId });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const createCheckItem = (0, react_1.useCallback)(async (checklistId, name, cardId) => {
        await client.checklists.createChecklistCheckItems({ id: checklistId, name });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const deleteCheckItem = (0, react_1.useCallback)(async (cardId, checkItemId) => {
        await client.cards.deleteCardChecklistItem({ id: cardId, idCheckItem: checkItemId });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const toggleCheckItem = (0, react_1.useCallback)(async (cardId, checkItemId, currentState) => {
        const newState = currentState === "complete" ? "incomplete" : "complete";
        await client.cards.updateCardCheckItem({
            id: cardId,
            idCheckItem: checkItemId,
            state: newState,
        });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const addAttachment = (0, react_1.useCallback)(async (cardId, url, name) => {
        await client.cards.createCardAttachment({ id: cardId, url, name });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const deleteAttachment = (0, react_1.useCallback)(async (cardId, attachmentId) => {
        await client.cards.deleteCardAttachment({ id: cardId, idAttachment: attachmentId });
        await refetchCardDetails(cardId);
    }, [client, refetchCardDetails]);
    const syncCache = (0, react_1.useCallback)(async () => {
        dispatch({ type: "SET_LOADING", loading: true });
        try {
            await cache.bootstrap();
            await cache.sync();
            dispatch({ type: "SET_SYNCED" });
        }
        catch (e) {
            dispatch({ type: "SET_ERROR", error: e.message || "Sync failed" });
        }
        finally {
            dispatch({ type: "SET_LOADING", loading: false });
        }
    }, [cache]);
    const loadAssignedCards = (0, react_1.useCallback)(async () => {
        const cards = await client.members.getMemberCards({ id: "me" });
        return cards.map(toTrelloCard);
    }, [client]);
    const value = {
        state,
        dispatch,
        client,
        cache,
        loadBoards,
        loadBoard,
        createCard,
        createList,
        moveCard,
        archiveCard,
        deleteCard,
        updateCard,
        addLabelToCard,
        removeLabelFromCard,
        addMemberToCard,
        removeMemberFromCard,
        loadCardDetails,
        createChecklist,
        deleteChecklist,
        createCheckItem,
        deleteCheckItem,
        toggleCheckItem,
        addAttachment,
        deleteAttachment,
        syncCache,
        loadAssignedCards,
    };
    return ((0, jsx_runtime_1.jsx)(TrelloContext.Provider, { value: value, children: children }));
}
function useTrello() {
    const ctx = (0, react_1.useContext)(TrelloContext);
    if (!ctx) {
        throw new Error("useTrello must be used within TrelloProvider");
    }
    return ctx;
}
