/**
 * page-manage.ts — 页面与资源绑定管理
 *
 * Usage:
 *
 *   ── 创建页面 ──────────────────────────────────────────────────────────────────
 *   ts-node scripts/page-manage.ts create \
 *     --pageCode    myModule        (required)
 *     --pageName    myModule        (optional, defaults to pageCode)
 *     --zhName      "我的模块"       (optional)
 *     --enName      "My Module"     (optional)
 *     --parentPageCode  admin       (optional)
 *     --sortOrder   1080            (optional, defaults to 9999)
 *     --resources   myModule,other  (optional, comma-separated — binds resources)
 *
 *   ── 更新页面 ──────────────────────────────────────────────────────────────────
 *   ts-node scripts/page-manage.ts update \
 *     --pageCode    myModule        (required)
 *     --pageName    newName         (optional)
 *     --zhName      "新名称"         (optional)
 *     --enName      "New Name"      (optional)
 *     --sortOrder   1090            (optional)
 *     --parentPageCode  game        (optional)
 *
 *   ── 删除页面 ──────────────────────────────────────────────────────────────────
 *   ts-node scripts/page-manage.ts delete \
 *     --pageCode    myModule        (required)
 *
 *   ── 绑定资源 ──────────────────────────────────────────────────────────────────
 *   ts-node scripts/page-manage.ts bind \
 *     --pageCode    myModule        (required)
 *     --resources   res1,res2       (required)
 *
 *   ── 解绑资源 ──────────────────────────────────────────────────────────────────
 *   ts-node scripts/page-manage.ts unbind \
 *     --pageCode    myModule        (required)
 *     --resources   res1,res2       (required)
 */

import { PrismaClient } from '@prisma/client';
import { bindResourceToPage, upsertPage } from './lib/page-helpers';

const prisma = new PrismaClient();

// ─── Arg parser ───────────────────────────────────────────────────────────────

function parseArgs(): { action: string; flags: Record<string, string> } {
  const argv = process.argv.slice(2);
  const action = argv[0] && !argv[0].startsWith('--') ? argv[0] : '';
  const flags: Record<string, string> = {};
  for (let i = action ? 1 : 0; i < argv.length; i++) {
    if (argv[i].startsWith('--')) {
      const key = argv[i].slice(2);
      const next = argv[i + 1];
      flags[key] = next && !next.startsWith('--') ? argv[++i] : 'true';
    }
  }
  return { action, flags };
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

async function resolveParent(parentPageCode: string): Promise<number> {
  const parent = await prisma.page.findUnique({
    where: { code: parentPageCode },
  });
  if (!parent) {
    console.error(
      `[page-manage] Parent page "${parentPageCode}" not found in DB.`,
    );
    process.exit(1);
  }
  return parent.id;
}

async function requirePage(pageCode: string) {
  const page = await prisma.page.findUnique({ where: { code: pageCode } });
  if (!page) {
    console.error(`[page-manage] Page "${pageCode}" not found in DB.`);
    process.exit(1);
  }
  return page;
}

// ─── Actions ──────────────────────────────────────────────────────────────────

async function actionCreate(flags: Record<string, string>) {
  const {
    pageCode,
    pageName,
    zhName,
    enName,
    parentPageCode,
    resources,
    sortOrder,
  } = flags;
  if (!pageCode) {
    console.error('[page-manage] --pageCode is required.');
    process.exit(1);
  }

  const parentId = parentPageCode
    ? await resolveParent(parentPageCode)
    : undefined;

  const page = await upsertPage(prisma, {
    code: pageCode,
    name: pageName || pageCode,
    zhName: zhName || pageCode,
    enName: enName || pageCode,
    sortOrder: sortOrder ? parseInt(sortOrder, 10) : 9999,
    parentId,
  });

  const wasCreated =
    Math.abs(page.createdAt.getTime() - page.updatedAt.getTime()) < 1000;
  if (wasCreated) {
    console.log(`[page-manage] ✚ Created page: ${pageCode} (id=${page.id})`);
  } else {
    console.log(
      `[page-manage] · Page already exists: ${pageCode} (id=${page.id}) — skipped`,
    );
  }

  if (resources) {
    const codes = resources
      .split(',')
      .map((s) => s.trim())
      .filter(Boolean);
    for (const code of codes) {
      await bindResourceToPage(
        prisma,
        page.id,
        code,
        `${code} resource (bound to page ${pageCode})`,
      );
      console.log(
        `[page-manage]   PageResource: page(${pageCode}) ↔ resource(${code})`,
      );
    }
  }
}

async function actionUpdate(flags: Record<string, string>) {
  const { pageCode, pageName, zhName, enName, parentPageCode, sortOrder } =
    flags;
  if (!pageCode) {
    console.error('[page-manage] --pageCode is required.');
    process.exit(1);
  }

  const page = await requirePage(pageCode);

  const data: Record<string, unknown> = {};
  if (pageName !== undefined) data.name = pageName;
  if (zhName !== undefined) data.zhName = zhName;
  if (enName !== undefined) data.enName = enName;
  if (sortOrder !== undefined) data.sortOrder = parseInt(sortOrder, 10);
  if (parentPageCode !== undefined)
    data.parentId = await resolveParent(parentPageCode);

  if (Object.keys(data).length === 0) {
    console.log(
      '[page-manage] No fields to update. Pass at least one of: --pageName --zhName --enName --sortOrder --parentPageCode',
    );
    process.exit(0);
  }

  await prisma.page.update({ where: { id: page.id }, data });
  console.log(
    `[page-manage] ✎ Updated page: ${pageCode} (id=${page.id})`,
    data,
  );
}

async function actionDelete(flags: Record<string, string>) {
  const { pageCode } = flags;
  if (!pageCode) {
    console.error('[page-manage] --pageCode is required.');
    process.exit(1);
  }

  const page = await requirePage(pageCode);

  await prisma.pageResource.deleteMany({ where: { pageId: page.id } });
  await prisma.rolePages.deleteMany({ where: { pageId: page.id } });
  await prisma.page.delete({ where: { id: page.id } });

  console.log(
    `[page-manage] ✖ Deleted page: ${pageCode} (id=${page.id}) + its PageResource + RolePages rows`,
  );
}

async function actionBind(flags: Record<string, string>) {
  const { pageCode, resources } = flags;
  if (!pageCode) {
    console.error('[page-manage] --pageCode is required.');
    process.exit(1);
  }
  if (!resources) {
    console.error('[page-manage] --resources is required.');
    process.exit(1);
  }

  const page = await requirePage(pageCode);
  const codes = resources
    .split(',')
    .map((s) => s.trim())
    .filter(Boolean);

  for (const code of codes) {
    await bindResourceToPage(
      prisma,
      page.id,
      code,
      `${code} resource (bound to page ${pageCode})`,
    );
    console.log(
      `[page-manage]   PageResource: page(${pageCode}) ↔ resource(${code})`,
    );
  }
  console.log(
    `[page-manage] ✅ Bound ${codes.length} resource(s) to page: ${pageCode}`,
  );
}

async function actionUnbind(flags: Record<string, string>) {
  const { pageCode, resources } = flags;
  if (!pageCode) {
    console.error('[page-manage] --pageCode is required.');
    process.exit(1);
  }
  if (!resources) {
    console.error('[page-manage] --resources is required.');
    process.exit(1);
  }

  const page = await requirePage(pageCode);
  const codes = resources
    .split(',')
    .map((s) => s.trim())
    .filter(Boolean);

  for (const code of codes) {
    const resource = await prisma.resource.findUnique({ where: { code } });
    if (!resource) {
      console.warn(`[page-manage]   ⚠ Resource "${code}" not found — skipped`);
      continue;
    }
    await prisma.pageResource.deleteMany({
      where: { pageId: page.id, resourceId: resource.id },
    });
    console.log(
      `[page-manage]   Unbound: page(${pageCode}) ↔ resource(${code})`,
    );
  }
  console.log(`[page-manage] ✅ Done.`);
}

// ─── Entry point ──────────────────────────────────────────────────────────────

const ACTIONS: Record<string, (f: Record<string, string>) => Promise<void>> = {
  create: actionCreate,
  update: actionUpdate,
  delete: actionDelete,
  bind: actionBind,
  unbind: actionUnbind,
};

async function main() {
  const { action, flags } = parseArgs();
  const handler = ACTIONS[action];
  if (!handler) {
    console.error(
      `[page-manage] Unknown action: "${action}". Valid actions: ${Object.keys(
        ACTIONS,
      ).join(', ')}`,
    );
    process.exit(1);
  }
  await handler(flags);
  console.log('[page-manage] ✅ Done.');
}

main()
  .catch((e) => {
    console.error('[page-manage] Fatal error:', e);
    process.exit(1);
  })
  .finally(() => prisma.$disconnect());
