import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

const baseUrl = process.env.MOD_CMS_URL?.replace(/\/$/, '');
const adminToken = process.env.MOD_CMS_ADMIN_TOKEN;

if (!baseUrl) {
  console.error('MOD_CMS_URL is required (e.g. https://mod-cms-preview.example.workers.dev)');
  process.exit(1);
}
if (!adminToken) {
  console.error('MOD_CMS_ADMIN_TOKEN is required');
  process.exit(1);
}

type ApiErrorBody = {
  error?: {
    message?: string;
  };
};

async function adminFetch(path: string, init: RequestInit = {}): Promise<unknown> {
  const headers = new Headers(init.headers);
  headers.set('Authorization', `Bearer ${adminToken}`);
  if (init.body && !headers.has('Content-Type')) {
    headers.set('Content-Type', 'application/json');
  }

  const response = await fetch(`${baseUrl}${path}`, { ...init, headers });
  const text = await response.text();
  let data: unknown = null;
  if (text) {
    try {
      data = JSON.parse(text);
    } catch {
      data = text;
    }
  }

  if (!response.ok) {
    const message =
      typeof data === 'object' &&
      data !== null &&
      'error' in data &&
      typeof (data as ApiErrorBody).error?.message === 'string'
        ? (data as ApiErrorBody).error!.message!
        : `HTTP ${response.status}`;
    throw new Error(message);
  }

  return data;
}

function textResult(data: unknown) {
  return {
    content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }],
  };
}

const server = new McpServer({ name: 'mod-cms', version: '0.0.0' });

server.registerTool(
  'create_post',
  {
    description: 'Create or update a content entry via POST /api/admin/content',
    inputSchema: {
      slug: z.string().describe('URL slug (kebab-case)'),
      type: z.string().describe('Content type (e.g. post)'),
      title: z.string().describe('Entry title'),
      body: z.string().optional().describe('HTML or markdown body'),
      category: z.string().optional().describe('Single category label'),
      tag: z.string().optional().describe('Single tag label'),
    },
  },
  async (args) => textResult(await adminFetch('/api/admin/content', { method: 'POST', body: JSON.stringify(args) })),
);

server.registerTool(
  'publish_post',
  {
    description: 'Publish a draft entry via POST /api/admin/publish',
    inputSchema: {
      id: z.string().describe('Content entry UUID'),
    },
  },
  async ({ id }) => textResult(await adminFetch('/api/admin/publish', { method: 'POST', body: JSON.stringify({ id }) })),
);

server.registerTool(
  'schedule_post',
  {
    description: 'Schedule an entry for future publication via POST /api/admin/schedule',
    inputSchema: {
      id: z.string().describe('Content entry UUID'),
      at: z.string().describe('ISO-8601 datetime for scheduled publish'),
    },
  },
  async ({ id, at }) =>
    textResult(await adminFetch('/api/admin/schedule', { method: 'POST', body: JSON.stringify({ id, at }) })),
);

server.registerTool(
  'unpublish_post',
  {
    description: 'Revert a published entry to draft via POST /api/admin/unpublish',
    inputSchema: {
      id: z.string().describe('Content entry UUID'),
    },
  },
  async ({ id }) => textResult(await adminFetch('/api/admin/unpublish', { method: 'POST', body: JSON.stringify({ id }) })),
);

server.registerTool(
  'remove_post',
  {
    description: 'Delete a content entry via DELETE /api/admin/remove',
    inputSchema: {
      id: z.string().describe('Content entry UUID'),
    },
  },
  async ({ id }) => textResult(await adminFetch('/api/admin/remove', { method: 'DELETE', body: JSON.stringify({ id }) })),
);

server.registerTool(
  'list_posts',
  {
    description: 'List content entries via GET /api/admin/content',
    inputSchema: {
      status: z.string().optional().describe('Filter by status: draft | published | scheduled'),
      type: z.string().optional().describe('Filter by content type'),
    },
  },
  async ({ status, type }) => {
    const params = new URLSearchParams();
    if (status) params.set('status', status);
    if (type) params.set('type', type);
    const qs = params.toString();
    return textResult(await adminFetch(`/api/admin/content${qs ? `?${qs}` : ''}`));
  },
);

server.registerTool(
  'get_settings',
  {
    description: 'Read all site settings via GET /api/admin/settings',
    inputSchema: {},
  },
  async () => textResult(await adminFetch('/api/admin/settings')),
);

server.registerTool(
  'set_setting',
  {
    description: 'Upsert a site setting via PUT /api/admin/settings',
    inputSchema: {
      key: z.string().describe('Setting key'),
      value: z.unknown().describe('JSON-serializable setting value'),
    },
  },
  async ({ key, value }) =>
    textResult(await adminFetch('/api/admin/settings', { method: 'PUT', body: JSON.stringify({ key, value }) })),
);

const transport = new StdioServerTransport();
await server.connect(transport);
