-- Baltique OS Core 0.78.2 — Enterprise Runtime Preflight
-- Idempotent schema layer for production readiness checks and acceptance scenarios.

CREATE TABLE IF NOT EXISTS system_runtime_preflight_runs (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  run_uuid VARCHAR(64) NOT NULL,
  run_type VARCHAR(40) NOT NULL DEFAULT 'manual',
  status VARCHAR(40) NOT NULL DEFAULT 'running',
  readiness_decision VARCHAR(20) NOT NULL DEFAULT 'HOLD',
  overall_score INT NOT NULL DEFAULT 0,
  critical_failed INT NOT NULL DEFAULT 0,
  warning_failed INT NOT NULL DEFAULT 0,
  info_failed INT NOT NULL DEFAULT 0,
  triggered_by_user_id BIGINT UNSIGNED NULL,
  started_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  finished_at DATETIME NULL,
  duration_ms INT NULL,
  summary_json JSON NULL,
  notes TEXT NULL,
  PRIMARY KEY(id),
  UNIQUE KEY uq_system_preflight_uuid (run_uuid),
  KEY idx_system_preflight_status (status, readiness_decision, started_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS system_runtime_preflight_checks (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  run_id BIGINT UNSIGNED NOT NULL,
  check_key VARCHAR(190) NOT NULL,
  domain_key VARCHAR(80) NOT NULL DEFAULT 'core',
  severity VARCHAR(40) NOT NULL DEFAULT 'warning',
  status VARCHAR(40) NOT NULL DEFAULT 'fail',
  title VARCHAR(255) NOT NULL,
  message TEXT NULL,
  remediation TEXT NULL,
  evidence_json JSON NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY(id),
  UNIQUE KEY uq_system_preflight_run_check (run_id, check_key),
  KEY idx_system_preflight_check_status (severity, status, domain_key),
  KEY idx_system_preflight_check_key (check_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS system_acceptance_scenarios (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  scenario_key VARCHAR(160) NOT NULL,
  scenario_label VARCHAR(255) NOT NULL,
  domain_key VARCHAR(80) NOT NULL DEFAULT 'core',
  criticality VARCHAR(40) NOT NULL DEFAULT 'major',
  owner_role VARCHAR(80) NOT NULL DEFAULT 'management',
  test_type VARCHAR(40) NOT NULL DEFAULT 'manual',
  automation_level VARCHAR(40) NOT NULL DEFAULT 'manual',
  objective TEXT NULL,
  prerequisite TEXT NULL,
  manual_steps MEDIUMTEXT NULL,
  expected_result TEXT NULL,
  status VARCHAR(40) NOT NULL DEFAULT 'active',
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NULL,
  PRIMARY KEY(id),
  UNIQUE KEY uq_system_acceptance_scenario (scenario_key),
  KEY idx_system_acceptance_domain (domain_key, criticality, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS system_acceptance_runs (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  scenario_key VARCHAR(160) NOT NULL,
  status VARCHAR(40) NOT NULL DEFAULT 'not_run',
  tested_by_user_id BIGINT UNSIGNED NULL,
  tested_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  notes TEXT NULL,
  evidence_json JSON NULL,
  PRIMARY KEY(id),
  KEY idx_system_acceptance_run_scenario (scenario_key, tested_at),
  KEY idx_system_acceptance_run_status (status, tested_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO system_acceptance_scenarios
(scenario_key,scenario_label,domain_key,criticality,owner_role,test_type,automation_level,objective,prerequisite,manual_steps,expected_result,status,created_at,updated_at)
VALUES
('patient_qualification_to_go','Pacjent: kwalifikacja → GO/HOLD/NO-GO','clinical','critical','coordination','manual','manual','Przejście pacjenta od kwalifikacji do decyzji bramki klinicznej.','Pacjent testowy z konsultacją i planowanym zabiegiem.','1. Otwórz pacjenta.\n2. Potwierdź kwalifikację.\n3. Uruchom workflow operacyjny.\n4. Sprawdź bramkę GO/HOLD/NO-GO.','System pokazuje jednoznaczny status GO, HOLD albo NO-GO oraz brak ręcznych obejść.','active',NOW(),NOW()),
('document_assembly_from_content_blocks','Dokumenty: Content Blocks → Document Instance','documents','critical','coordination','manual','manual','Weryfikacja, że dokument medyczny powstaje z bloków i reguł, nie z Word/PDF.','Aktywne Content Blocks i Rules Matrix.','1. Wybierz typ zabiegu.\n2. Wygeneruj dokument zgody.\n3. Sprawdź manifest źródłowy.','Dokument ma snapshot treści, źródła Content Blocks i wersję reguł.','active',NOW(),NOW()),
('tablet_signature_immutable_archive','Podpis: tablet → immutable archive','consent','critical','coordination','manual','manual','Dowód podpisu jako nieedytowalny rekord, nie luźny podpis graficzny.','Dokument gotowy do podpisu.','1. Otwórz formularz podpisu.\n2. Podpisz jako pacjent testowy.\n3. Sprawdź archiwum podpisów.','Archiwum zawiera snapshot_html, snapshot_sha256/content_sha256 i status locked.','active',NOW(),NOW()),
('or_readiness_no_duplicates','OR Readiness: idempotencja dnia','or','critical','or_coordinator','manual','manual','Jedna sprawa operacyjna ma jeden status gotowości w danym dniu.','Co najmniej 2 sprawy operacyjne w dniu testowym.','1. Uruchom skan OR Readiness dwukrotnie.\n2. Sprawdź listę statusów.','Nie powstają duplikaty dla tego samego readiness_source_key.','active',NOW(),NOW()),
('digital_twin_scenarios','Digital Twin: baseline i scenariusze','or','critical','management','manual','manual','Digital Twin działa jako silnik scenariuszy, nie tylko wizualizacja.','Dzień operacyjny z salą, personelem i PACU.','1. Otwórz OR Digital Twin.\n2. Wygeneruj baseline.\n3. Wygeneruj rekomendowany scenariusz.','Powstają scenariusze z simulation_date, scenario_key, metrykami ryzyka, kosztu i opóźnień.','active',NOW(),NOW()),
('safe_auto_apply_preflight','Safe Auto-Apply: preflight przed zmianą','or','critical','management','manual','manual','Rekomendacje nie zmieniają grafiku bez preflight i śladu decyzji.','Scenariusz Digital Twin ze statusem rekomendowanym.','1. Otwórz Safe Auto-Apply.\n2. Uruchom preflight.\n3. Nie zatwierdzaj bez kontroli.','System zapisuje decyzję, warunki i możliwość rollbacku.','active',NOW(),NOW()),
('mobile_push_registration','OR Mobile Push: rejestracja urządzenia','or','major','or_coordinator','manual','manual','Push działa bez błędu JS i zapisuje subskrypcję w dual-schema.','Przeglądarka z obsługą Service Worker.','1. Otwórz OR Mobile Push.\n2. Włącz powiadomienia.\n3. Sprawdź tabelę subskrypcji.','Subskrypcja ma endpoint_hash i subscription_json albo kompatybilne pola endpoint/p256dh/auth_secret.','active',NOW(),NOW()),
('communication_inbound_case_assignment','Communication Hub: inbound → Case ID','communication','critical','coordination','manual','manual','Wiadomość przychodząca trafia do właściwej sprawy pacjenta.','Wiadomość testowa z tokenem lub Case ID.','1. Zaimportuj wiadomość.\n2. Uruchom triage.\n3. Sprawdź przypisanie.','Wątek jest przypisany do pacjenta/sprawy, a status triage jest audytowalny.','active',NOW(),NOW()),
('postop_aftercare_tasks','Pooperacyjna: wypis → zadania opieki','clinical','major','nursing','manual','manual','Po wypisie system tworzy dalszą opiekę, nie sekretariat ręcznie.','Pacjent po operacji testowej.','1. Zmień etap na wypis.\n2. Sprawdź opiekę pooperacyjną.\n3. Sprawdź zadania.','Powstają zadania i komunikaty pooperacyjne zgodne ze ścieżką.','active',NOW(),NOW()),
('marketing_nps_gate','Marketing/NPS: po regułach klinicznych i zgodach','marketing','major','management','manual','manual','Marketing nie kontaktuje pacjenta przed regułami klinicznymi i zgodami.','Pacjent po opiece pooperacyjnej.','1. Sprawdź zgody komunikacyjne.\n2. Sprawdź status kliniczny.\n3. Uruchom NPS.','NPS/marketing aktywuje się dopiero po spełnieniu reguł zgód i statusu klinicznego.','active',NOW(),NOW()),
('inventory_implant_passport','Implant: magazyn → paszport implantu','inventory','critical','pharmacy','manual','manual','Implant użyty w zabiegu tworzy paszport i ślad LOT/SN.','Zabieg z implantem testowym.','1. Zarezerwuj implant.\n2. Oznacz użycie.\n3. Sprawdź Implant Passport.','Paszport zawiera identyfikację implantu i powiązanie ze sprawą pacjenta.','active',NOW(),NOW()),
('map_digital_twin_operational_state','Mapa szpitala: stan operacyjny zasobów','site','major','management','manual','manual','Mapa jest planszą operacyjną, nie dekoracją.','Aktywne lokalizacje lub SVG.','1. Otwórz mapę szpitala.\n2. Sprawdź sale, PACU, łóżka i ruch pacjentów.','Zasoby i pacjenci są powiązani ze stanem operacyjnym systemu.','active',NOW(),NOW())
ON DUPLICATE KEY UPDATE
  scenario_label=VALUES(scenario_label),
  domain_key=VALUES(domain_key),
  criticality=VALUES(criticality),
  owner_role=VALUES(owner_role),
  objective=VALUES(objective),
  prerequisite=VALUES(prerequisite),
  manual_steps=VALUES(manual_steps),
  expected_result=VALUES(expected_result),
  status='active',
  updated_at=NOW();

INSERT INTO system_modules
(module_key,module_label,domain_key,owner_role,status,route_path,replacement_module_key,source_of_truth,clinical_purpose,ai_mode,version,active,created_at,updated_at)
VALUES
('runtimepreflight','Runtime Preflight','admin','admin','active','/system_runtime_preflight.php',NULL,'database','Produkcyjna kontrola gotowości po integracji 0.78.x.','embedded_ready','0.78.2',1,NOW(),NOW()),
('acceptancetests','Acceptance Tests','admin','admin','active','/system_acceptance_tests.php',NULL,'database','Rejestr scenariuszy akceptacyjnych dla Enterprise Release.','embedded_ready','0.78.2',1,NOW(),NOW())
ON DUPLICATE KEY UPDATE
  module_label=VALUES(module_label), domain_key=VALUES(domain_key), owner_role=VALUES(owner_role), status='active', route_path=VALUES(route_path), clinical_purpose=VALUES(clinical_purpose), version='0.78.2', active=1, updated_at=NOW();

INSERT INTO system_module_routes
(module_key,route_path,route_type,status,requires_role,legacy_redirect_to,created_at,updated_at)
VALUES
('runtimepreflight','/system_runtime_preflight.php','page','active','admin',NULL,NOW(),NOW()),
('acceptancetests','/system_acceptance_tests.php','page','active','admin',NULL,NOW(),NOW())
ON DUPLICATE KEY UPDATE module_key=VALUES(module_key), status='active', requires_role='admin', updated_at=NOW();

INSERT INTO system_feature_flags
(flag_key,flag_value,flag_scope,description,updated_by_user_id,created_at,updated_at)
VALUES
('module_runtimepreflight_enabled','1','global','Feature flag dla modułu Runtime Preflight',NULL,NOW(),NOW()),
('module_acceptancetests_enabled','1','global','Feature flag dla modułu Acceptance Tests',NULL,NOW(),NOW())
ON DUPLICATE KEY UPDATE flag_value='1', description=VALUES(description), updated_at=NOW();

INSERT INTO app_settings (setting_key, setting_value, created_at, updated_at)
VALUES
('core_version','0.78.2',NOW(),NOW()),
('schema_version','0.78.2',NOW(),NOW()),
('enterprise_runtime_preflight_version','0.78.2',NOW(),NOW())
ON DUPLICATE KEY UPDATE setting_value=VALUES(setting_value), updated_at=NOW();

INSERT INTO system_migration_ledger
(migration_key,version,file_path,checksum_sha256,status,applied_by_user_id,applied_at,notes,details_json)
VALUES
('087_core_0_78_2_enterprise_runtime_preflight','0.78.2','database/migrations/087_core_0_78_2_enterprise_runtime_preflight.sql',NULL,'applied',NULL,NOW(),'Enterprise Runtime Preflight applied.',JSON_OBJECT('runtime_preflight', true, 'acceptance_scenarios', true))
ON DUPLICATE KEY UPDATE version=VALUES(version), file_path=VALUES(file_path), status='applied', applied_at=NOW(), notes=VALUES(notes), details_json=VALUES(details_json);
