import type { Core } from '@strapi/strapi';

const DEMO_EMAIL = 'demo@strapi-demo.local';
const DEMO_PASSWORD = 'Demo1234!';

type PermissionMap = Record<string, string[]>;

async function ensurePermissions(
  strapi: Core.Strapi,
  roleType: 'public' | 'authenticated',
  permissions: PermissionMap,
) {
  const role = await strapi.db.query('plugin::users-permissions.role').findOne({
    where: { type: roleType },
  });

  if (!role) return;

  for (const [uid, actions] of Object.entries(permissions)) {
    for (const action of actions) {
      const permissionAction = `${uid}.${action}`;
      const existing = await strapi.db.query('plugin::users-permissions.permission').findOne({
        where: { action: permissionAction, role: role.id },
      });

      if (!existing) {
        await strapi.db.query('plugin::users-permissions.permission').create({
          data: { action: permissionAction, role: role.id },
        });
      }
    }
  }
}

async function ensureDemoUser(strapi: Core.Strapi) {
  const existing = await strapi.db.query('plugin::users-permissions.user').findOne({
    where: { email: DEMO_EMAIL },
  });

  if (existing) return;

  const authenticatedRole = await strapi.db.query('plugin::users-permissions.role').findOne({
    where: { type: 'authenticated' },
  });

  if (!authenticatedRole) return;

  await strapi.plugin('users-permissions').service('user').add({
    username: 'demo',
    email: DEMO_EMAIL,
    password: DEMO_PASSWORD,
    role: authenticatedRole.id,
    confirmed: true,
    provider: 'local',
  });

  strapi.log.info(`Demo user created: ${DEMO_EMAIL} / ${DEMO_PASSWORD}`);
}

async function seedGlobal(strapi: Core.Strapi) {
  const existing = await strapi.documents('api::global.global').findFirst({});

  const data = {
    siteName: 'Strapi Demo',
    siteDescription: 'A small demo site powered by Strapi and Vue.',
    heroTitle: 'Content managed in Strapi',
    heroSubtitle: 'Edit copy, blog posts, and member-only pages from the Strapi admin — no redeploy needed.',
    heroCtaLabel: 'Explore the blog',
    defaultSeo: {
      metaTitle: 'Strapi Demo',
      metaDescription: 'See what Strapi can do with a Vue frontend.',
    },
  };

  if (!existing) {
    await strapi.documents('api::global.global').create({ data });
  } else {
    await strapi.documents('api::global.global').update({
      documentId: existing.documentId,
      data,
    });
  }
}

async function seedAbout(strapi: Core.Strapi) {
  const existing = await strapi.documents('api::about.about').findFirst({});

  if (!existing) {
    await strapi.documents('api::about.about').create({
      data: {
        title: 'About this demo',
        blocks: [
          {
            __component: 'shared.rich-text',
            body: 'This site is a minimal showcase of Strapi as a headless CMS. Public pages load content from the Strapi REST API. The member area is protected — only logged-in users can fetch that content.',
          },
          {
            __component: 'shared.quote',
            title: 'Why Strapi?',
            body: 'Give editors a friendly admin panel while developers keep building with their favorite frontend framework.',
          },
        ],
      } as never,
    });
  }
}

async function seedBlogPosts(strapi: Core.Strapi) {
  const posts = [
    {
      title: 'What is a headless CMS?',
      slug: 'what-is-a-headless-cms',
      excerpt: 'Separate content from presentation and deliver it anywhere via APIs.',
      body: '<p>A headless CMS stores structured content and exposes it through APIs. Your Vue app (or mobile app, or another site) decides how to display it.</p>',
    },
    {
      title: 'Why teams pick Strapi',
      slug: 'why-teams-pick-strapi',
      excerpt: 'Open source, customizable, and quick to set up for prototypes and production.',
      body: '<p>Strapi gives you content types, roles, media library, and plugins out of the box — perfect for demos like this one.</p>',
    },
    {
      title: 'Connecting Vue to Strapi',
      slug: 'connecting-vue-to-strapi',
      excerpt: 'Use the REST API and JWT auth from your frontend.',
      body: '<p>This demo uses fetch with a JWT stored in localStorage. Public endpoints need no token; protected content sends Authorization: Bearer …</p>',
    },
  ];

  for (const post of posts) {
    const existing = await strapi.documents('api::blog-post.blog-post').findFirst({
      filters: { slug: post.slug },
    });

    if (existing) {
      if (!existing.publishedAt) {
        await strapi.documents('api::blog-post.blog-post').publish({
          documentId: existing.documentId,
        });
      }
      continue;
    }

    await strapi.documents('api::blog-post.blog-post').create({
      data: post,
      status: 'published',
    });
  }

  const testPost = await strapi.documents('api::blog-post.blog-post').findFirst({
    filters: { slug: 'test' },
  });
  if (testPost) {
    await strapi.documents('api::blog-post.blog-post').delete({
      documentId: testPost.documentId,
    });
  }
}

async function seedMemberArea(strapi: Core.Strapi) {
  const existing = await strapi.documents('api::member-area.member-area').findFirst({});

  const data = {
    title: 'Welcome, member!',
    content:
      '<p>This page is loaded from Strapi’s <strong>Member Area</strong> single type. The Public role cannot read it — you had to log in so the API returns this content.</p><p>Try changing this text in the Strapi admin under Content Manager → Member Area.</p>',
  };

  if (!existing) {
    await strapi.documents('api::member-area.member-area').create({ data });
  }
}

export async function setupDemo(strapi: Core.Strapi) {
  await ensurePermissions(strapi, 'public', {
    'api::global.global': ['find'],
    'api::about.about': ['find'],
    'api::blog-post.blog-post': ['find', 'findOne'],
  });

  await ensurePermissions(strapi, 'authenticated', {
    'api::member-area.member-area': ['find'],
  });

  await ensureDemoUser(strapi);
  await seedGlobal(strapi);
  await seedAbout(strapi);
  await seedBlogPosts(strapi);
  await seedMemberArea(strapi);

  strapi.log.info('Demo content and permissions are ready.');
}

export { DEMO_EMAIL, DEMO_PASSWORD };
