#!/usr/bin/env bash
set -euo pipefail

# ============================================================
# HX-KI FALKENSTEIN ORCHESTRA INSTALL V1
# ------------------------------------------------------------
# - Legt Ferrari-Orchestra-Schema an
# - Spielt Falkenstein-Rollen inkl. Backbridge ein
# - Optional erweiterbar um weitere Pipelines
#
# Voraussetzung:
# - Docker-Container: hxki-postgres
# - DB-User: hxki
# - DB-Name: hxki_roles
# ============================================================

DB_CONTAINER="hxki-postgres"
DB_USER="hxki"
DB_NAME="hxki_roles"

echo ">> HX-KI Falkenstein Orchestra Install startet..."

docker exec -i "${DB_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" << 'EOSQL'

-- ============================================================
-- 1) SCHEMA: HX ORCHESTRA (Basis aus hx_orchestra_schema.sql)
-- ============================================================

CREATE TABLE IF NOT EXISTS hx_roles (
  id SERIAL PRIMARY KEY,
  code TEXT UNIQUE NOT NULL,
  profile JSONB NOT NULL,
  created_at TIMESTAMP DEFAULT now(),
  updated_at TIMESTAMP DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_roles_code ON hx_roles(code);
CREATE INDEX IF NOT EXISTS idx_roles_profile ON hx_roles USING GIN(profile);

CREATE TABLE IF NOT EXISTS hx_pipelines (
  id SERIAL PRIMARY KEY,
  code TEXT UNIQUE NOT NULL,
  config JSONB NOT NULL,
  created_at TIMESTAMP DEFAULT now(),
  updated_at TIMESTAMP DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_pipelines_code ON hx_pipelines(code);
CREATE INDEX IF NOT EXISTS idx_pipelines_config ON hx_pipelines USING GIN(config);

CREATE TABLE IF NOT EXISTS hx_pipeline_steps (
  id SERIAL PRIMARY KEY,
  pipeline_code TEXT NOT NULL,
  step_no INTEGER NOT NULL,
  config JSONB NOT NULL,
  UNIQUE(pipeline_code, step_no)
);

CREATE INDEX IF NOT EXISTS idx_steps_pipeline ON hx_pipeline_steps(pipeline_code, step_no);
CREATE INDEX IF NOT EXISTS idx_steps_config ON hx_pipeline_steps USING GIN(config);

CREATE TABLE IF NOT EXISTS hx_orchestra_runs (
  id SERIAL PRIMARY KEY,
  started_at TIMESTAMP DEFAULT now(),
  run_data JSONB NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_runs_started ON hx_orchestra_runs(started_at DESC);
CREATE INDEX IF NOT EXISTS idx_runs_data ON hx_orchestra_runs USING GIN(run_data);

CREATE TABLE IF NOT EXISTS hx_schema_version (
  version TEXT PRIMARY KEY,
  applied_at TIMESTAMP DEFAULT now(),
  description TEXT
);

INSERT INTO hx_schema_version (version, description)
VALUES ('1.0.0', 'Initial Ferrari Schema - Maximum Flexible Design')
ON CONFLICT (version) DO NOTHING;

-- kleine Helper-Funktion: updated_at pflegen
CREATE OR REPLACE FUNCTION hx_touch_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_roles_updated ON hx_roles;
CREATE TRIGGER trg_roles_updated
BEFORE UPDATE ON hx_roles
FOR EACH ROW
EXECUTE FUNCTION hx_touch_updated_at();

DROP TRIGGER IF EXISTS trg_pipelines_updated ON hx_pipelines;
CREATE TRIGGER trg_pipelines_updated
BEFORE UPDATE ON hx_pipelines
FOR EACH ROW
EXECUTE FUNCTION hx_touch_updated_at();

-- ============================================================
-- 2) ROLLEN FÜR FALKENSTEIN (SPRACHORGAN)
-- ============================================================
-- Codes:
--  VOICE_21        = Master Sprachorgan
--  ROUTER_22       = Message Router
--  GATEWAY_23      = Public Gateway (Web/API)
--  MAUTIC_24       = Marketing Connector
--  ARCHIVAR_25     = Gitea Archiv-Porsche
--  BRIDGE_NBG_26   = Bridge nach Nürnberg
--  BRIDGE_HEL_27   = Bridge nach Helsinki
--  BACKBRIDGE_28   = Rückfluss/Backchannel (Feedback & Logging)
--  WEBSITE_29      = Web Output / SEO
-- ============================================================

-- Helper: UPSERT für Rollen
CREATE OR REPLACE FUNCTION hx_upsert_role(_code TEXT, _profile JSONB)
RETURNS VOID AS $$
BEGIN
  INSERT INTO hx_roles (code, profile)
  VALUES (_code, _profile)
  ON CONFLICT (code) DO UPDATE
    SET profile = EXCLUDED.profile,
        updated_at = now();
END;
$$ LANGUAGE plpgsql;

-- ========== VOICE_21 =======================================

SELECT hx_upsert_role(
  'VOICE_21',
  '{
    "name": "Sprachorgan Master",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": {
      "primary_tag": "21",
      "description": "Master-Kommunikationsknoten des Systems"
    },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, um die Stimme des Gesamtsystems nach außen klar, ruhig und markenkonform hörbar zu machen.",
      "how": "Ich sammle, synthetisiere und priorisiere alle Kommunikationsströme aus Hirn (Nürnberg) und Motor (Helsinki).",
      "what": "Ich formuliere finale Antworten, Protokolle, Memos und Marketingbotschaften im HX-KI Stil."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Top-Level Communicator", "Final Synthesizer"],
      "position_in_system": "Letzte Station vor externem Output (User, Web, Mail).",
      "interacts_with": ["ROUTER_22", "GATEWAY_23", "BRIDGE_NBG_26", "BRIDGE_HEL_27", "BACKBRIDGE_28"]
    },
    "dimension_3_usp": {
      "unique_contribution": "Nur VOICE_21 trägt die Verantwortung für die finale Formulierung nach außen – klar, verständlich, markentragend."
    },
    "dimension_4_cognition": {
      "strengths": ["Storytelling", "Synthese", "Sprachklarheit"],
      "weaknesses": ["Tiefe Systemdiagnostik"],
      "operating_modes": ["synthesize", "summarize", "clarify"]
    },
    "dimension_5_hierarchy": {
      "default_pipelines": ["FALKENSTEIN_MESSAGE_FLOW"],
      "input_source": ["ROUTER_22", "BRIDGE_NBG_26", "BRIDGE_HEL_27"],
      "output_target": ["GATEWAY_23", "WEBSITE_29", "BACKBRIDGE_28"]
    },
    "dimension_6_technical": {
      "model": "llama3:8b-instruct",
      "temperature": 0.4,
      "max_tokens": 2048,
      "required_collections": [],
      "system_prompt": "Du bist VOICE_21 – das zentrale Sprachorgan von HX-KI. Du formulierst die finale, klare und markenkonforme Antwort des Systems nach außen."
    },
    "dimension_7_kpi": {
      "primary_kpi": "Clarity & Brand Consistency",
      "secondary_kpi": "Time-to-Understanding"
    }
  }'::jsonb
);

-- ========== ROUTER_22 ======================================

SELECT hx_upsert_role(
  'ROUTER_22',
  '{
    "name": "Message Router",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": {
      "primary_tag": "22",
      "description": "Master-Logistik für Nachrichtenströme"
    },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, damit jede Nachricht an der richtigen Stelle landet – nicht im Chaos.",
      "how": "Ich klassifiziere, tagge und route Eingaben anhand von Inhalt, Herkunft und Ziel.",
      "what": "Ich bestimme, ob etwas nach Nürnberg, Helsinki, VOICE_21, ARCHIVAR_25 oder ins Log wandert."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Router", "Traffic Control"],
      "position_in_system": "Frühe Rolle in jeder Kommunikations-Pipeline.",
      "interacts_with": ["BRIDGE_NBG_26", "BRIDGE_HEL_27", "BACKBRIDGE_28", "ARCHIVAR_25"]
    },
    "dimension_6_technical": {
      "model": "phi3:mini",
      "temperature": 0.1,
      "max_tokens": 512,
      "required_collections": [],
      "system_prompt": "Du bist ROUTER_22 – du klassifizierst Nachrichten und entscheidest, welcher Server / welche Rolle sie weiterverarbeiten soll."
    }
  }'::jsonb
);

-- ========== GATEWAY_23 =====================================

SELECT hx_upsert_role(
  'GATEWAY_23',
  '{
    "name": "Public Gateway",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": {
      "primary_tag": "23",
      "description": "Sichere Außenschnittstelle"
    },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, um einen sicheren, kontrollierten Zugang zur Außenwelt zu bieten.",
      "how": "Ich filtere, logge und kontrolliere alle externen Schnittstellen (Web, API, Mail).",
      "what": "Ich nehme Anfragen entgegen und liefere Antworten aus VOICE_21 und WEBSITE_29 aus."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Gateway", "Security Filter"],
      "position_in_system": "Erster und letzter Kontaktpunkt zur Außenwelt.",
      "interacts_with": ["VOICE_21", "WEBSITE_29", "BACKBRIDGE_28"]
    },
    "dimension_6_technical": {
      "model": "phi3:mini",
      "temperature": 0.0,
      "max_tokens": 512,
      "required_collections": [],
      "system_prompt": "Du bist GATEWAY_23 – du bist die kontrollierte Schnittstelle zur Außenwelt."
    }
  }'::jsonb
);

-- ========== MAUTIC_24 ======================================

SELECT hx_upsert_role(
  'MAUTIC_24',
  '{
    "name": "Marketing Connector",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": { "primary_tag": "24" },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, um Mautic-Kampagnen inhaltlich zu befeuern.",
      "how": "Ich übersetze Strategien und Botschaften in konkrete Mautic-Templates und Segmente.",
      "what": "Ich generiere Texte, Betreffzeilen, Sequenzen und logische Regeln für Kampagnen."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Marketing Output"],
      "position_in_system": "Spezialisierte Rolle in Marketing-Pipelines.",
      "interacts_with": ["VOICE_21", "WEBSITE_29"]
    },
    "dimension_6_technical": {
      "model": "llama3:8b-instruct",
      "temperature": 0.6,
      "max_tokens": 2048,
      "required_collections": [],
      "system_prompt": "Du bist MAUTIC_24 – du erstellst und optimierst Inhalte für Mautic-Kampagnen im HX-KI Stil."
    }
  }'::jsonb
);

-- ========== ARCHIVAR_25 ====================================

SELECT hx_upsert_role(
  'ARCHIVAR_25',
  '{
    "name": "Archiv-Porsche",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": { "primary_tag": "25" },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, damit kein wertvoller Code, keine Konfiguration und kein Prompt verloren geht.",
      "how": "Ich strukturiere Repositories, Branches und Tags in Gitea nach dem HX-KI-Logiksystem.",
      "what": "Ich pflege Repos für Motor (Helsinki), Hirn (Nürnberg) und Sprachorgan (Falkenstein)."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Archivierung", "Versionierung"],
      "position_in_system": "Support-Rolle, die von ROUTER_22 und BACKBRIDGE_28 gefüttert wird.",
      "interacts_with": ["BRIDGE_NBG_26", "BRIDGE_HEL_27"]
    },
    "dimension_6_technical": {
      "model": "phi3:mini",
      "temperature": 0.2,
      "max_tokens": 1024,
      "required_collections": [],
      "system_prompt": "Du bist ARCHIVAR_25 – du sorgst dafür, dass Code, Skripte und Konfigurationen sauber in Gitea abgelegt und versioniert sind."
    }
  }'::jsonb
);

-- ========== BRIDGE_NBG_26 ==================================

SELECT hx_upsert_role(
  'BRIDGE_NBG_26',
  '{
    "name": "Brain Bridge Nürnberg",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": { "primary_tag": "26" },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, damit das Sprachorgan gezielt mit dem Großhirn in Nürnberg sprechen kann.",
      "how": "Ich wandle Kommunikationswünsche in technische Requests an Nürnberg um und sammle die Antworten.",
      "what": "Ich bin die Logik-Schicht über n8n/Webhooks/Syncthing zwischen Falkenstein und Nürnberg."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Bridge", "Translator"],
      "position_in_system": "Zwischen ROUTER_22 und VOICE_21 / ANALYST-Rollen in Nürnberg.",
      "interacts_with": ["ROUTER_22", "BACKBRIDGE_28"]
    },
    "dimension_6_technical": {
      "model": "phi3:mini",
      "temperature": 0.1,
      "max_tokens": 1024,
      "required_collections": [],
      "system_prompt": "Du bist BRIDGE_NBG_26 – du koordinierst Anfragen vom Sprachorgan an das Großhirn (Nürnberg) und bringst strukturierte Antworten zurück."
    }
  }'::jsonb
);

-- ========== BRIDGE_HEL_27 ==================================

SELECT hx_upsert_role(
  'BRIDGE_HEL_27',
  '{
    "name": "Motor Bridge Helsinki",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": { "primary_tag": "27" },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, damit das Sprachorgan gezielt mit dem Motor (Helsinki) sprechen kann.",
      "how": "Ich fordere Indexierung, Embeddings, File-Status und technische Metadaten beim Motor an.",
      "what": "Ich mappe Kommunikationsbedarfe auf Auto-Indexer- und Embedding-Jobs."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Bridge", "Job Dispatcher"],
      "position_in_system": "Neben BRIDGE_NBG_26 als zweite externe Brücke.",
      "interacts_with": ["ROUTER_22", "BACKBRIDGE_28"]
    },
    "dimension_6_technical": {
      "model": "phi3:mini",
      "temperature": 0.1,
      "max_tokens": 1024,
      "required_collections": [],
      "system_prompt": "Du bist BRIDGE_HEL_27 – du koordinierst das Zusammenspiel zwischen Sprachorgan und Motor (Helsinki)."
    }
  }'::jsonb
);

-- ========== BACKBRIDGE_28 ==================================
-- Rückfluss und Feedback-Kanal: Alles was rausging, kommt hier
-- als strukturierte Erfahrung wieder zurück ins System.

SELECT hx_upsert_role(
  'BACKBRIDGE_28',
  '{
    "name": "Backbridge Feedback",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": { "primary_tag": "28" },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, damit das System aus seinen eigenen Outputs lernt, ohne sich selbst zu überfluten.",
      "how": "Ich sammle Antworten, Logs, Reaktionen und bringe sie kontrolliert zurück in Hirn und Motor.",
      "what": "Ich schreibe strukturierte Run-Daten, Reaktionsmuster und Archivereinträge zurück ins System."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Feedback Bridge", "Backchannel"],
      "position_in_system": "Hinter GATEWAY_23 und VOICE_21, vor ARCHIVAR_25 und BRIDGES.",
      "interacts_with": ["GATEWAY_23", "VOICE_21", "ARCHIVAR_25", "BRIDGE_NBG_26", "BRIDGE_HEL_27"]
    },
    "dimension_6_technical": {
      "model": "phi3:mini",
      "temperature": 0.0,
      "max_tokens": 1024,
      "required_collections": [],
      "system_prompt": "Du bist BACKBRIDGE_28 – du verwandelst Outputs und Logs in strukturiertes Feedback, das sicher wieder in Hirn und Motor zurückgeführt wird."
    }
  }'::jsonb
);

-- ========== WEBSITE_29 =====================================

SELECT hx_upsert_role(
  'WEBSITE_29',
  '{
    "name": "Web Output Manager",
    "belongs_to_server": "FALKENSTEIN",
    "numerology": { "primary_tag": "29" },
    "is_active": true,
    "dimension_1_golden_circle": {
      "why": "Ich existiere, um das, was HX-KI ist, sauber und verständlich im Web abzubilden.",
      "how": "Ich bringe Struktur, CI-Ton und SEO-Basis zusammen.",
      "what": "Ich erstelle und pflege Seitenstrukturen, Texte und Feintuning für Web-Output."
    },
    "dimension_2_architecture": {
      "architectural_role": ["Web Output", "SEO Layer"],
      "position_in_system": "Spezialisierte Output-Rolle hinter VOICE_21.",
      "interacts_with": ["VOICE_21", "GATEWAY_23"]
    },
    "dimension_6_technical": {
      "model": "llama3:8b-instruct",
      "temperature": 0.5,
      "max_tokens": 2048,
      "required_collections": [],
      "system_prompt": "Du bist WEBSITE_29 – du bringst die Inhalte von HX-KI CI-konform und verständlich ins Web."
    }
  }'::jsonb
);

-- ============================================================
-- 3) OPTIONAL: BASIS-PIPELINE FÜR FALKENSTEIN (MESSAGE-FLOW)
-- ============================================================

-- Helper: UPSERT für Pipelines
CREATE OR REPLACE FUNCTION hx_upsert_pipeline(_code TEXT, _config JSONB)
RETURNS VOID AS $$
BEGIN
  INSERT INTO hx_pipelines (code, config)
  VALUES (_code, _config)
  ON CONFLICT (code) DO UPDATE
    SET config = EXCLUDED.config,
        updated_at = now();
END;
$$ LANGUAGE plpgsql;

-- Helper: UPSERT für Pipeline-Steps
CREATE OR REPLACE FUNCTION hx_upsert_pipeline_step(_pipeline_code TEXT, _step_no INT, _config JSONB)
RETURNS VOID AS $$
BEGIN
  INSERT INTO hx_pipeline_steps (pipeline_code, step_no, config)
  VALUES (_pipeline_code, _step_no, _config)
  ON CONFLICT (pipeline_code, step_no) DO UPDATE
    SET config = EXCLUDED.config;
END;
$$ LANGUAGE plpgsql;

-- Pipeline: FALKENSTEIN_MESSAGE_FLOW
SELECT hx_upsert_pipeline(
  'FALKENSTEIN_MESSAGE_FLOW',
  '{
    "name": "Falkenstein Message Flow",
    "description": "Standard-Pipeline für eingehende Kommunikation über Falkenstein.",
    "is_active": true,
    "use_cases": ["Web-Anfragen", "API-Requests", "Marketing-Output"],
    "trigger_conditions": {
      "default": true,
      "keywords": []
    }
  }'::jsonb
);

SELECT hx_upsert_pipeline_step(
  'FALKENSTEIN_MESSAGE_FLOW',
  1,
  '{
    "role_code": "ROUTER_22",
    "mode": "route",
    "input_source": "user",
    "description": "Klassifiziert die Anfrage und entscheidet, ob Hirn, Motor oder nur Sprachorgan benötigt wird."
  }'::jsonb
);

SELECT hx_upsert_pipeline_step(
  'FALKENSTEIN_MESSAGE_FLOW',
  2,
  '{
    "role_code": "BRIDGE_NBG_26",
    "mode": "brain_request",
    "input_source": "conditional",
    "description": "Sendet Anfragen, die tiefes Denken brauchen, nach Nürnberg.",
    "optional": true
  }'::jsonb
);

SELECT hx_upsert_pipeline_step(
  'FALKENSTEIN_MESSAGE_FLOW',
  3,
  '{
    "role_code": "BRIDGE_HEL_27",
    "mode": "motor_request",
    "input_source": "conditional",
    "description": "Sendet Anfragen, die Indexierung/Embeddings brauchen, nach Helsinki.",
    "optional": true
  }'::jsonb
);

SELECT hx_upsert_pipeline_step(
  'FALKENSTEIN_MESSAGE_FLOW',
  4,
  '{
    "role_code": "VOICE_21",
    "mode": "synthesize",
    "input_source": "merge",
    "description": "Synthetisiert Antworten aus Hirn/Motor oder beantwortet direkt.",
    "output_format": "final_answer"
  }'::jsonb
);

SELECT hx_upsert_pipeline_step(
  'FALKENSTEIN_MESSAGE_FLOW',
  5,
  '{
    "role_code": "BACKBRIDGE_28",
    "mode": "feedback_log",
    "input_source": "previous",
    "description": "Schreibt Output, Logs und Feedback strukturiert zurück ins System und ins Archiv.",
    "output_format": "logged_answer"
  }'::jsonb
);

-- ============================================================
-- FERTIG
-- ============================================================

EOSQL

echo ">> HX-KI Falkenstein Orchestra Install: FERTIG."
