/**
 * Comments REST endpoints.
 *
 * GET    /items/:itemId/comments        — list comments for an item
 * POST   /items/:itemId/comments        — add comment
 * PUT    /items/:itemId/comments/:id    — edit comment (author only)
 * DELETE /items/:itemId/comments/:id    — delete comment (author or admin)
 */

import type { FastifyInstance } from 'fastify';
import { BadRequestError, NotFoundError, ForbiddenError } from '../../lib/errors.js';
import { extractAuth } from '../../lib/auth.js';
import * as repo from './repository.js';
import * as itemRepo from '../items/repository.js';
import { CreateCommentSchema, UpdateCommentSchema, type CommentDoc } from './types.js';

export async function commentRoutes(app: FastifyInstance) {
  // List comments
  app.get('/items/:itemId/comments', async req => {
    await extractAuth(req);
    const { itemId } = req.params as { itemId: string };
    const item = await itemRepo.getById(itemId);
    if (!item) throw new NotFoundError('Item not found');
    const comments = await repo.listByItem(itemId);
    return { comments, count: comments.length };
  });

  // Add comment
  app.post('/items/:itemId/comments', async (req, reply) => {
    const auth = await extractAuth(req);
    const { itemId } = req.params as { itemId: string };
    const item = await itemRepo.getById(itemId);
    if (!item) throw new NotFoundError('Item not found');

    const parsed = CreateCommentSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const now = new Date().toISOString();
    const doc: CommentDoc = {
      id: `cmt_${crypto.randomUUID()}`,
      itemId,
      productId: item.productId,
      authorId: auth.sub,
      authorEmail: auth.email ?? null,
      body: parsed.data.body,
      createdAt: now,
      updatedAt: now,
    };

    const created = await repo.create(doc);
    await itemRepo.incrementCommentCount(itemId, 1);
    reply.code(201);
    return created;
  });

  // Edit comment
  app.put('/items/:itemId/comments/:id', async req => {
    const auth = await extractAuth(req);
    const { itemId, id } = req.params as { itemId: string; id: string };

    const comment = await repo.getById(id);
    if (!comment || comment.itemId !== itemId) throw new NotFoundError('Comment not found');
    if (comment.authorId !== auth.sub && auth.role !== 'admin') {
      throw new ForbiddenError('Only the author or admin can edit this comment');
    }

    const parsed = UpdateCommentSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const updated = await repo.update(id, { body: parsed.data.body });
    if (!updated) throw new NotFoundError('Comment update failed');
    return updated;
  });

  // Delete comment
  app.delete('/items/:itemId/comments/:id', async req => {
    const auth = await extractAuth(req);
    const { itemId, id } = req.params as { itemId: string; id: string };

    const comment = await repo.getById(id);
    if (!comment || comment.itemId !== itemId) throw new NotFoundError('Comment not found');
    if (comment.authorId !== auth.sub && auth.role !== 'admin') {
      throw new ForbiddenError('Only the author or admin can delete this comment');
    }

    await repo.remove(id);
    await itemRepo.incrementCommentCount(itemId, -1);
    return { success: true };
  });
}
