-- docker-dev cluster seed. Idempotent — safe to re-run on every `docker compose up`.
--
-- Populates:
--   ServerCluster   MAIN, SITE-A, SITE-B
--   ClusterNode     driver-a, driver-b  → MAIN
--                   site-a-1, site-a-2  → SITE-A
--                   site-b-1, site-b-2  → SITE-B
--
-- ServerCluster.NodeCount + RedundancyMode are coupled by CHECK constraint:
--   NodeCount=1 ⇒ RedundancyMode='None'
--   NodeCount=2 ⇒ RedundancyMode∈('Warm','Hot')
--
-- Each ClusterNode.ApplicationUri MUST be globally unique (UX_ClusterNode_ApplicationUri).
-- Convention: urn:OtOpcUa:<NodeId>.
--
-- Host = Compose service name (resolves inside the otopcua-dev network).
-- OpcUaPort stays at the container-internal 4840; the host-side port mapping is in
-- docker-compose.yml ports: blocks and is irrelevant to ClusterNode rows.

SET NOCOUNT ON;
SET XACT_ABORT ON;

BEGIN TRANSACTION;

------------------------------------------------------------------------------
-- ServerCluster
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT 1 FROM dbo.ServerCluster WHERE ClusterId = 'MAIN')
    INSERT INTO dbo.ServerCluster
        (ClusterId, Name, Enterprise, Site, NodeCount, RedundancyMode, Enabled, Notes, CreatedBy)
    VALUES
        ('MAIN', 'Main cluster', 'zb', 'docker-dev',
         2, 'Warm', 1,
         'docker-dev seed — admin-a/admin-b control-plane, driver-a/driver-b OPC UA publishers.',
         'docker-dev-seed');

IF NOT EXISTS (SELECT 1 FROM dbo.ServerCluster WHERE ClusterId = 'SITE-A')
    INSERT INTO dbo.ServerCluster
        (ClusterId, Name, Enterprise, Site, NodeCount, RedundancyMode, Enabled, Notes, CreatedBy)
    VALUES
        ('SITE-A', 'Site A', 'zb', 'site-a',
         2, 'Warm', 1,
         'docker-dev seed — 2-node fused admin+driver cluster.',
         'docker-dev-seed');

IF NOT EXISTS (SELECT 1 FROM dbo.ServerCluster WHERE ClusterId = 'SITE-B')
    INSERT INTO dbo.ServerCluster
        (ClusterId, Name, Enterprise, Site, NodeCount, RedundancyMode, Enabled, Notes, CreatedBy)
    VALUES
        ('SITE-B', 'Site B', 'zb', 'site-b',
         2, 'Warm', 1,
         'docker-dev seed — 2-node fused admin+driver cluster.',
         'docker-dev-seed');

------------------------------------------------------------------------------
-- ClusterNode — main cluster OPC UA publishers
--
-- NodeId is "<compose-service>:4053" so it matches what ClusterRoleInfo +
-- ConfigPublishCoordinator derive from Akka.Cluster.Get(system).State.Members
-- (member.Address.Host:Port). NodeDeploymentState.NodeId is FK-bound to
-- ClusterNode.NodeId; mismatched values cause FK 547 on deploy.
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'driver-a:4053')
    INSERT INTO dbo.ClusterNode
        (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
    VALUES ('driver-a:4053', 'MAIN', 'driver-a', 4840, 8081, 'urn:OtOpcUa:driver-a', 200, 1, 'docker-dev-seed');

IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'driver-b:4053')
    INSERT INTO dbo.ClusterNode
        (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
    VALUES ('driver-b:4053', 'MAIN', 'driver-b', 4840, 8081, 'urn:OtOpcUa:driver-b', 150, 1, 'docker-dev-seed');

------------------------------------------------------------------------------
-- ClusterNode — site A
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-a-1:4053')
    INSERT INTO dbo.ClusterNode
        (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
    VALUES ('site-a-1:4053', 'SITE-A', 'site-a-1', 4840, 8081, 'urn:OtOpcUa:site-a-1', 200, 1, 'docker-dev-seed');

IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-a-2:4053')
    INSERT INTO dbo.ClusterNode
        (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
    VALUES ('site-a-2:4053', 'SITE-A', 'site-a-2', 4840, 8081, 'urn:OtOpcUa:site-a-2', 150, 1, 'docker-dev-seed');

------------------------------------------------------------------------------
-- ClusterNode — site B
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-b-1:4053')
    INSERT INTO dbo.ClusterNode
        (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
    VALUES ('site-b-1:4053', 'SITE-B', 'site-b-1', 4840, 8081, 'urn:OtOpcUa:site-b-1', 200, 1, 'docker-dev-seed');

IF NOT EXISTS (SELECT 1 FROM dbo.ClusterNode WHERE NodeId = 'site-b-2:4053')
    INSERT INTO dbo.ClusterNode
        (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
    VALUES ('site-b-2:4053', 'SITE-B', 'site-b-2', 4840, 8081, 'urn:OtOpcUa:site-b-2', 150, 1, 'docker-dev-seed');

------------------------------------------------------------------------------
-- Galaxy MxAccess gateway — MAIN cluster
--
-- Namespace.Kind=SystemPlatform is required for Galaxy/MXAccess data per
-- decision #107; raw equipment drivers use Equipment. DriverInstance points
-- at the external mxaccessgw process. The driver code lives in this repo
-- (.NET 10, cross-platform); only the gateway worker needs Windows.
--
-- ApiKeySecretRef = env:GALAXY_MXGW_API_KEY → resolved at runtime by
-- GalaxyDriver.ResolveApiKey. The env var is set on every driver-role
-- container in docker-compose.yml.
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT 1 FROM dbo.Namespace WHERE NamespaceId = 'MAIN-galaxy')
    INSERT INTO dbo.Namespace
        (NamespaceRowId, NamespaceId, ClusterId, Kind, NamespaceUri, Enabled, Notes)
    VALUES
        (NEWID(), 'MAIN-galaxy', 'MAIN', 'SystemPlatform',
         'urn:zb:docker-dev:galaxy', 1,
         'docker-dev seed — Galaxy / MXAccess namespace served by the MAIN cluster.');

IF NOT EXISTS (SELECT 1 FROM dbo.DriverInstance WHERE DriverInstanceId = 'MAIN-galaxy-mxgw')
    INSERT INTO dbo.DriverInstance
        (DriverInstanceRowId, DriverInstanceId, ClusterId, NamespaceId, Name, DriverType, Enabled, DriverConfig)
    VALUES
        (NEWID(), 'MAIN-galaxy-mxgw', 'MAIN', 'MAIN-galaxy',
         'MxAccess gateway (10.100.0.48:5120)', 'GalaxyMxGateway', 1,
         N'{
  "Gateway": {
    "Endpoint": "http://10.100.0.48:5120",
    "ApiKeySecretRef": "env:GALAXY_MXGW_API_KEY",
    "UseTls": false,
    "ConnectTimeoutSeconds": 10,
    "DefaultCallTimeoutSeconds": 30
  },
  "MxAccess": {
    "ClientName": "OtOpcUa-MAIN-docker-dev",
    "PublishingIntervalMs": 1000
  },
  "Repository": {
    "DiscoverPageSize": 5000,
    "WatchDeployEvents": true
  },
  "Reconnect": {
    "InitialBackoffMs": 500,
    "MaxBackoffMs": 30000,
    "ReplayOnSessionLost": true
  }
}');

------------------------------------------------------------------------------
-- Galaxy test tags — TestMachine_001.TestAlarm001..003
--
-- SystemPlatform-namespace tags have EquipmentId=NULL and use FolderPath +
-- Name to address the MXAccess item. The Galaxy driver subscribes via the
-- "FolderPath.Name" MXAccess reference form; OPC UA browse path is the
-- equivalent "FolderPath/Name" under the SystemPlatform namespace.
------------------------------------------------------------------------------

IF NOT EXISTS (SELECT 1 FROM dbo.Tag WHERE TagId = 'MAIN-galaxy-TestMachine_001-TestAlarm001')
    INSERT INTO dbo.Tag
        (TagRowId, TagId, DriverInstanceId, DeviceId, EquipmentId, Name, FolderPath, DataType, AccessLevel, WriteIdempotent, PollGroupId, TagConfig)
    VALUES
        (NEWID(), 'MAIN-galaxy-TestMachine_001-TestAlarm001', 'MAIN-galaxy-mxgw', NULL, NULL,
         'TestAlarm001', 'TestMachine_001', 'Boolean', 0, 0, NULL, N'{}');

IF NOT EXISTS (SELECT 1 FROM dbo.Tag WHERE TagId = 'MAIN-galaxy-TestMachine_001-TestAlarm002')
    INSERT INTO dbo.Tag
        (TagRowId, TagId, DriverInstanceId, DeviceId, EquipmentId, Name, FolderPath, DataType, AccessLevel, WriteIdempotent, PollGroupId, TagConfig)
    VALUES
        (NEWID(), 'MAIN-galaxy-TestMachine_001-TestAlarm002', 'MAIN-galaxy-mxgw', NULL, NULL,
         'TestAlarm002', 'TestMachine_001', 'Boolean', 0, 0, NULL, N'{}');

IF NOT EXISTS (SELECT 1 FROM dbo.Tag WHERE TagId = 'MAIN-galaxy-TestMachine_001-TestAlarm003')
    INSERT INTO dbo.Tag
        (TagRowId, TagId, DriverInstanceId, DeviceId, EquipmentId, Name, FolderPath, DataType, AccessLevel, WriteIdempotent, PollGroupId, TagConfig)
    VALUES
        (NEWID(), 'MAIN-galaxy-TestMachine_001-TestAlarm003', 'MAIN-galaxy-mxgw', NULL, NULL,
         'TestAlarm003', 'TestMachine_001', 'Boolean', 0, 0, NULL, N'{}');

COMMIT TRANSACTION;

------------------------------------------------------------------------------
-- Summary (logged by sqlcmd output)
------------------------------------------------------------------------------

SELECT ClusterId, Name, NodeCount, RedundancyMode FROM dbo.ServerCluster ORDER BY ClusterId;
SELECT NodeId, ClusterId, Host, OpcUaPort, ApplicationUri, ServiceLevelBase
  FROM dbo.ClusterNode ORDER BY ClusterId, NodeId;
SELECT NamespaceId, ClusterId, Kind, NamespaceUri FROM dbo.Namespace ORDER BY ClusterId, NamespaceId;
SELECT DriverInstanceId, ClusterId, DriverType, NamespaceId, Name
  FROM dbo.DriverInstance ORDER BY ClusterId, DriverInstanceId;
SELECT TagId, DriverInstanceId, FolderPath, Name, DataType FROM dbo.Tag ORDER BY DriverInstanceId, FolderPath, Name;
