import {
    SyncedBook,
    SyncedChapter,
    SyncedChapterContent,
    SyncedChapterInfo,
    SyncedCharacter,
    SyncedCharacterAttribute,
    SyncedLocation,
    SyncedLocationElement,
    SyncedLocationSubElement,
    SyncedWorld,
    SyncedWorldElement,
    SyncedIncident,
    SyncedPlotPoint,
    SyncedIssue,
    SyncedActSummary,
    SyncedGuideLine,
    SyncedAIGuideLine
} from "@/lib/models/SyncedBook";

/**
 * Résultat de comparaison pour un livre
 */
export interface BookSyncDiff {
    id: string;
    type: string;
    title: string;
    subTitle: string | null;
    bookNeedsUpdate: boolean; // Le livre lui-même a changé
    lastUpdate: number;
    chapters: SyncedChapter[];
    characters: SyncedCharacter[];
    locations: SyncedLocation[];
    worlds: SyncedWorld[];
    incidents: SyncedIncident[];
    plotPoints: SyncedPlotPoint[];
    issues: SyncedIssue[];
    actSummaries: SyncedActSummary[];
    guideLine: SyncedGuideLine | null;
    aiGuideLine: SyncedAIGuideLine | null;
    hasAnyChanges: boolean; // Indique si des changements existent
}

/**
 * Compare en profondeur deux livres synchronisés et retourne les différences
 */
export function compareBooks(serverBook: SyncedBook, localBook: SyncedBook): BookSyncDiff {
    const bookNeedsUpdate = serverBook.lastUpdate > localBook.lastUpdate;

    // Comparer les chapitres
    const chaptersWithChanges: SyncedChapter[] = [];
    for (const serverChapter of serverBook.chapters) {
        const localChapter = localBook.chapters.find(c => c.id === serverChapter.id);

        if (!localChapter) {
            // Chapitre n'existe pas localement
            chaptersWithChanges.push(serverChapter);
        } else if (serverChapter.lastUpdate > localChapter.lastUpdate) {
            // Chapitre a changé
            chaptersWithChanges.push(serverChapter);
        } else {
            // Vérifier les contenus du chapitre
            const contentsWithChanges: SyncedChapterContent[] = [];
            for (const serverContent of serverChapter.contents) {
                const localContent = localChapter.contents.find(c => c.id === serverContent.id);
                if (!localContent || serverContent.lastUpdate > localContent.lastUpdate) {
                    contentsWithChanges.push(serverContent);
                }
            }

            // Vérifier l'info du chapitre
            let infoNeedsUpdate = false;
            if (serverChapter.info && localChapter.info) {
                infoNeedsUpdate = serverChapter.info.lastUpdate > localChapter.info.lastUpdate;
            } else if (serverChapter.info && !localChapter.info) {
                infoNeedsUpdate = true;
            }

            // Si des contenus ou info ont changé, inclure le chapitre
            if (contentsWithChanges.length > 0 || infoNeedsUpdate) {
                chaptersWithChanges.push({
                    ...serverChapter,
                    contents: contentsWithChanges.length > 0 ? contentsWithChanges : serverChapter.contents,
                    info: infoNeedsUpdate ? serverChapter.info : null
                });
            }
        }
    }

    // Comparer les personnages
    const charactersWithChanges: SyncedCharacter[] = [];
    for (const serverChar of serverBook.characters) {
        const localChar = localBook.characters.find(c => c.id === serverChar.id);

        if (!localChar) {
            charactersWithChanges.push(serverChar);
        } else if (serverChar.lastUpdate > localChar.lastUpdate) {
            charactersWithChanges.push(serverChar);
        } else {
            // Vérifier les attributs
            const attributesWithChanges: SyncedCharacterAttribute[] = [];
            for (const serverAttr of serverChar.attributes) {
                const localAttr = localChar.attributes.find(a => a.id === serverAttr.id);
                if (!localAttr || serverAttr.lastUpdate > localAttr.lastUpdate) {
                    attributesWithChanges.push(serverAttr);
                }
            }

            if (attributesWithChanges.length > 0) {
                charactersWithChanges.push({
                    ...serverChar,
                    attributes: attributesWithChanges
                });
            }
        }
    }

    // Comparer les locations
    const locationsWithChanges: SyncedLocation[] = [];
    for (const serverLoc of serverBook.locations) {
        const localLoc = localBook.locations.find(l => l.id === serverLoc.id);

        if (!localLoc) {
            locationsWithChanges.push(serverLoc);
        } else if (serverLoc.lastUpdate > localLoc.lastUpdate) {
            locationsWithChanges.push(serverLoc);
        } else {
            // Vérifier les éléments
            const elementsWithChanges: SyncedLocationElement[] = [];
            for (const serverElem of serverLoc.elements) {
                const localElem = localLoc.elements.find(e => e.id === serverElem.id);

                if (!localElem) {
                    elementsWithChanges.push(serverElem);
                } else if (serverElem.lastUpdate > localElem.lastUpdate) {
                    elementsWithChanges.push(serverElem);
                } else {
                    // Vérifier les sous-éléments
                    const subElementsWithChanges: SyncedLocationSubElement[] = [];
                    for (const serverSubElem of serverElem.subElements) {
                        const localSubElem = localElem.subElements.find(s => s.id === serverSubElem.id);
                        if (!localSubElem || serverSubElem.lastUpdate > localSubElem.lastUpdate) {
                            subElementsWithChanges.push(serverSubElem);
                        }
                    }

                    if (subElementsWithChanges.length > 0) {
                        elementsWithChanges.push({
                            ...serverElem,
                            subElements: subElementsWithChanges
                        });
                    }
                }
            }

            if (elementsWithChanges.length > 0) {
                locationsWithChanges.push({
                    ...serverLoc,
                    elements: elementsWithChanges
                });
            }
        }
    }

    // Comparer les mondes
    const worldsWithChanges: SyncedWorld[] = [];
    for (const serverWorld of serverBook.worlds) {
        const localWorld = localBook.worlds.find(w => w.id === serverWorld.id);

        if (!localWorld) {
            worldsWithChanges.push(serverWorld);
        } else if (serverWorld.lastUpdate > localWorld.lastUpdate) {
            worldsWithChanges.push(serverWorld);
        } else {
            // Vérifier les éléments du monde
            const elementsWithChanges: SyncedWorldElement[] = [];
            for (const serverElem of serverWorld.elements) {
                const localElem = localWorld.elements.find(e => e.id === serverElem.id);
                if (!localElem || serverElem.lastUpdate > localElem.lastUpdate) {
                    elementsWithChanges.push(serverElem);
                }
            }

            if (elementsWithChanges.length > 0) {
                worldsWithChanges.push({
                    ...serverWorld,
                    elements: elementsWithChanges
                });
            }
        }
    }

    // Comparer les incidents
    const incidentsWithChanges: SyncedIncident[] = [];
    for (const serverIncident of serverBook.incidents) {
        const localIncident = localBook.incidents.find(i => i.id === serverIncident.id);
        if (!localIncident || serverIncident.lastUpdate > localIncident.lastUpdate) {
            incidentsWithChanges.push(serverIncident);
        }
    }

    // Comparer les plot points
    const plotPointsWithChanges: SyncedPlotPoint[] = [];
    for (const serverPlot of serverBook.plotPoints) {
        const localPlot = localBook.plotPoints.find(p => p.id === serverPlot.id);
        if (!localPlot || serverPlot.lastUpdate > localPlot.lastUpdate) {
            plotPointsWithChanges.push(serverPlot);
        }
    }

    // Comparer les issues
    const issuesWithChanges: SyncedIssue[] = [];
    for (const serverIssue of serverBook.issues) {
        const localIssue = localBook.issues.find(i => i.id === serverIssue.id);
        if (!localIssue || serverIssue.lastUpdate > localIssue.lastUpdate) {
            issuesWithChanges.push(serverIssue);
        }
    }

    // Comparer les act summaries
    const actSummariesWithChanges: SyncedActSummary[] = [];
    for (const serverAct of serverBook.actSummaries) {
        const localAct = localBook.actSummaries.find(a => a.id === serverAct.id);
        if (!localAct || serverAct.lastUpdate > localAct.lastUpdate) {
            actSummariesWithChanges.push(serverAct);
        }
    }

    // Comparer guideline
    let guideLineNeedsUpdate: SyncedGuideLine | null = null;
    if (serverBook.guideLine && localBook.guideLine) {
        if (serverBook.guideLine.lastUpdate > localBook.guideLine.lastUpdate) {
            guideLineNeedsUpdate = serverBook.guideLine;
        }
    } else if (serverBook.guideLine && !localBook.guideLine) {
        guideLineNeedsUpdate = serverBook.guideLine;
    }

    // Comparer AI guideline
    let aiGuideLineNeedsUpdate: SyncedAIGuideLine | null = null;
    if (serverBook.aiGuideLine && localBook.aiGuideLine) {
        if (serverBook.aiGuideLine.lastUpdate > localBook.aiGuideLine.lastUpdate) {
            aiGuideLineNeedsUpdate = serverBook.aiGuideLine;
        }
    } else if (serverBook.aiGuideLine && !localBook.aiGuideLine) {
        aiGuideLineNeedsUpdate = serverBook.aiGuideLine;
    }

    // Déterminer s'il y a des changements
    const hasAnyChanges = bookNeedsUpdate ||
        chaptersWithChanges.length > 0 ||
        charactersWithChanges.length > 0 ||
        locationsWithChanges.length > 0 ||
        worldsWithChanges.length > 0 ||
        incidentsWithChanges.length > 0 ||
        plotPointsWithChanges.length > 0 ||
        issuesWithChanges.length > 0 ||
        actSummariesWithChanges.length > 0 ||
        guideLineNeedsUpdate !== null ||
        aiGuideLineNeedsUpdate !== null;

    return {
        id: serverBook.id,
        type: serverBook.type,
        title: serverBook.title,
        subTitle: serverBook.subTitle,
        bookNeedsUpdate,
        lastUpdate: serverBook.lastUpdate,
        chapters: chaptersWithChanges,
        characters: charactersWithChanges,
        locations: locationsWithChanges,
        worlds: worldsWithChanges,
        incidents: incidentsWithChanges,
        plotPoints: plotPointsWithChanges,
        issues: issuesWithChanges,
        actSummaries: actSummariesWithChanges,
        guideLine: guideLineNeedsUpdate,
        aiGuideLine: aiGuideLineNeedsUpdate,
        hasAnyChanges
    };
}

/**
 * Compare tous les livres serveur vs locaux et retourne ceux qui ont des changements
 */
export function getBooksToSyncFromServer(serverBooks: SyncedBook[], localBooks: SyncedBook[]): BookSyncDiff[] {
    const booksWithChanges: BookSyncDiff[] = [];

    for (const serverBook of serverBooks) {
        const localBook = localBooks.find(b => b.id === serverBook.id);

        if (!localBook) {
            // Livre n'existe pas localement - tout le livre doit être synchronisé
            booksWithChanges.push({
                id: serverBook.id,
                type: serverBook.type,
                title: serverBook.title,
                subTitle: serverBook.subTitle,
                bookNeedsUpdate: true,
                lastUpdate: serverBook.lastUpdate,
                chapters: serverBook.chapters,
                characters: serverBook.characters,
                locations: serverBook.locations,
                worlds: serverBook.worlds,
                incidents: serverBook.incidents,
                plotPoints: serverBook.plotPoints,
                issues: serverBook.issues,
                actSummaries: serverBook.actSummaries,
                guideLine: serverBook.guideLine,
                aiGuideLine: serverBook.aiGuideLine,
                hasAnyChanges: true
            });
        } else {
            // Comparer en profondeur
            const diff = compareBooks(serverBook, localBook);
            if (diff.hasAnyChanges) {
                booksWithChanges.push(diff);
            }
        }
    }

    return booksWithChanges;
}

/**
 * Compare tous les livres locaux vs serveur et retourne ceux qui ont des changements locaux
 */
export function getBooksToSyncToServer(localBooks: SyncedBook[], serverBooks: SyncedBook[]): BookSyncDiff[] {
    const booksWithChanges: BookSyncDiff[] = [];

    for (const localBook of localBooks) {
        const serverBook = serverBooks.find(b => b.id === localBook.id);

        if (!serverBook) {
            // Livre n'existe pas sur le serveur - tout le livre doit être envoyé
            booksWithChanges.push({
                id: localBook.id,
                type: localBook.type,
                title: localBook.title,
                subTitle: localBook.subTitle,
                bookNeedsUpdate: true,
                lastUpdate: localBook.lastUpdate,
                chapters: localBook.chapters,
                characters: localBook.characters,
                locations: localBook.locations,
                worlds: localBook.worlds,
                incidents: localBook.incidents,
                plotPoints: localBook.plotPoints,
                issues: localBook.issues,
                actSummaries: localBook.actSummaries,
                guideLine: localBook.guideLine,
                aiGuideLine: localBook.aiGuideLine,
                hasAnyChanges: true
            });
        } else {
            // Comparer en profondeur (local vs server)
            const diff = compareBooks(localBook, serverBook);
            if (diff.hasAnyChanges) {
                booksWithChanges.push(diff);
            }
        }
    }

    return booksWithChanges;
}
