import { ipcMain } from 'electron';
import { createHandler } from '../database/LocalSystem.js';
import Book, {BookSyncCompare, CompleteBook, SyncedBook} from '../database/models/Book.js';
import type { BookProps, GuideLine, GuideLineAI, Act, Issue, WorldProps } from '../database/models/Book.js';
import Chapter from '../database/models/Chapter.js';
import type { ChapterProps } from '../database/models/Chapter.js';

interface UpdateBookBasicData {
    title: string;
    subTitle: string;
    summary: string;
    publicationDate: string;
    wordCount: number;
    bookId: string;
}

interface UpdateGuideLineData {
    bookId: string;
    tone: string | null;
    atmosphere: string | null;
    writingStyle: string | null;
    themes: string | null;
    symbolism: string | null;
    motifs: string | null;
    narrativeVoice: string | null;
    pacing: string | null;
    keyMessages: string | null;
    intendedAudience: string | null;
}

interface StoryData {
    acts: Act[];
    issues: Issue[];
    mainChapter: ChapterProps[];
}

interface UpdateStoryData {
    bookId: string;
    acts: Act[];
    mainChapters: ChapterProps[];
}

interface CreateBookData {
    title: string;
    subTitle: string | null;
    summary: string | null;
    type: string;
    serieId: number | null;
    desiredReleaseDate: string | null;
    desiredWordCount: number | null;
}

interface AddIncidentData {
    bookId: string;
    name: string;
}

interface AddPlotPointData {
    bookId: string;
    name: string;
    incidentId: string;
}

interface AddIssueData {
    bookId: string;
    name: string;
}

interface AddWorldData {
    bookId: string;
    worldName: string;
}

interface AddWorldElementData {
    worldId: string;
    elementName: string;
    elementType: number;
}

interface SetAIGuideLineData {
    bookId: string;
    narrativeType: number;
    dialogueType: number;
    plotSummary: string;
    toneAtmosphere: string;
    verbTense: number;
    language: number;
    themes: string;
}

interface GetGuidelineData {
    id: string;
}

// GET /books - Get all books
ipcMain.handle('db:book:books', createHandler<void, BookProps[]>(
        async function(userId: string, _body: void, lang: 'fr' | 'en'):Promise<BookProps[]> {
            return await Book.getBooks(userId, lang);
        }
    )
);

// GET /books/synced - Get all synced books
ipcMain.handle('db:books:synced', createHandler<void, SyncedBook[]>(
        async function(userId: string, _body: void, lang: 'fr' | 'en'):Promise<SyncedBook[]> {
            return await Book.getSyncedBooks(userId, lang);
        })
);

// POST /book/sync/save - Save complete book
ipcMain.handle('db:book:syncSave', createHandler<CompleteBook, boolean>(
        async function(userId: string, data: CompleteBook, lang: 'fr' | 'en'):Promise<boolean> {
            return await Book.saveCompleteBook(userId, data, lang);
        })
);

// GET /book/:id - Get single book
ipcMain.handle('db:book:bookBasicInformation', createHandler<string, BookProps>(
        async function(userId: string, bookId: string, lang: 'fr' | 'en'):Promise<BookProps> {
            return await Book.getBook(userId, bookId);
        }
    )
);

// POST /book/basic-information - Update book basic info
ipcMain.handle('db:book:updateBasicInformation', createHandler<UpdateBookBasicData, boolean>(
        function(userId: string, data: UpdateBookBasicData, lang: 'fr' | 'en') {
            return Book.updateBookBasicInformation(userId, data.title, data.subTitle, data.summary, data.publicationDate, data.wordCount, data.bookId, lang);
        }
    )
);

// GET /book/sync/to-client - Get book data to sync to client
ipcMain.handle('db:book:sync:toServer', createHandler<BookSyncCompare, CompleteBook>(
        async function(userId: string, data:BookSyncCompare, lang: 'fr' | 'en'):Promise<CompleteBook> {
            return await Book.getCompleteSyncBook(userId, data, lang);
        }
    )
);

// GET /book/sync/from-server - Get book data to sync from server
ipcMain.handle('db:book:sync:toClient', createHandler<CompleteBook, boolean>(
        async function(userId: string, data:CompleteBook,  lang: 'fr' | 'en'):Promise<boolean> {
            return await Book.syncBookFromServerToClient(userId, data, lang);
        }
    )
);

// GET /book/guide-line - Get guideline
ipcMain.handle('db:book:guideline:get',
    createHandler<GetGuidelineData, GuideLine | null>(async function(userId: string, data: GetGuidelineData, lang: 'fr' | 'en') {
            return await Book.getGuideLine(userId, data.id, lang);
        }
    )
);

// POST /book/guide-line - Update guideline
ipcMain.handle('db:book:guideline:update', createHandler<UpdateGuideLineData, boolean>(
        async function(userId: string, data: UpdateGuideLineData, lang: 'fr' | 'en') {
            return await Book.updateGuideLine(
                userId,
                data.bookId,
                data.tone,
                data.atmosphere,
                data.writingStyle,
                data.themes,
                data.symbolism,
                data.motifs,
                data.narrativeVoice,
                data.pacing,
                data.keyMessages,
                data.intendedAudience,
                lang
            );
        }
    )
);

// GET /book/story - Get story data (acts + issues + mainChapter)
interface GetStoryData {
    bookid: string;
}
ipcMain.handle('db:book:story:get', createHandler<GetStoryData, StoryData>(
        async function(userId: string, data: GetStoryData, lang: 'fr' | 'en'):Promise<StoryData> {
            const acts:Act[] = await Book.getActsData(userId, data.bookid, lang);
            const issues:Issue[] = await Book.getIssuesFromBook(userId, data.bookid, lang);
            const mainChapter:ChapterProps[] = Chapter.getAllChaptersFromABook(userId, data.bookid, lang);
            return {
                acts,
                issues,
                mainChapter
            };
        }
    )
);

// POST /book/story - Update story (acts + mainChapters)
ipcMain.handle('db:book:story:update', createHandler<UpdateStoryData, boolean>(
        function(userId: string, data: UpdateStoryData, lang: 'fr' | 'en'):boolean {
            return Book.updateStory(userId, data.bookId, data.acts, data.mainChapters, lang);
        }
    )
);

// POST /book/add - Create new book
ipcMain.handle('db:book:create', createHandler<CreateBookData, string>(
        function(userId: string, data: CreateBookData, lang: 'fr' | 'en') {
            return Book.addBook(
                null,
                userId,
                data.title,
                data.subTitle || '',
                data.summary || '',
                data.type,
                data.serieId || 0,
                data.desiredReleaseDate || '',
                data.desiredWordCount || 0,
                lang
            );
        }
    )
);


// POST /book/incident/new - Add incident
ipcMain.handle(
    'db:book:incident:add',
    createHandler<AddIncidentData, string>(
        function(userId: string, data: AddIncidentData, lang: 'fr' | 'en') {
            return Book.addNewIncident(userId, data.bookId, data.name, lang);
        }
    )
);

// DELETE /book/incident/remove - Remove incident
interface RemoveIncidentData {
    bookId: string;
    incidentId: string;
}

ipcMain.handle('db:book:incident:remove', createHandler<RemoveIncidentData, boolean>(
        function(userId: string, data: RemoveIncidentData, lang: 'fr' | 'en') {
            return Book.removeIncident(userId, data.bookId, data.incidentId, lang);
        }
    )
);

// POST /book/plot/new - Add plot point
ipcMain.handle('db:book:plot:add', createHandler<AddPlotPointData, string>(
        function(userId: string, data: AddPlotPointData, lang: 'fr' | 'en') {
            return Book.addNewPlotPoint(
                userId,
                data.bookId,
                data.incidentId,
                data.name,
                lang
            );
        }
    )
);

// DELETE /book/plot/remove - Remove plot point
interface RemovePlotData {
    plotId: string;
}
ipcMain.handle(
    'db:book:plot:remove',
    createHandler<RemovePlotData, boolean>(
        function(userId: string, data: RemovePlotData, lang: 'fr' | 'en') {
            return Book.removePlotPoint(userId, data.plotId, lang);
        }
    )
);

// POST /book/issue/add - Add issue
ipcMain.handle('db:book:issue:add', createHandler<AddIssueData, string>(
        function(userId: string, data: AddIssueData, lang: 'fr' | 'en') {
            return Book.addNewIssue(userId, data.bookId, data.name, lang);
        }
    )
);

// DELETE /book/issue/remove - Remove issue
interface RemoveIssueData {
    bookId: string;
    issueId: string;
}
ipcMain.handle('db:book:issue:remove', createHandler<RemoveIssueData, boolean>(
        function(userId: string, data: RemoveIssueData, lang: 'fr' | 'en') {
            return Book.removeIssue(userId, data.issueId, lang);
        }
    )
);

// GET /book/worlds - Get worlds for book
interface GetWorldsData {
    bookid: string;
}
ipcMain.handle('db:book:worlds:get', createHandler<GetWorldsData, WorldProps[]>(
        function(userId: string, data: GetWorldsData, lang: 'fr' | 'en') {
            return Book.getWorlds(userId, data.bookid, lang);
        }
    )
);

// POST /book/world/add - Add world
ipcMain.handle('db:book:world:add', createHandler<AddWorldData, string>(
        function(userId: string, data: AddWorldData, lang: 'fr' | 'en') {
            return Book.addNewWorld(userId, data.bookId, data.worldName, lang);
        }
    )
);

// POST /book/world/element/add - Add element to world
ipcMain.handle('db:book:world:element:add', createHandler<AddWorldElementData, string>(
        function(userId: string, data: AddWorldElementData, lang: 'fr' | 'en') {
            return Book.addNewElementToWorld(
                userId,
                data.worldId,
                data.elementName,
                data.elementType.toString(),
                lang
            );
        }
    )
);
// DELETE /book/world/element/delete - Remove element from world
interface RemoveWorldElementData {
    elementId: string;
}
ipcMain.handle('db:book:world:element:remove', createHandler<RemoveWorldElementData, boolean>(
        function(userId: string, data: RemoveWorldElementData, lang: 'fr' | 'en') {
            return Book.removeElementFromWorld(userId, data.elementId, lang);
        }
    )
);

// DELETE /book/delete - Delete book
interface DeleteBookData {
    id: string;
}
ipcMain.handle('db:book:delete', createHandler<DeleteBookData, boolean>(
        function(userId: string, data: DeleteBookData, lang: 'fr' | 'en') {
            return Book.removeBook(userId, data.id, lang);
        }
    )
);

// GET /book/ai/guideline - Get AI guideline
interface GetAIGuidelineData {
    id: string;
}
ipcMain.handle('db:book:guideline:ai:get', createHandler<GetAIGuidelineData, GuideLineAI>(
        function(userId: string, data: GetAIGuidelineData, lang: 'fr' | 'en') {
            return Book.getGuideLineAI(userId, data.id, lang);
        }
    )
);

// POST /book/ai/guideline (set) - Set AI guideline
ipcMain.handle('db:book:guideline:ai:set', createHandler<SetAIGuideLineData, boolean>(
        function(userId: string, data: SetAIGuideLineData, lang: 'fr' | 'en') {
            return Book.setAIGuideLine(
                userId,
                data.bookId,
                data.narrativeType,
                data.dialogueType,
                data.plotSummary,
                data.toneAtmosphere,
                data.verbTense,
                data.language,
                data.themes,
                lang
            );
        }
    )
);

// PUT /book/world/update - Update world
interface UpdateWorldData {
    bookId: string;
    world: WorldProps;
}

ipcMain.handle('db:book:world:update', createHandler<UpdateWorldData, boolean>(
        function(userId: string, data: UpdateWorldData, lang: 'fr' | 'en') {
            return Book.updateWorld(userId, data.world, lang);
        }
    )
);
