using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using TakeoutSaaS.Infrastructure.Identity.Persistence;

#nullable disable

namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb;

/// <summary>
/// 写入交易流水菜单与权限定义。
/// </summary>
[DbContext(typeof(IdentityDbContext))]
[Migration("20260304093000_SeedFinanceTransactionMenuAndPermissions")]
public sealed class SeedFinanceTransactionMenuAndPermissions : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql(
            """
            DO $$
            DECLARE
                v_parent_permission_id bigint;
                v_view_permission_id bigint;
                v_detail_permission_id bigint;
                v_export_permission_id bigint;
                v_parent_menu_id bigint;
                v_transaction_menu_id bigint;
                v_permission_seed_base bigint := 840000000000000000;
                v_menu_seed_base bigint := 850000000000000000;
            BEGIN
                -- 1. 确保财务权限分组存在。
                SELECT "Id"
                INTO v_parent_permission_id
                FROM public.permissions
                WHERE "Code" = 'group:tenant:finance'
                ORDER BY "Id"
                LIMIT 1;

                IF v_parent_permission_id IS NULL THEN
                    v_parent_permission_id := v_permission_seed_base + 1;
                    INSERT INTO public.permissions (
                        "Id", "Name", "Code", "Description",
                        "CreatedAt", "UpdatedAt", "DeletedAt",
                        "CreatedBy", "UpdatedBy", "DeletedBy",
                        "ParentId", "SortOrder", "Type", "Portal")
                    VALUES (
                        v_parent_permission_id, '财务中心', 'group:tenant:finance', '财务中心权限分组',
                        NOW(), NULL, NULL,
                        NULL, NULL, NULL,
                        0, 5000, 'group', 1)
                    ON CONFLICT ("Code") DO NOTHING;
                END IF;

                -- 2. Upsert 交易流水查看权限。
                INSERT INTO public.permissions (
                    "Id", "Name", "Code", "Description",
                    "CreatedAt", "UpdatedAt", "DeletedAt",
                    "CreatedBy", "UpdatedBy", "DeletedBy",
                    "ParentId", "SortOrder", "Type", "Portal")
                VALUES (
                    v_permission_seed_base + 11, '交易流水查看', 'tenant:finance:transaction:view', '查看交易流水列表与统计',
                    NOW(), NULL, NULL,
                    NULL, NULL, NULL,
                    v_parent_permission_id, 5010, 'leaf', 1)
                ON CONFLICT ("Code") DO UPDATE
                SET "Name" = EXCLUDED."Name",
                    "Description" = EXCLUDED."Description",
                    "ParentId" = EXCLUDED."ParentId",
                    "SortOrder" = EXCLUDED."SortOrder",
                    "Type" = EXCLUDED."Type",
                    "Portal" = EXCLUDED."Portal",
                    "DeletedAt" = NULL,
                    "DeletedBy" = NULL,
                    "UpdatedAt" = NOW();

                -- 3. Upsert 交易流水详情权限。
                INSERT INTO public.permissions (
                    "Id", "Name", "Code", "Description",
                    "CreatedAt", "UpdatedAt", "DeletedAt",
                    "CreatedBy", "UpdatedBy", "DeletedBy",
                    "ParentId", "SortOrder", "Type", "Portal")
                VALUES (
                    v_permission_seed_base + 12, '交易流水详情', 'tenant:finance:transaction:detail', '查看交易流水详情抽屉',
                    NOW(), NULL, NULL,
                    NULL, NULL, NULL,
                    v_parent_permission_id, 5020, 'leaf', 1)
                ON CONFLICT ("Code") DO UPDATE
                SET "Name" = EXCLUDED."Name",
                    "Description" = EXCLUDED."Description",
                    "ParentId" = EXCLUDED."ParentId",
                    "SortOrder" = EXCLUDED."SortOrder",
                    "Type" = EXCLUDED."Type",
                    "Portal" = EXCLUDED."Portal",
                    "DeletedAt" = NULL,
                    "DeletedBy" = NULL,
                    "UpdatedAt" = NOW();

                -- 4. Upsert 交易流水导出权限。
                INSERT INTO public.permissions (
                    "Id", "Name", "Code", "Description",
                    "CreatedAt", "UpdatedAt", "DeletedAt",
                    "CreatedBy", "UpdatedBy", "DeletedBy",
                    "ParentId", "SortOrder", "Type", "Portal")
                VALUES (
                    v_permission_seed_base + 13, '交易流水导出', 'tenant:finance:transaction:export', '导出交易流水 CSV',
                    NOW(), NULL, NULL,
                    NULL, NULL, NULL,
                    v_parent_permission_id, 5030, 'leaf', 1)
                ON CONFLICT ("Code") DO UPDATE
                SET "Name" = EXCLUDED."Name",
                    "Description" = EXCLUDED."Description",
                    "ParentId" = EXCLUDED."ParentId",
                    "SortOrder" = EXCLUDED."SortOrder",
                    "Type" = EXCLUDED."Type",
                    "Portal" = EXCLUDED."Portal",
                    "DeletedAt" = NULL,
                    "DeletedBy" = NULL,
                    "UpdatedAt" = NOW();

                -- 5. 回填权限 ID。
                SELECT "Id" INTO v_view_permission_id FROM public.permissions WHERE "Code" = 'tenant:finance:transaction:view' LIMIT 1;
                SELECT "Id" INTO v_detail_permission_id FROM public.permissions WHERE "Code" = 'tenant:finance:transaction:detail' LIMIT 1;
                SELECT "Id" INTO v_export_permission_id FROM public.permissions WHERE "Code" = 'tenant:finance:transaction:export' LIMIT 1;

                -- 6. 确保租户端财务父菜单存在。
                SELECT "Id"
                INTO v_parent_menu_id
                FROM public.menu_definitions
                WHERE "Portal" = 1 AND "Path" = '/finance' AND "DeletedAt" IS NULL
                ORDER BY "Id"
                LIMIT 1;

                IF v_parent_menu_id IS NULL THEN
                    v_parent_menu_id := v_menu_seed_base + 1;
                    INSERT INTO public.menu_definitions (
                        "Id", "ParentId", "Name", "Path", "Component", "Title", "Icon",
                        "IsIframe", "Link", "KeepAlive", "SortOrder",
                        "RequiredPermissions", "MetaPermissions", "MetaRoles", "AuthListJson",
                        "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "Portal")
                    VALUES (
                        v_parent_menu_id, 0, 'Finance', '/finance', 'BasicLayout', '财务中心', 'lucide:wallet',
                        FALSE, NULL, FALSE, 500,
                        '', '', '', NULL,
                        NOW(), NULL, NULL, NULL, NULL, NULL, 1)
                    ON CONFLICT ("Id") DO NOTHING;
                END IF;

                -- 7. Upsert 交易流水菜单。
                SELECT "Id"
                INTO v_transaction_menu_id
                FROM public.menu_definitions
                WHERE "Portal" = 1 AND "Path" = '/finance/transaction'
                ORDER BY "DeletedAt" NULLS FIRST, "Id"
                LIMIT 1;

                IF v_transaction_menu_id IS NULL THEN
                    v_transaction_menu_id := v_menu_seed_base + 11;
                    INSERT INTO public.menu_definitions (
                        "Id", "ParentId", "Name", "Path", "Component", "Title", "Icon",
                        "IsIframe", "Link", "KeepAlive", "SortOrder",
                        "RequiredPermissions", "MetaPermissions", "MetaRoles", "AuthListJson",
                        "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "Portal")
                    VALUES (
                        v_transaction_menu_id, v_parent_menu_id, 'TransactionFlow', '/finance/transaction', '/finance/transaction/index', '交易流水', 'lucide:receipt',
                        FALSE, NULL, TRUE, 510,
                        'tenant:finance:transaction:view', 'tenant:finance:transaction:view', '', NULL,
                        NOW(), NULL, NULL, NULL, NULL, NULL, 1)
                    ON CONFLICT ("Id") DO NOTHING;
                ELSE
                    UPDATE public.menu_definitions
                    SET "ParentId" = v_parent_menu_id,
                        "Name" = 'TransactionFlow',
                        "Component" = '/finance/transaction/index',
                        "Title" = '交易流水',
                        "Icon" = 'lucide:receipt',
                        "IsIframe" = FALSE,
                        "Link" = NULL,
                        "KeepAlive" = TRUE,
                        "SortOrder" = 510,
                        "RequiredPermissions" = 'tenant:finance:transaction:view',
                        "MetaPermissions" = 'tenant:finance:transaction:view',
                        "MetaRoles" = '',
                        "DeletedAt" = NULL,
                        "DeletedBy" = NULL,
                        "UpdatedAt" = NOW(),
                        "Portal" = 1
                    WHERE "Id" = v_transaction_menu_id;
                END IF;

                -- 8. 为 tenant-admin 角色直接授予新权限。
                INSERT INTO public.role_permissions (
                    "Id", "RoleId", "PermissionId", "CreatedAt", "UpdatedAt", "DeletedAt",
                    "CreatedBy", "UpdatedBy", "DeletedBy", "TenantId", "Portal")
                SELECT
                    ABS(HASHTEXTEXTENDED('tenant-admin:' || role."Id"::text || ':' || permission_id::text, 0)),
                    role."Id",
                    permission_id,
                    NOW(), NULL, NULL,
                    NULL, NULL, NULL,
                    role."TenantId",
                    1
                FROM public.roles role
                CROSS JOIN LATERAL (
                    SELECT UNNEST(ARRAY[v_view_permission_id, v_detail_permission_id, v_export_permission_id]) AS permission_id
                ) item
                WHERE role."Code" = 'tenant-admin'
                  AND role."DeletedAt" IS NULL
                  AND item.permission_id IS NOT NULL
                ON CONFLICT ("RoleId", "PermissionId") DO UPDATE
                SET "DeletedAt" = NULL,
                    "DeletedBy" = NULL,
                    "UpdatedAt" = NOW(),
                    "Portal" = 1;

                -- 9. 将旧财务权限角色映射到新交易流水查看/详情权限。
                INSERT INTO public.role_permissions (
                    "Id", "RoleId", "PermissionId", "CreatedAt", "UpdatedAt", "DeletedAt",
                    "CreatedBy", "UpdatedBy", "DeletedBy", "TenantId", "Portal")
                SELECT
                    ABS(HASHTEXTEXTENDED('legacy-view:' || source."RoleId"::text || ':' || item.permission_id::text, 0)),
                    source."RoleId",
                    item.permission_id,
                    NOW(), NULL, NULL,
                    NULL, NULL, NULL,
                    source."TenantId",
                    1
                FROM (
                    SELECT DISTINCT rp."RoleId", rp."TenantId"
                    FROM public.role_permissions rp
                    JOIN public.permissions p ON p."Id" = rp."PermissionId"
                    WHERE p."Code" IN ('tenant:finance:statement:view', 'tenant:finance:income:view')
                      AND rp."DeletedAt" IS NULL
                ) source
                CROSS JOIN LATERAL (
                    SELECT UNNEST(ARRAY[v_view_permission_id, v_detail_permission_id]) AS permission_id
                ) item
                WHERE item.permission_id IS NOT NULL
                ON CONFLICT ("RoleId", "PermissionId") DO UPDATE
                SET "DeletedAt" = NULL,
                    "DeletedBy" = NULL,
                    "UpdatedAt" = NOW(),
                    "Portal" = 1;

                -- 10. 将旧导出权限角色映射到新交易流水导出权限。
                INSERT INTO public.role_permissions (
                    "Id", "RoleId", "PermissionId", "CreatedAt", "UpdatedAt", "DeletedAt",
                    "CreatedBy", "UpdatedBy", "DeletedBy", "TenantId", "Portal")
                SELECT
                    ABS(HASHTEXTEXTENDED('legacy-export:' || source."RoleId"::text || ':' || v_export_permission_id::text, 0)),
                    source."RoleId",
                    v_export_permission_id,
                    NOW(), NULL, NULL,
                    NULL, NULL, NULL,
                    source."TenantId",
                    1
                FROM (
                    SELECT DISTINCT rp."RoleId", rp."TenantId"
                    FROM public.role_permissions rp
                    JOIN public.permissions p ON p."Id" = rp."PermissionId"
                    WHERE p."Code" IN ('tenant:finance:statement:export', 'tenant:finance:income:export')
                      AND rp."DeletedAt" IS NULL
                ) source
                WHERE v_export_permission_id IS NOT NULL
                ON CONFLICT ("RoleId", "PermissionId") DO UPDATE
                SET "DeletedAt" = NULL,
                    "DeletedBy" = NULL,
                    "UpdatedAt" = NOW(),
                    "Portal" = 1;
            END $$;
            """);
    }

    /// <inheritdoc />
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql(
            """
            DO $$
            BEGIN
                DELETE FROM public.role_permissions
                WHERE "PermissionId" IN (
                    SELECT "Id"
                    FROM public.permissions
                    WHERE "Code" IN (
                        'tenant:finance:transaction:view',
                        'tenant:finance:transaction:detail',
                        'tenant:finance:transaction:export'));

                DELETE FROM public.menu_definitions
                WHERE "Portal" = 1 AND "Path" = '/finance/transaction';

                DELETE FROM public.permissions
                WHERE "Code" IN (
                    'tenant:finance:transaction:view',
                    'tenant:finance:transaction:detail',
                    'tenant:finance:transaction:export');
            END $$;
            """);
    }
}
