import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  Res,
  HttpStatus,
  HttpCode,
  UseGuards,
  ParseIntPipe,
} from '@nestjs/common';
import { Response } from 'express';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiQuery,
  ApiBearerAuth,
  ApiSecurity,
  ApiParam,
} from '@nestjs/swagger';
import { TemplateFormSectionService } from './template-form-section.service';
import { CreateTemplateFormSectionDto } from './dto/create-template-form-section.dto';
import { UpdateTemplateFormSectionDto } from './dto/update-template-form-section.dto';
import { FilterTemplateFormSectionDto } from './dto/filter-template-form-section.dto';
import { CloneFromMasterDto } from './dto/clone-from-master.dto';
import { TemplateFormBuilderDto, TemplateFormBuilderResponseDto } from './dto/template-form-builder.dto';
import { ResponseService } from 'src/common/response-handling/response-handler';
import { Roles } from 'src/common/decorators/roles.decorator';
import { RolesGuard } from 'src/common/guards/roles.guard';
import { AppLoggerService } from 'src/common/services/logger.service';
import { handleControllerError } from 'src/common/utils/controller-response-handling';
import { CombinedAuthGuard } from 'src/auth/combined-auth.guard';
import { ROLE_VALUES } from 'src/common/constants/strings-constants';

@ApiTags('template-form-section')
@Controller('v1/template-sections')
@UseGuards(CombinedAuthGuard, RolesGuard)
@Roles(ROLE_VALUES.ADMIN, ROLE_VALUES.COORDINATOR)
@ApiBearerAuth('Authorization')
@ApiSecurity('userIdAuth')
@ApiSecurity('activeRoleAuth')
export class TemplateFormSectionController {
  constructor(
    private readonly templateFormSectionService: TemplateFormSectionService,
    private readonly responseService: ResponseService,
    private readonly logger: AppLoggerService,
  ) {}

  /**
   * Get all template form sections with filters
   */
  @Get()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Get all template form sections with filters' })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'offset', required: false, type: Number })
  @ApiQuery({ name: 'searchText', required: false, type: String })
  @ApiQuery({ name: 'programTemplateId', required: false, type: Number })
  @ApiQuery({ name: 'parentSectionId', required: false, type: Number })
  @ApiQuery({ name: 'masterFormSectionId', required: false, type: Number })
  @ApiResponse({ status: HttpStatus.OK, description: 'Template form sections retrieved successfully' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async findAll(@Query() filters: FilterTemplateFormSectionDto, @Res() res: Response) {
    this.logger.log('GET /v1/template-sections - Request received', { filters });
    try {
      const result = await this.templateFormSectionService.findAll(filters);
      this.logger.log('Template form sections retrieved successfully');
      return this.responseService.success(res, 'Template form sections retrieved successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Get section hierarchy for a program template
   */
  @Get('hierarchy/:programTemplateId')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Get template form sections as hierarchical tree for a program template' })
  @ApiParam({ name: 'programTemplateId', type: Number })
  @ApiResponse({ status: HttpStatus.OK, description: 'Section hierarchy retrieved successfully' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async getHierarchy(
    @Param('programTemplateId', ParseIntPipe) programTemplateId: number,
    @Res() res: Response,
  ) {
    this.logger.log('GET /v1/template-sections/hierarchy/:programTemplateId - Request received', {
      programTemplateId,
    });
    try {
      const result = await this.templateFormSectionService.getHierarchyByTemplate(programTemplateId);
      this.logger.log('Section hierarchy retrieved successfully');
      return this.responseService.success(res, 'Section hierarchy retrieved successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Get a single template form section by ID
   */
  @Get(':id')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Get a template form section by ID' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: HttpStatus.OK, description: 'Template form section retrieved successfully' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Template form section not found' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async findById(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
    this.logger.log('GET /v1/template-sections/:id - Request received', { id });
    try {
      const result = await this.templateFormSectionService.findById(id);
      this.logger.log('Template form section retrieved successfully', { sectionId: id });
      return this.responseService.success(res, 'Template form section retrieved successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Get subsections of a template section
   */
  @Get(':id/subsections')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Get all subsections of a template section' })
  @ApiParam({ name: 'id', type: Number, description: 'Parent section ID' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Subsections retrieved successfully' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Parent section not found' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async getChildren(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
    this.logger.log('GET /v1/template-sections/:id/subsections - Request received', { id });
    try {
      const result = await this.templateFormSectionService.getChildren(id);
      this.logger.log('Subsections retrieved successfully', { parentId: id });
      return this.responseService.success(res, 'Subsections retrieved successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Get ancestors of a template section
   */
  @Get(':id/ancestors')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Get ancestors of a template section (breadcrumb trail)' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: HttpStatus.OK, description: 'Ancestors retrieved successfully' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Section not found' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async getAncestors(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
    this.logger.log('GET /v1/template-sections/:id/ancestors - Request received', { id });
    try {
      const result = await this.templateFormSectionService.getAncestors(id);
      this.logger.log('Ancestors retrieved successfully', { sectionId: id });
      return this.responseService.success(res, 'Ancestors retrieved successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Create a template form section
   */
  @Post()
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new template form section' })
  @ApiResponse({ status: HttpStatus.CREATED, description: 'Template form section created successfully' })
  @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Invalid input data' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async create(@Body() createDto: CreateTemplateFormSectionDto, @Res() res: Response) {
    this.logger.log('POST /v1/template-sections - Request received', { createDto });
    try {
      const result = await this.templateFormSectionService.create(createDto);
      this.logger.log('Template form section created successfully', { sectionId: result.id });
      return this.responseService.success(
        res,
        'Template form section created successfully',
        result,
        HttpStatus.CREATED,
      );
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Clone from master section
   * @deprecated Use POST /v1/program-templates/:id/clone-from-master instead
   */
  @Post('clone-from-master')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Clone master form section(s) to template level' })
  @ApiResponse({ status: HttpStatus.CREATED, description: 'Section(s) cloned successfully' })
  @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Invalid input or already cloned' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Master section not found' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async cloneFromMaster(@Body() cloneDto: CloneFromMasterDto, @Res() res: Response) {
    this.logger.log('POST /v1/template-sections/clone-from-master - Request received (DEPRECATED)', {
      cloneDto,
    });
    try {
      const result = await this.templateFormSectionService.cloneFromMaster(cloneDto);
      this.logger.log('Section(s) cloned from master successfully', {
        clonedCount: result.clonedSections,
      });
      return this.responseService.success(
        res,
        'Section(s) cloned from master successfully',
        result,
        HttpStatus.CREATED,
      );
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Update a template form section
   */
  @Put(':id')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Update a template form section' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: HttpStatus.OK, description: 'Template form section updated successfully' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Template form section not found' })
  @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Invalid input data' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async update(
    @Param('id', ParseIntPipe) id: number,
    @Body() updateDto: UpdateTemplateFormSectionDto,
    @Res() res: Response,
  ) {
    this.logger.log('PUT /v1/template-sections/:id - Request received', { id, updateDto });
    try {
      const result = await this.templateFormSectionService.update(id, updateDto);
      this.logger.log('Template form section updated successfully', { sectionId: id });
      return this.responseService.success(res, 'Template form section updated successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  /**
   * Delete a template form section
   */
  @Delete(':id')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Delete a template form section (soft delete)' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: HttpStatus.OK, description: 'Template form section deleted successfully' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Template form section not found' })
  @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Cannot delete section with children' })
  @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error' })
  async delete(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
    this.logger.log('DELETE /v1/template-sections/:id - Request received', { id });
    try {
      const result = await this.templateFormSectionService.delete(id);
      this.logger.log('Template form section deleted successfully', { sectionId: id });
      return this.responseService.success(res, 'Template form section deleted successfully', result);
    } catch (error) {
      handleControllerError(res, error);
    }
  }
}