-- ============================================================================
-- 本地开发种子：root OU + 通知收件用户
--
-- 用途
--   appsettings.local.json 的 AppConfig:Portal:EditionOUMappings 里，EditionId="root"
--   映射到 OU `3A0971B1-75B7-C43A-F39D-3CED32E0DF30`。该 ID 来自 dev 环境（这份配置是
--   Nacos 改造前的 dev 快照），本地种子库里并没有这个 OU。
--
-- 不跑这个脚本会怎样
--   门户订单支付后自动建租户会失败，且报错极具误导性：
--     CustomTenantController.CreateAsync 最后一步「发邮件给 root OU」
--       → _organizationUnitRepository.FindAsync(ouid) 返回 null
--       → GetMembersAsync(null) 在 EF 表达式求值时抛 NullReferenceException
--       → 接口 500 → OrderService.CreateTenant 捕获 → 整个事务回滚
--   现象是：订单已支付(PaymentStatus=200)，但 Orders.TargetTenantID 为 NULL、
--   SaasTenants 里查无此租户，AMLPortal_TenantEventQueues 留下一条 Status=300(重试中)。
--   日志里只有 "An exception was thrown while attempting to evaluate a LINQ query
--   parameter expression"，很难联想到是缺一条 OU 数据。
--   （GetParentAgentList 里也有同一段 root OU 逻辑，同样依赖它。）
--
-- 何时执行
--   任何一次重建本地库之后，都要跑一遍：
--     · `docker compose -f docker-compose.local.yml down -v`（EF 迁移 + 代码种子重建）
--     · 或 RESTORE `AML-local-dev.bak`（目前本地库的实际数据来源）
--   两条路都不会带出这条 OU：它既不在代码种子里（属环境数据），那份 .bak 里也没有。
--
-- 执行方式
--   docker exec -i aml-mssql /opt/mssql-tools18/bin/sqlcmd \
--     -S localhost -U sa -P "Aml@Local2026" -C -d AbpAML \
--     -i /dev/stdin < seed-root-ou.sql
--
--   或先 docker cp 进容器再 -i 指定路径。
--
-- 幂等：可重复执行，已存在则跳过。
-- ============================================================================

SET NOCOUNT ON;

-- 收件邮箱：租户创建成功的通知会真实发送到这里（经 iCS(stag) → smtp.yandex.com，
-- 不走 appsettings 里的 Abp.Mailing.Smtp，那个 127.0.0.1:25 本地并不存在）。
-- 想换收件人改这里即可。
DECLARE @NotifyEmail nvarchar(256) = N'f-r-x@163.com';
DECLARE @UserName    nvarchar(256) = N'local-sales-admin';

-- 必须与 appsettings.local.json 中 EditionOUMappings[EditionId="root"].OUIDs[0] 一致
DECLARE @OuId uniqueidentifier = '3A0971B1-75B7-C43A-F39D-3CED32E0DF30';
DECLARE @UserId uniqueidentifier;

BEGIN TRAN;

-- 1) root OU（host 级：TenantId / ParentId 均为 NULL）
--    Code 只需在 host 范围内不与现有 OU 冲突；种子数据已占用 00001~00003。
IF NOT EXISTS (SELECT 1 FROM AbpOrganizationUnits WHERE Id = @OuId)
BEGIN
    INSERT INTO AbpOrganizationUnits
        (Id, TenantId, ParentId, Code, DisplayName, ExtraProperties, ConcurrencyStamp, CreationTime, IsDeleted)
    VALUES
        (@OuId, NULL, NULL, N'00099', N'Local Root OU (sales admin)', N'{}',
         CONVERT(nvarchar(40), NEWID()), GETDATE(), 0);
    PRINT '[seed] AbpOrganizationUnits: root OU created';
END
ELSE
    PRINT '[seed] AbpOrganizationUnits: root OU already exists, skipped';

-- 2) 通知收件用户（host 级，不设密码 —— 仅用于被 GetMembersAsync 查到并取 Email/UserName）
SELECT @UserId = Id FROM AbpUsers WHERE TenantId IS NULL AND NormalizedEmail = UPPER(@NotifyEmail);

IF @UserId IS NULL
BEGIN
    SET @UserId = NEWID();
    INSERT INTO AbpUsers
        (Id, TenantId, UserName, NormalizedUserName, Name, Email, NormalizedEmail, EmailConfirmed,
         PasswordHash, SecurityStamp, IsExternal, PhoneNumberConfirmed, TwoFactorEnabled,
         LockoutEnabled, AccessFailedCount, ExtraProperties, ConcurrencyStamp, CreationTime, IsDeleted)
    VALUES
        (@UserId, NULL, @UserName, UPPER(@UserName), N'Local Sales Admin', @NotifyEmail, UPPER(@NotifyEmail), 1,
         NULL, CONVERT(nvarchar(40), NEWID()), 0, 0, 0,
         0, 0, N'{}', CONVERT(nvarchar(40), NEWID()), GETDATE(), 0);
    PRINT '[seed] AbpUsers: notify user created';
END
ELSE
    PRINT '[seed] AbpUsers: notify user already exists, skipped';

-- 3) 用户挂到 OU 下（FindAllParentAgentsFromOU 靠这层关联找人）
IF NOT EXISTS (SELECT 1 FROM AbpUserOrganizationUnits WHERE UserId = @UserId AND OrganizationUnitId = @OuId)
BEGIN
    INSERT INTO AbpUserOrganizationUnits (UserId, OrganizationUnitId, TenantId, CreationTime)
    VALUES (@UserId, @OuId, NULL, GETDATE());
    PRINT '[seed] AbpUserOrganizationUnits: membership created';
END
ELSE
    PRINT '[seed] AbpUserOrganizationUnits: membership already exists, skipped';

COMMIT;

-- 验证：应返回恰好一行
SELECT u.UserName, u.Email, ou.DisplayName, ou.Code
FROM AbpUsers u
JOIN AbpUserOrganizationUnits uo ON uo.UserId = u.Id
JOIN AbpOrganizationUnits ou     ON ou.Id = uo.OrganizationUnitId
WHERE ou.Id = @OuId;
