/**
 * Skills Routes
 *
 * REST API endpoints for skill management.
 */

import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
import type { AppContext } from '../router.js';
import { getSkillRegistry, type Skill, type SkillInfo } from '../../skills/index.js';

export const skillsRoutes = new Hono<AppContext>();

/**
 * Create skill request schema
 */
const CreateSkillSchema = z.object({
  name: z.string().min(1).max(64).regex(/^[a-z][a-z0-9_-]*$/),
  description: z.string(),
  userInvocable: z.boolean().default(true),
  tools: z.array(z.string()).default([]),
  instructions: z.string().optional(),
});

/**
 * Invoke skill request schema
 */
const InvokeSkillSchema = z.object({
  args: z.string().default(''),
});

/**
 * Convert Skill to SkillInfo
 */
function toSkillInfo(skill: Skill): SkillInfo {
  return {
    name: skill.name,
    description: skill.description,
    userInvocable: skill.userInvocable,
    tools: skill.tools,
    path: skill.filePath ?? '',
    exists: true,
    builtin: skill.builtin,
  };
}

/**
 * GET /skills - List all skills
 */
skillsRoutes.get('/', async (c) => {
  const repoRoot = c.get('repoRoot');
  const registry = getSkillRegistry({ repoRoot });

  try {
    const skills = await registry.getAllSkills();
    const skillList = Array.from(skills.values()).map(toSkillInfo);

    return c.json({
      skills: skillList,
      total: skillList.length,
    });
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      500
    );
  }
});

/**
 * GET /skills/invocable - List user-invocable skills
 */
skillsRoutes.get('/invocable', async (c) => {
  const repoRoot = c.get('repoRoot');
  const registry = getSkillRegistry({ repoRoot });

  try {
    const skills = await registry.getUserInvocableSkills();

    return c.json({
      skills: skills.map((s) => ({
        name: s.name,
        description: s.description,
      })),
      total: skills.length,
    });
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      500
    );
  }
});

/**
 * GET /skills/:name - Get a specific skill
 */
skillsRoutes.get('/:name', async (c) => {
  const repoRoot = c.get('repoRoot');
  const { name } = c.req.param();
  const registry = getSkillRegistry({ repoRoot });

  try {
    const skill = await registry.getSkill(name);

    if (!skill) {
      return c.json({ error: `Skill not found: ${name}` }, 404);
    }

    return c.json(toSkillInfo(skill));
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      500
    );
  }
});

/**
 * POST /skills - Create a new skill
 */
skillsRoutes.post('/', zValidator('json', CreateSkillSchema), async (c) => {
  const repoRoot = c.get('repoRoot');
  const body = c.req.valid('json');
  const registry = getSkillRegistry({ repoRoot });

  try {
    const skill = await registry.createSkill(body.name, body.description, {
      userInvocable: body.userInvocable,
      tools: body.tools,
      instructions: body.instructions,
    });

    return c.json({
      success: true,
      skill: toSkillInfo(skill),
    }, 201);
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      400
    );
  }
});

/**
 * POST /skills/:name/invoke - Invoke a skill
 */
skillsRoutes.post(
  '/:name/invoke',
  zValidator('json', InvokeSkillSchema),
  async (c) => {
    const repoRoot = c.get('repoRoot');
    const { name } = c.req.param();
    const body = c.req.valid('json');
    const registry = getSkillRegistry({ repoRoot });

    try {
      const invocation = await registry.invokeSkill(name, body.args);

      if (!invocation) {
        return c.json({ error: `Skill not found: ${name}` }, 404);
      }

      return c.json(invocation);
    } catch (error) {
      return c.json(
        { error: error instanceof Error ? error.message : 'Unknown error' },
        500
      );
    }
  }
);

/**
 * DELETE /skills/:name - Delete a skill
 */
skillsRoutes.delete('/:name', async (c) => {
  const repoRoot = c.get('repoRoot');
  const { name } = c.req.param();
  const registry = getSkillRegistry({ repoRoot });

  try {
    const deleted = await registry.deleteSkill(name);

    if (!deleted) {
      return c.json({ error: `Skill not found: ${name}` }, 404);
    }

    return c.json({
      success: true,
      message: `Skill "${name}" deleted`,
    });
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      400
    );
  }
});

/**
 * POST /skills/reload - Reload skills from disk
 */
skillsRoutes.post('/reload', async (c) => {
  const repoRoot = c.get('repoRoot');
  const registry = getSkillRegistry({ repoRoot });

  try {
    await registry.reload();
    const skills = await registry.listSkills();

    return c.json({
      success: true,
      skillCount: skills.length,
    });
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      500
    );
  }
});
