import {
  Body,
  Controller,
  Delete,
  Get,
  HttpStatus,
  Param,
  Patch,
  Post,
  Query,
  Req,
  Res,
  UseGuards,
  UsePipes,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { ZodValidationPipe } from '../../common/pipes/zod-validation.pipe';
import { JwtAuthGuard } from '../owner/guards/jwt.guard';
import {
  assignBuddyDto,
  assignBuddySchema,
  createOnboardingCaseDto,
  createOnboardingCaseSchema,
  createOnboardingTaskDto,
  createOnboardingTaskSchema,
  createOnboardingTemplateDto,
  createOnboardingTemplateSchema,
  createProvisioningItemDto,
  createProvisioningItemSchema,
  filterOnboardingCaseDto,
  filterOnboardingCaseSchema,
  signOnboardingDocumentDto,
  signOnboardingDocumentSchema,
  updateOnboardingCaseDto,
  updateOnboardingCaseSchema,
  updateOnboardingTaskDto,
  updateOnboardingTaskSchema,
  updateOnboardingTemplateDto,
  updateOnboardingTemplateSchema,
  updateProvisioningItemDto,
  updateProvisioningItemSchema,
} from './onboarding.dto';
import { OnboardingService } from './onboarding.service';

@Controller('onboarding')
export class OnboardingController {
  constructor(private readonly service: OnboardingService) {}

  // -------------------------------------------------------------
  // TEMPLATES
  // -------------------------------------------------------------

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createOnboardingTemplateSchema))
  @Post('templates')
  async createTemplate(
    @Body() data: createOnboardingTemplateDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.createTemplate(data, owner_id);
    return res.status(HttpStatus.CREATED).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Post('templates/reset-defaults')
  async resetDefaultTemplates(
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.resetDefaultTemplates(owner_id);
    return res.status(HttpStatus.OK).json({
      data: result,
      status: HttpStatus.OK,
      message: 'Default onboarding templates reset and seeded successfully',
    });
  }

  @UseGuards(JwtAuthGuard)
  @Get('templates')
  async getTemplates(
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.getTemplates(owner_id);
    return res.status(HttpStatus.OK).json({
      data: result,
      status: HttpStatus.OK,
      message: 'Templates retrieved successfully',
    });
  }

  @UseGuards(JwtAuthGuard)
  @Get('templates/:id')
  async getTemplateById(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.getTemplateById(id, owner_id);
    return res.status(HttpStatus.OK).json({
      data: result,
      status: HttpStatus.OK,
      message: 'Template retrieved successfully',
    });
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateOnboardingTemplateSchema))
  @Patch('templates/:id')
  async updateTemplate(
    @Param('id') id: string,
    @Body() data: updateOnboardingTemplateDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.updateTemplate(id, data, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Delete('templates/:id')
  async deleteTemplate(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.deleteTemplate(id, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Patch('templates/:id/set-default')
  async setDefaultTemplate(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.setDefaultTemplate(id, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  // -------------------------------------------------------------
  // CASES
  // -------------------------------------------------------------

  @UseGuards(JwtAuthGuard)
  @Get('stats')
  async getDashboardStats(
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.getDashboardStats(owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Get('my-portal')
  async getMyPortal(
    @Req() req: Request,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const memberId = (req.user as any)?.sub || (req.user as any)?.id;
    const result = await this.service.getMyWelcomePortal(memberId, owner_id);
    return res.status(HttpStatus.OK).json({
      data: result,
      status: HttpStatus.OK,
      message: 'My onboarding portal retrieved successfully',
    });
  }

  @UseGuards(JwtAuthGuard)
  @Get('me/welcome')
  async getMyWelcomePortal(
    @Req() req: Request,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const memberId = (req.user as any)?.sub || (req.user as any)?.id;
    const result = await this.service.getMyWelcomePortal(memberId, owner_id);
    return res.status(HttpStatus.OK).json({
      data: result,
      status: HttpStatus.OK,
      message: 'Welcome portal retrieved successfully',
    });
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createOnboardingCaseSchema))
  @Post()
  async createCase(
    @Body() data: createOnboardingCaseDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.createCase(data, owner_id);
    return res.status(HttpStatus.CREATED).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(filterOnboardingCaseSchema))
  @Get('filter')
  async getCasesByFilter(
    @Query() query: filterOnboardingCaseDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.getCasesByFilter(query, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Get(':id')
  async getCaseById(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.getCaseById(id, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateOnboardingCaseSchema))
  @Patch(':id')
  async updateCase(
    @Param('id') id: string,
    @Body() data: updateOnboardingCaseDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.updateCase(id, data, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Delete(':id')
  async deleteCase(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.deleteCase(id, owner_id);
    return res.status(HttpStatus.OK).json({
      data: result,
      status: HttpStatus.OK,
      message: 'Onboarding case deleted successfully',
    });
  }

  // -------------------------------------------------------------
  // TASKS
  // -------------------------------------------------------------

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createOnboardingTaskSchema))
  @Post(':id/tasks')
  async addTask(
    @Param('id') caseId: string,
    @Body() data: createOnboardingTaskDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.addTask(caseId, data, owner_id);
    return res.status(HttpStatus.CREATED).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateOnboardingTaskSchema))
  @Patch('tasks/:taskId')
  async updateTask(
    @Param('taskId') taskId: string,
    @Body() data: updateOnboardingTaskDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const memberId = (req.user as any)?.sub || (req.user as any)?.id;
    const result = await this.service.updateTask(taskId, data, owner_id, memberId);
    return res.status(HttpStatus.OK).json(result);
  }

  // -------------------------------------------------------------
  // DOCUMENTS
  // -------------------------------------------------------------

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(signOnboardingDocumentSchema))
  @Post('documents/:documentId/sign')
  async signDocument(
    @Param('documentId') documentId: string,
    @Body() data: signOnboardingDocumentDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const memberId = (req.user as any)?.sub || (req.user as any)?.id;
    const result = await this.service.signDocument(documentId, data, memberId, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  // -------------------------------------------------------------
  // PROVISIONING
  // -------------------------------------------------------------

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createProvisioningItemSchema))
  @Post(':id/provisioning')
  async addProvisioningItem(
    @Param('id') caseId: string,
    @Body() data: createProvisioningItemDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.addProvisioningItem(caseId, data, owner_id);
    return res.status(HttpStatus.CREATED).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateProvisioningItemSchema))
  @Patch('provisioning/:itemId')
  async updateProvisioningItem(
    @Param('itemId') itemId: string,
    @Body() data: updateProvisioningItemDto,
    @CurrentUser() owner_id: string,
    @Res() res: Response,
  ) {
    const result = await this.service.updateProvisioningItem(itemId, data, owner_id);
    return res.status(HttpStatus.OK).json(result);
  }

  // -------------------------------------------------------------
  // BUDDY
  // -------------------------------------------------------------

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(assignBuddySchema))
  @Post(':id/buddy')
  async assignBuddy(
    @Param('id') caseId: string,
    @Body() data: assignBuddyDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const memberId = (req.user as any)?.sub || (req.user as any)?.id;
    const result = await this.service.assignBuddy(caseId, data, memberId, owner_id);
    return res.status(HttpStatus.CREATED).json(result);
  }
}
