import {
  Body,
  Controller,
  Delete,
  Get,
  NotFoundException,
  Param,
  ParseUUIDPipe,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { PermissionGuard } from '../../auth/guards/permission.guard';
import { Permissions } from '../../auth/decorators/permissions.decorator';
import { AccessLevel, ModuleName } from '../../entities/role-permission.entity';
import { successResponse } from '../../common/responses/api-response';
import { CommunicationTemplateService } from './communication-template.service';
import {
  CreateCommunicationTemplateDto,
  UpdateCommunicationTemplateDto,
} from './dto';
import {
  CommunicationChannel,
  CommunicationContext,
} from '../../entities/communication-template.entity';

/**
 * Communication Template admin API.
 *
 * The generic list + CRUD paths sit under COMMUNICATION_TEMPLATE
 * permission. The two consumer endpoints (fetch-by-channel-context
 * for the FE picker, and render) are gated by the same VIEW right
 * because they only expose the template body which the admin has
 * already curated for the tenant.
 */
@Controller('communication-templates')
@UseGuards(JwtAuthGuard, PermissionGuard)
export class CommunicationTemplateController {
  constructor(private readonly service: CommunicationTemplateService) {}

  @Get()
  @Permissions({
    module: ModuleName.COMMUNICATION_TEMPLATE,
    accessLevel: AccessLevel.VIEW,
  })
  async findAll(
    @Query('channel') channel?: CommunicationChannel,
    @Query('context') context?: CommunicationContext,
  ) {
    // Consumer path — Query/Booking/MD pages pass channel + context
    // and get only the active templates for their bucket. Admin path
    // omits both and gets the full tenant list.
    const data =
      channel && context
        ? await this.service.findByChannelAndContext(channel, context)
        : await this.service.findAllForAdmin();
    return successResponse(data, 'Templates fetched');
  }

  @Get(':id')
  @Permissions({
    module: ModuleName.COMMUNICATION_TEMPLATE,
    accessLevel: AccessLevel.VIEW,
  })
  async findById(@Param('id', ParseUUIDPipe) id: string) {
    const t = await this.service.findById(id);
    if (!t) throw new NotFoundException('Template not found');
    return successResponse(t, 'Template fetched');
  }

  @Post()
  @Permissions({
    module: ModuleName.COMMUNICATION_TEMPLATE,
    accessLevel: AccessLevel.CREATE,
  })
  async create(@Body() dto: CreateCommunicationTemplateDto) {
    const r = await this.service.create(dto);
    return successResponse(r, r.message);
  }

  @Patch(':id')
  @Permissions({
    module: ModuleName.COMMUNICATION_TEMPLATE,
    accessLevel: AccessLevel.EDIT,
  })
  async update(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateCommunicationTemplateDto,
  ) {
    const r = await this.service.update(id, dto);
    return successResponse(r, r.message);
  }

  @Delete(':id')
  @Permissions({
    module: ModuleName.COMMUNICATION_TEMPLATE,
    accessLevel: AccessLevel.DELETE,
  })
  async remove(@Param('id', ParseUUIDPipe) id: string) {
    const r = await this.service.remove(id);
    return successResponse(r, r.message);
  }

  /**
   * Render a template against a specific subject. `subject_id`
   * semantics depend on the template's `context` — for QUERY it's
   * a queries.id. The FE Copy Email/WhatsApp buttons POST here.
   */
  @Post(':id/render')
  @Permissions({
    module: ModuleName.COMMUNICATION_TEMPLATE,
    accessLevel: AccessLevel.VIEW,
  })
  async render(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: { subject_id: string },
  ) {
    const r = await this.service.render(id, body.subject_id);
    return successResponse(r, 'Template rendered');
  }
}
