import { createContext } from "preact";
import { useContext, useMemo, useReducer } from "preact/hooks";

import LLM from "../utils/llm";
import { useStoredReducer } from "@common/hooks/useStoredState";

// ─── Types ────────────────────────────────────────────────────────────────────

export interface ChatMessage {
    id: string;
    role: 'user' | 'assistant' | 'system';
    content: string;
}

export interface Story {
    id: string;
    title: string;
    text: string;
    chatMessages: ChatMessage[];
}

// ─── State ───────────────────────────────────────────────────────────────────

interface IState {
    stories: Story[];
    currentStoryId: string | null;
    connection: LLM.Connection | null;
    model: string | null;
}

// ─── Actions ─────────────────────────────────────────────────────────────────

type Action =
    | { type: 'CREATE_STORY'; title: string }
    | { type: 'RENAME_STORY'; id: string; title: string }
    | { type: 'EDIT_STORY'; id: string; text: string }
    | { type: 'DELETE_STORY'; id: string }
    | { type: 'SELECT_STORY'; id: string }
    | { type: 'ADD_CHAT_MESSAGE'; storyId: string; message: ChatMessage }
    | { type: 'CLEAR_CHAT'; storyId: string }
    | { type: 'SET_CONNECTION'; connection: LLM.Connection | null }
    | { type: 'SET_MODEL'; model: string | null };

// ─── Initial State ───────────────────────────────────────────────────────────

const DEFAULT_STATE: IState = {
    stories: [],
    currentStoryId: null,
    connection: null,
    model: null,
};

// ─── Reducer ─────────────────────────────────────────────────────────────────

function reducer(state: IState, action: Action): IState {
    switch (action.type) {
        case 'CREATE_STORY': {
            const story: Story = {
                id: crypto.randomUUID(),
                title: action.title,
                text: '',
                chatMessages: [],
            };
            return {
                ...state,
                stories: [...state.stories, story],
                currentStoryId: story.id,
            };
        }
        case 'RENAME_STORY': {
            return {
                ...state,
                stories: state.stories.map(s =>
                    s.id === action.id ? { ...s, title: action.title } : s
                ),
            };
        }
        case 'EDIT_STORY': {
            return {
                ...state,
                stories: state.stories.map(s =>
                    s.id === action.id ? { ...s, text: action.text } : s
                ),
            };
        }
        case 'DELETE_STORY': {
            const remaining = state.stories.filter(s => s.id !== action.id);
            const deletingCurrent = state.currentStoryId === action.id;
            return {
                ...state,
                stories: remaining,
                currentStoryId: deletingCurrent ? null : state.currentStoryId,
            };
        }
        case 'SELECT_STORY': {
            return {
                ...state,
                currentStoryId: action.id,
            };
        }
        case 'ADD_CHAT_MESSAGE': {
            return {
                ...state,
                stories: state.stories.map(s => {
                    if (s.id !== action.storyId) return s;
                    const existingIndex = s.chatMessages.findIndex(m => m.id === action.message.id);
                    if (existingIndex !== -1) {
                        // Overwrite existing message with same id
                        const updatedMessages = [...s.chatMessages];
                        updatedMessages[existingIndex] = action.message;
                        return { ...s, chatMessages: updatedMessages };
                    }
                    // Append new message
                    return { ...s, chatMessages: [...s.chatMessages, action.message] };
                }),
            };
        }
        case 'CLEAR_CHAT': {
            return {
                ...state,
                stories: state.stories.map(s =>
                    s.id === action.storyId ? { ...s, chatMessages: [] } : s
                ),
            };
        }
        case 'SET_CONNECTION': {
            return {
                ...state,
                connection: action.connection,
            };
        }
        case 'SET_MODEL': {
            return {
                ...state,
                model: action.model,
            };
        }
    }
}

// ─── Context ─────────────────────────────────────────────────────────────────

export interface AppState {
    stories: Story[];
    currentStory: Story | null;
    connection: LLM.Connection | null;
    model: string | null;
    dispatch: (action: Action) => void;
}

const StateContext = createContext<AppState>({} as AppState);

export const useAppState = () => useContext(StateContext);

// ─── Provider ────────────────────────────────────────────────────────────────

export const StateContextProvider = ({ children }: { children?: any }) => {
    const [state, dispatch] = useStoredReducer('storywriter.state', reducer, DEFAULT_STATE);

    const value = useMemo<AppState>(() => ({
        stories: state.stories,
        currentStory: state.stories.find(s => s.id === state.currentStoryId) ?? null,
        connection: state.connection,
        model: state.model,
        dispatch,
    }), [state]);

    return (
        <StateContext.Provider value={value}>
            {children}
        </StateContext.Provider>
    );
};
