import {
  Controller,
  Get,
  Post,
  Patch,
  Delete,
  Param,
  Query,
  Body,
  HttpCode,
  HttpStatus,
  UseGuards,
} from '@nestjs/common';
import { z } from 'zod';
import { WordsService } from './words.service';
import { Word } from './entities/word.entity';
import { Definition } from './entities/definition.entity';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { CurrentUser } from '../auth/current-user.decorator';

// ---------------------------------------------------------------------------
// Zod validation schemas
// ---------------------------------------------------------------------------

const CreateWordSchema = z.object({
  text: z.string().min(1).max(255).trim(),
  definition: z.string().min(1).optional(),
});

const AddDefinitionSchema = z.object({
  text: z.string().min(1),
  context: z.string().min(1).optional(),
});

const UpdateDefinitionSchema = z.object({
  context: z.string().min(1).nullable().optional(),
  text: z.string().min(1).optional(),
});

// ---------------------------------------------------------------------------
// Controller — all routes protected by JWT
// ---------------------------------------------------------------------------

/**
 * WordsController — REST endpoints for Word resources.
 * All routes require a valid Bearer token.
 * Words are scoped to the authenticated user.
 */
@Controller('words')
@UseGuards(JwtAuthGuard)
export class WordsController {
  constructor(private readonly wordsService: WordsService) {}

  /** GET /words?search=xxx&status=to_be_defined&page=1&limit=20 */
  @Get()
  findAll(
    @CurrentUser() userId: string,
    @Query('search') search?: string,
    @Query('status') status?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    return this.wordsService.findAll(
      userId,
      search,
      status,
      page ? parseInt(page, 10) : 1,
      limit ? parseInt(limit, 10) : 20,
    );
  }

  /** GET /words/:id */
  @Get(':id')
  findOne(@CurrentUser() userId: string, @Param('id') id: string): Promise<Word> {
    return this.wordsService.findOne(id, userId);
  }

  /** POST /words */
  @Post()
  create(@CurrentUser() userId: string, @Body() body: unknown): Promise<Word> {
    const { text, definition } = CreateWordSchema.parse(body);
    return this.wordsService.create(userId, text, definition);
  }

  /** POST /words/:id/definitions */
  @Post(':id/definitions')
  addDefinition(
    @CurrentUser() userId: string,
    @Param('id') id: string,
    @Body() body: unknown,
  ): Promise<Word> {
    const { text, context } = AddDefinitionSchema.parse(body);
    return this.wordsService.addDefinition(id, userId, text, context);
  }

  /** PATCH /words/:id/definitions/:definitionId */
  @Patch(':id/definitions/:definitionId')
  updateDefinition(
    @CurrentUser() userId: string,
    @Param('id') id: string,
    @Param('definitionId') definitionId: string,
    @Body() body: unknown,
  ): Promise<Definition> {
    const { context, text } = UpdateDefinitionSchema.parse(body);
    return this.wordsService.updateDefinition(id, definitionId, userId, { context, text });
  }

  /** DELETE /words/:id/definitions/:definitionId */
  @Delete(':id/definitions/:definitionId')
  removeDefinition(
    @CurrentUser() userId: string,
    @Param('id') id: string,
    @Param('definitionId') definitionId: string,
  ): Promise<Word> {
    return this.wordsService.removeDefinition(id, definitionId, userId);
  }

  /** DELETE /words/:id */
  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  remove(@CurrentUser() userId: string, @Param('id') id: string): Promise<void> {
    return this.wordsService.remove(id, userId);
  }
}
