/**
 * Aggregates data for the Integrations architecture page.
 * Primary payload: GET /api/system/integrations-overview (no fictitious diagram data).
 */

import { useState, useEffect, useCallback } from 'react';
import api from '../api';
import type { FeatureInstance, NavigationMandate } from './useNavigation';

export interface AicoreModuleRow {
  connectorType: string;
  label: string;
  modelCount: number;
}

export interface InfraToolRow {
  id: string;
  label: string;
}

export type DataLayerItemKind =
  | 'userConnection'
  | 'dataSource'
  | 'featureDataSource'
  | 'trusteeAccounting';

export interface DataLayerItem {
  kind: DataLayerItemKind;
  id: string;
  /** userConnection */
  displayLabel?: string;
  connectionReference?: string;
  authority?: string;
  /** dataSource */
  label?: string;
  sourceType?: string;
  connectionId?: string;
  /** shared */
  featureInstanceId?: string | null;
  mandateId?: string | null;
  /** featureDataSource */
  featureCode?: string;
  tableName?: string;
  /** trusteeAccounting */
  instanceLabel?: string;
  connectorType?: string;
}

export interface LiveStats {
  aiCallCount: number;
  aiCallPeriodDays: number;
  totalWorkflows: number;
  activeWorkflows: number;
  totalRuns: number;
  totalTokens: number;
}

export interface ExtractorClassRow {
  className: string;
  extensions: string[];
}

export interface RendererClassRow {
  className: string;
  formats: string[];
}

export interface IntegrationsDiagramPayload {
  aicoreModules: AicoreModuleRow[];
  infraTools: InfraToolRow[];
  extractorExtensions: string[];
  extractorClasses: ExtractorClassRow[];
  rendererFormats: string[];
  rendererClasses: RendererClassRow[];
  dataLayerItems: DataLayerItem[];
  liveStats: LiveStats;
  errors?: string[];
}

export interface MandateCardData {
  id: string;
  uiLabel: string;
  dotColor: string;
  /** "Feature: Instanzbezeichnung" per instance */
  moduleChips: string[];
}

export interface UseIntegrationsOverviewResult {
  loading: boolean;
  error: string | null;
  refetch: () => Promise<void>;
  diagram: IntegrationsDiagramPayload | null;
  mandateCards: MandateCardData[];
  workflowChips: string[];
  hasNeutralization: boolean;
}

function _dotColorForIndex(index: number): string {
  const palette = ['#378ADD', '#1D9E75', '#D85A30', '#8B5CF6', '#EC4899', '#0EA5E9'];
  return palette[index % palette.length];
}

function _collectGraphicalEditorInstanceIds(mandates: NavigationMandate[]): string[] {
  const ids: string[] = [];
  for (const mandate of mandates) {
    for (const feature of mandate.features) {
      if (feature.uiComponent === 'feature.graphicalEditor') {
        for (const inst of feature.instances) {
          if (inst.id && !ids.includes(inst.id)) {
            ids.push(inst.id);
          }
        }
      }
    }
  }
  return ids;
}

function _hasFeatureCode(mandates: NavigationMandate[], code: string): boolean {
  for (const mandate of mandates) {
    for (const feature of mandate.features) {
      if (feature.uiComponent === `feature.${code}`) {
        return true;
      }
    }
  }
  return false;
}

function _featureCodeFromUiComponent(uiComponent: string): string {
  return uiComponent.startsWith('feature.') ? uiComponent.slice(8) : uiComponent;
}

function _instanceChipLine(inst: FeatureInstance, featureUiComponent: string): string {
  const label = (inst.uiLabel || '').trim();
  const code = (inst.featureCode || _featureCodeFromUiComponent(featureUiComponent)).trim();
  if (label && code) {
    return `${label} (${code})`;
  }
  if (label) {
    return label;
  }
  return code;
}

function _buildMandateCards(mandates: NavigationMandate[]): MandateCardData[] {
  return mandates.map((m, i) => {
    const moduleChips: string[] = [];
    for (const f of m.features) {
      for (const inst of f.instances) {
        const line = _instanceChipLine(inst, f.uiComponent);
        if (line && !moduleChips.includes(line)) {
          moduleChips.push(line);
        }
      }
    }
    return {
      id: m.id,
      uiLabel: m.uiLabel,
      dotColor: _dotColorForIndex(i),
      moduleChips: moduleChips.slice(0, 24),
    };
  });
}

const _DEFAULT_LIVE_STATS: LiveStats = {
  aiCallCount: 0,
  aiCallPeriodDays: 30,
  totalWorkflows: 0,
  activeWorkflows: 0,
  totalRuns: 0,
  totalTokens: 0,
};

function _normalizeExtractorClasses(raw: unknown): ExtractorClassRow[] {
  if (!Array.isArray(raw)) return [];
  const out: ExtractorClassRow[] = [];
  for (const row of raw) {
    if (!row || typeof row !== 'object') continue;
    const r = row as Record<string, unknown>;
    const className = typeof r.className === 'string' ? r.className : '';
    const extensions = Array.isArray(r.extensions) ? (r.extensions as string[]) : [];
    if (className && extensions.length) out.push({ className, extensions });
  }
  return out;
}

function _normalizeRendererClasses(raw: unknown): RendererClassRow[] {
  if (!Array.isArray(raw)) return [];
  const out: RendererClassRow[] = [];
  for (const row of raw) {
    if (!row || typeof row !== 'object') continue;
    const r = row as Record<string, unknown>;
    const className = typeof r.className === 'string' ? r.className : '';
    const formats = Array.isArray(r.formats) ? (r.formats as string[]) : [];
    if (className && formats.length) out.push({ className, formats });
  }
  return out;
}

function _normalizeDiagramPayload(raw: unknown): IntegrationsDiagramPayload {
  const o = raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : {};
  const rawStats = o.liveStats && typeof o.liveStats === 'object'
    ? (o.liveStats as Record<string, unknown>)
    : {};
  return {
    aicoreModules: Array.isArray(o.aicoreModules) ? (o.aicoreModules as AicoreModuleRow[]) : [],
    infraTools: Array.isArray(o.infraTools) ? (o.infraTools as InfraToolRow[]) : [],
    extractorExtensions: Array.isArray(o.extractorExtensions)
      ? (o.extractorExtensions as string[])
      : [],
    extractorClasses: _normalizeExtractorClasses(o.extractorClasses),
    rendererFormats: Array.isArray(o.rendererFormats) ? (o.rendererFormats as string[]) : [],
    rendererClasses: _normalizeRendererClasses(o.rendererClasses),
    dataLayerItems: Array.isArray(o.dataLayerItems) ? (o.dataLayerItems as DataLayerItem[]) : [],
    liveStats: {
      aiCallCount: typeof rawStats.aiCallCount === 'number' ? rawStats.aiCallCount : _DEFAULT_LIVE_STATS.aiCallCount,
      aiCallPeriodDays: typeof rawStats.aiCallPeriodDays === 'number' ? rawStats.aiCallPeriodDays : _DEFAULT_LIVE_STATS.aiCallPeriodDays,
      totalWorkflows: typeof rawStats.totalWorkflows === 'number' ? rawStats.totalWorkflows : _DEFAULT_LIVE_STATS.totalWorkflows,
      activeWorkflows: typeof rawStats.activeWorkflows === 'number' ? rawStats.activeWorkflows : _DEFAULT_LIVE_STATS.activeWorkflows,
      totalRuns: typeof rawStats.totalRuns === 'number' ? rawStats.totalRuns : _DEFAULT_LIVE_STATS.totalRuns,
      totalTokens: typeof rawStats.totalTokens === 'number' ? rawStats.totalTokens : _DEFAULT_LIVE_STATS.totalTokens,
    },
    errors: Array.isArray(o.errors) ? (o.errors as string[]) : undefined,
  };
}

export function useIntegrationsOverview(): UseIntegrationsOverviewResult {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [diagram, setDiagram] = useState<IntegrationsDiagramPayload | null>(null);
  const [mandateCards, setMandateCards] = useState<MandateCardData[]>([]);
  const [workflowChips, setWorkflowChips] = useState<string[]>([]);
  const [hasNeutralization, setHasNeutralization] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const [navResult, diagramResult] = await Promise.allSettled([
        api.get('/api/navigation'),
        api.get('/api/system/integrations-overview'),
      ]);

      let mandatesForWorkflows: NavigationMandate[] = [];

      if (navResult.status === 'fulfilled') {
        const blocks = navResult.value.data?.blocks ?? [];
        const dynamicBlock = blocks.find((b: { type: string }) => b.type === 'dynamic');
        mandatesForWorkflows = dynamicBlock?.mandates ?? [];
        setMandateCards(_buildMandateCards(mandatesForWorkflows));
        setHasNeutralization(_hasFeatureCode(mandatesForWorkflows, 'neutralization'));
      } else {
        setMandateCards([]);
        setHasNeutralization(false);
        setError(
          navResult.reason instanceof Error
            ? navResult.reason.message
            : String(navResult.reason),
        );
      }

      if (diagramResult.status === 'fulfilled') {
        setDiagram(_normalizeDiagramPayload(diagramResult.value.data));
      } else {
        setDiagram(_normalizeDiagramPayload({}));
        const msg =
          diagramResult.reason instanceof Error
            ? diagramResult.reason.message
            : String(diagramResult.reason);
        setError((prev) => (prev ? `${prev} | ${msg}` : msg));
      }

      const geIds = _collectGraphicalEditorInstanceIds(mandatesForWorkflows);
      const wfLabels: string[] = [];
      const seenWf = new Set<string>();
      for (const instanceId of geIds.slice(0, 4)) {
        try {
          const wfRes = await api.get(`/api/workflows/${instanceId}/workflows`, {
            params: { active: 'true' },
          });
          const wfData = wfRes.data;
          const list = Array.isArray(wfData)
            ? wfData
            : (wfData as { items?: { label?: string }[]; workflows?: { label?: string }[] })?.items ??
              (wfData as { workflows?: { label?: string }[] })?.workflows ??
              [];
          for (const w of list) {
            const lab = (w as { label?: string }).label;
            if (lab && !seenWf.has(lab)) {
              seenWf.add(lab);
              wfLabels.push(lab);
            }
            if (wfLabels.length >= 8) break;
          }
        } catch {
          /* ignore */
        }
        if (wfLabels.length >= 8) break;
      }
      setWorkflowChips(wfLabels.slice(0, 8));
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : 'Laden fehlgeschlagen');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void load();
  }, [load]);

  return {
    loading,
    error,
    refetch: load,
    diagram,
    mandateCards,
    workflowChips,
    hasNeutralization,
  };
}
