import type { GlassMaterialSettings, NodedcTheme } from "@nodedc/ui-core";
import type { ToolbarPlacement } from "@nodedc/ui-react";
import type { FaviconAssetUrls } from "./favicon.js";
import type { MapPageLayout, MapPageSettings } from "./MapFixturePreview.js";
import type { MapPresentationProfile } from "./mapPresentationProfile.js";

export type MaterialDraft = {
  panelHex: string;
  panelOpacity: number;
  fieldHex: string;
  fieldOpacity: number;
  nestedHex: string;
};

export type MapDesignProfileFragment = {
  schemaVersion: 1;
  templateId: "map";
  templateVersion: string;
  settings: MapPageSettings;
  presentationProfiles: MapPresentationProfile[];
};

export type DesignProfilePageFragment = MapDesignProfileFragment;

export interface StoredLayout {
  theme?: NodedcTheme;
  accentHex?: string;
  materialByTheme?: Record<NodedcTheme, MaterialDraft>;
  environment?: {
    lightColor?: string;
    brightness?: number;
    glowDistance?: number;
    connectionType?: string;
    connectionColor?: string;
    usePortColors?: boolean;
    fillColor?: string;
    fillOpacity?: number;
    strokeColor?: string;
    strokeOpacity?: number;
  };
  media?: {
    source?: "file" | "url";
    url?: string;
    fileName?: string;
    fileSrc?: string;
    visible?: boolean;
    logoSource?: "file" | "url";
    logoUrl?: string;
    logoFileName?: string;
    logoFileSrc?: string;
    faviconFileName?: string;
    faviconAssets?: FaviconAssetUrls;
  };
  glass?: GlassMaterialSettings;
  toolbar?: {
    placement?: ToolbarPlacement;
    background?: string;
    border?: string;
    outline?: string;
    minSize?: number;
    maxSize?: number;
    lensCount?: number;
    autoHide?: boolean;
  };
  /** Design fragments are keyed by a registered Page Library type/version. */
  pageTypes?: Record<string, DesignProfilePageFragment>;
}

export type MapDesignOverrides = {
  settings?: Partial<MapPageSettings>;
  presentationProfiles?: MapPresentationProfile[];
};

export const mapDesignProfileKey = (templateVersion: string) => `map@${templateVersion}`;

export function mapDesignFragmentFromLayout(layout: MapPageLayout, templateVersion: string): MapDesignProfileFragment {
  return {
    schemaVersion: 1,
    templateId: "map",
    templateVersion,
    settings: structuredClone(layout.settings),
    presentationProfiles: structuredClone(layout.presentationProfiles),
  };
}

export function mapDesignFragmentForLayout(layout: StoredLayout | null | undefined, templateVersion: string) {
  const fragment = layout?.pageTypes?.[mapDesignProfileKey(templateVersion)];
  return fragment?.templateId === "map" ? fragment : null;
}

export function resolveMapDesignLayout(
  base: MapPageLayout | null | undefined,
  fragment: MapDesignProfileFragment | null | undefined,
  overrides?: MapDesignOverrides,
) {
  if (!base) return null;
  if (!fragment) return base;
  return {
    ...base,
    settings: {
      ...base.settings,
      ...fragment.settings,
      ...overrides?.settings,
    },
    presentationProfiles: structuredClone(overrides?.presentationProfiles ?? fragment.presentationProfiles),
  } satisfies MapPageLayout;
}

export function mapDesignOverridesFromResolved(
  resolved: MapPageLayout,
  fragment: MapDesignProfileFragment | null | undefined,
): MapDesignOverrides | undefined {
  if (!fragment) return undefined;
  const settings = Object.fromEntries(Object.entries(resolved.settings).filter(([key, value]) => (
    fragment.settings[key as keyof MapPageSettings] !== value
  ))) as Partial<MapPageSettings>;
  const presentationProfiles = JSON.stringify(resolved.presentationProfiles) === JSON.stringify(fragment.presentationProfiles)
    ? undefined
    : structuredClone(resolved.presentationProfiles);
  if (Object.keys(settings).length === 0 && !presentationProfiles) return undefined;
  return {
    ...(Object.keys(settings).length > 0 ? { settings } : {}),
    ...(presentationProfiles ? { presentationProfiles } : {}),
  };
}
