// Client and world settings that back the Sites workflow.

import { ConnectionDatabaseService } from "../../features/connections/services/ConnectionDatabaseService.js";
import { SiteSceneVisibilityManager } from "../../features/site/services/SiteSceneVisibilityManager.js";
import { applyNexusAccentColor, DEFAULT_NEXUS_ACCENT } from "../appearance/NexusAppearance.js";

const MODULE_ID = "augur-nexus";

async function syncSitePlayerVisibility() {
    if (!game.user?.isGM) return;
    for (const scene of game.scenes?.contents || []) {
        await SiteSceneVisibilityManager.applySceneVisibility(scene);
    }
}

function notifyConnectionsChanged(reason) {
    Hooks.callAll("augurNexusConnectionsChanged", {
        graph: ConnectionDatabaseService.getGraph(),
        reason
    });
}

export function registerNexusSettings() {
    game.settings.register(MODULE_ID, "interfaceAccentColor", {
        scope: "world",
        config: true,
        name: "Interface Accent",
        hint: "Sets structural highlights across Nexus and compatible module interfaces for everyone in this world. World-state and semantic colors are not changed.",
        type: new foundry.data.fields.ColorField({
            required: true,
            nullable: false,
            initial: DEFAULT_NEXUS_ACCENT
        }),
        default: DEFAULT_NEXUS_ACCENT,
        onChange: applyNexusAccentColor
    });
    applyNexusAccentColor();

    game.settings.register(MODULE_ID, "siteCustomIconFolder", {
        scope: "client",
        config: false,
        type: Object,
        default: {
            source: "data",
            path: ""
        }
    });

    game.settings.register(MODULE_ID, "npcCustomPortraitFolder", {
        scope: "client",
        config: false,
        type: Object,
        default: {
            source: "data",
            path: ""
        }
    });

    game.settings.register(MODULE_ID, "shopCustomImageFolder", {
        scope: "client",
        config: false,
        type: Object,
        default: {
            source: "data",
            path: ""
        }
    });

    game.settings.register(MODULE_ID, "shipCustomImageFolder", {
        scope: "client",
        config: false,
        type: Object,
        default: {
            source: "data",
            path: ""
        }
    });

    game.settings.register(MODULE_ID, "siteSceneRootFolderId", {
        scope: "world",
        config: false,
        type: String,
        default: ""
    });

    game.settings.register(MODULE_ID, "connectionsGraph", {
        scope: "world",
        config: false,
        type: Object,
        default: {
            version: 1,
            customCategories: {},
            nodes: {},
            edges: {}
        },
        onChange: graph => Hooks.callAll("augurNexusLegacyConnectionsGraphChanged", graph)
    });

    game.settings.register(MODULE_ID, "connectionDatabaseJournalEntryId", {
        scope: "world",
        config: false,
        type: String,
        default: "",
        onChange: documentId => Hooks.callAll("augurNexusConnectionDatabasePointerChanged", documentId)
    });

    game.settings.register(MODULE_ID, "placeJournalEntryId", {
        scope: "world",
        config: false,
        type: String,
        default: ""
    });

    game.settings.register(MODULE_ID, "connectionDossierJournalEntryId", {
        scope: "world",
        config: false,
        type: String,
        default: ""
    });

    game.settings.register(MODULE_ID, "playerSceneViewing", {
        scope: "world",
        config: true,
        name: "Player Scene Viewing",
        hint: "Controls whether players can use Nexus buttons to view linked Nexus scenes on their own clients. Foundry scene ownership and token vision still apply.",
        type: String,
        default: "all",
        choices: {
            explicit: "Explicit Only",
            all: "All Nexus Scenes"
        },
        onChange: () => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusPlayerSceneAccessChanged");
        }
    });

    game.settings.register(MODULE_ID, "playerNexusVisibility", {
        scope: "world",
        config: true,
        name: "Player Visibility",
        hint: "Controls which Nexus scenes and site pins are visible to players. Visible To Players settings can override this.",
        type: String,
        default: "all",
        choices: {
            explicit: "Explicit Only",
            all: "All Nexus Scenes"
        },
        onChange: () => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusPlayerSceneAccessChanged");
            syncSitePlayerVisibility().catch(err => {
                console.warn("Failed to sync site player visibility.", err);
            });
        }
    });

    game.settings.register(MODULE_ID, "playerConnectionVisibility", {
        scope: "world",
        config: true,
        name: "Connection Visibility",
        hint: "Controls which Nexus connections are visible to players. Connection-level Visible To Players settings can override this.",
        type: String,
        default: "all",
        choices: {
            explicit: "Explicit Only",
            all: "All Connections"
        },
        onChange: () => {
            ui.nexus?.render?.();
            notifyConnectionsChanged("connectionVisibilitySettingChanged");
        }
    });

    game.settings.register(MODULE_ID, "playerNpcVisibility", {
        scope: "world",
        config: true,
        name: "People Visibility",
        hint: "Controls which Nexus people are visible to players. Person-level Visible To Players settings can override this.",
        type: String,
        default: "all",
        choices: {
            explicit: "Explicit Only",
            all: "All People"
        },
        onChange: policy => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusCampaignEntityVisibilityChanged", { reason: "entityVisibilitySettingChanged", entityType: "npc", policy });
            Hooks.callAll("augurNexusCampaignEntitiesChanged", { reason: "entityVisibilitySettingChanged", entityType: "npc" });
            notifyConnectionsChanged("entityVisibilitySettingChanged");
        }
    });

    game.settings.register(MODULE_ID, "playerFactionVisibility", {
        scope: "world",
        config: true,
        name: "Organization Visibility",
        hint: "Controls which Nexus organizations are visible to players. Organization-level Visible To Players settings can override this.",
        type: String,
        default: "all",
        choices: {
            explicit: "Explicit Only",
            all: "All Organizations"
        },
        onChange: policy => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusCampaignEntityVisibilityChanged", { reason: "entityVisibilitySettingChanged", entityType: "faction", policy });
            Hooks.callAll("augurNexusCampaignEntitiesChanged", { reason: "entityVisibilitySettingChanged", entityType: "faction" });
            notifyConnectionsChanged("entityVisibilitySettingChanged");
        }
    });

    game.settings.register(MODULE_ID, "playerLocationVisibility", {
        scope: "world",
        config: true,
        name: "Location Visibility",
        hint: "Controls which Nexus locations are visible to players. Location-level visibility can override this.",
        type: String,
        default: "all",
        choices: { explicit: "Explicit Only", all: "All Locations" },
        onChange: policy => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusCampaignEntityVisibilityChanged", { reason: "entityVisibilitySettingChanged", entityType: "location", policy });
            Hooks.callAll("augurNexusCampaignEntitiesChanged", { reason: "entityVisibilitySettingChanged", entityType: "location" });
            notifyConnectionsChanged("entityVisibilitySettingChanged");
        }
    });

    game.settings.register(MODULE_ID, "playerLocationDisclosure", {
        scope: "world",
        config: true,
        name: "Default Location Details",
        hint: "Controls whether visible Nexus locations show full details or an Unvisited view by default. Location-level Player Details settings can override this.",
        type: String,
        default: "full",
        choices: {
            limited: "Exploration - Unvisited",
            full: "Open Information - Visited"
        },
        onChange: disclosure => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusCampaignEntityDisclosureChanged", { reason: "disclosureSettingChanged", entityType: "location", disclosure });
            Hooks.callAll("augurNexusCampaignEntitiesChanged", { reason: "disclosureSettingChanged", entityType: "location" });
            notifyConnectionsChanged("entityDisclosureSettingChanged");
        }
    });

    game.settings.register(MODULE_ID, "playerShipVisibility", {
        scope: "world",
        config: true,
        name: "Ship Visibility",
        hint: "Controls which Nexus ships are visible to players. Ship-level Visible To Players settings can override this.",
        type: String,
        default: "all",
        choices: {
            explicit: "Explicit Only",
            all: "All Ships"
        },
        onChange: policy => {
            ui.nexus?.render?.();
            Hooks.callAll("augurNexusCampaignEntityVisibilityChanged", { reason: "entityVisibilitySettingChanged", entityType: "ship", policy });
            Hooks.callAll("augurNexusCampaignEntitiesChanged", { reason: "entityVisibilitySettingChanged", entityType: "ship" });
            notifyConnectionsChanged("entityVisibilitySettingChanged");
        }
    });

    game.settings.register(MODULE_ID, "cinematicSceneTransitions", {
        scope: "world",
        config: true,
        name: "Cinematic Scene Transitions",
        hint: "Use zoom and fade camera transitions when moving through Nexus scenes. Disable this if Nexus navigation should leave scene views alone.",
        type: Boolean,
        default: true
    });

    game.settings.register(MODULE_ID, "entityPlacementCreatesSceneConnections", {
        scope: "world",
        config: true,
        name: "Entity placement creates scene connections",
        hint: "When people, ships, or organizations are placed as Nexus scene markers, automatically connect the current scene to that entity.",
        type: Boolean,
        default: true
    });

    game.settings.register(MODULE_ID, "trackShipLocationFromMarkers", {
        scope: "world",
        config: true,
        name: "Track Ship Location from Markers",
        hint: "When enabled, placing a Ship marker moves that Ship to the Scene, removes its other managed markers, and updates Current Location. Disable this to manage Ship markers and Current Location independently.",
        type: Boolean,
        default: true,
        onChange: () => Hooks.callAll("augurNexusCampaignEntitiesChanged", { reason: "shipLocationTrackingSettingChanged", entity: null })
    });

    game.settings.register(MODULE_ID, "nexusBrowserShowIcons", {
        scope: "client",
        config: false,
        type: Boolean,
        default: true
    });

    game.settings.register(MODULE_ID, "siteGeneratorState", {
        scope: "client",
        config: false,
        type: Object,
        default: {
            genreId: "fantasy",
            themeId: "castle",
            sceneType: "empty",
            sizeId: "small",
            iconRole: "landmark",
            iconId: null,
            customIconSrc: "",
            iconColor: "#ffffff",
            iconSizeMode: "scene-default",
            customIconSize: null,
            mapColorId: "green",
            snapToGrid: false,
            autoSortScenes: true,
            randomizeAfterPlacement: false
        }
    });
}
