import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Put,
  Query,
  Req,
  UseGuards,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { AcceptStaffInviteDto } from './dto/accept-staff-invite.dto';
import { InviteStaffDto } from './dto/invite-staff.dto';
import { PreviewStaffInviteDto } from './dto/preview-staff-invite.dto';
import { UpdateStaffMemberDto } from './dto/update-staff-member.dto';
import { UpsertWorkingHoursDto } from './dto/upsert-working-hours.dto';
import { StaffService } from './staff.service';
import { StaffWorkingHoursService } from './staff-working-hours.service';

@ApiTags('staff')
@ApiBearerAuth('JWT-auth')
@Controller('staff')
export class StaffController {
  constructor(
    private readonly staffService: StaffService,
    private readonly staffWorkingHoursService: StaffWorkingHoursService,
  ) {}

  @Get('invitations/preview')
  @ApiOperation({ summary: 'Preview invite info by token (public)' })
  previewInvite(@Query() query: PreviewStaffInviteDto) {
    return this.staffService.previewInvite(query.token);
  }

  @Post('invitations/accept')
  @ApiOperation({ summary: 'Accept invite and activate account (public)' })
  acceptInvite(@Body() dto: AcceptStaffInviteDto) {
    return this.staffService.acceptInvite(dto);
  }

  @Get()
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'List organization members (requires TAB_STAFF_READ or owner)' })
  list(@Req() req: { user: { id: string; organizationId?: string } }) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.list(req.user.id, organizationId);
  }

  @Post('invite')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'Invite staff (requires TAB_STAFF_EDIT or owner)' })
  invite(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Body() dto: InviteStaffDto,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.invite(req.user.id, organizationId, dto);
  }

  @Post('members/:membershipId/clear-password')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({
    summary:
      'Clear a staff member password and return a setup link (owner or TAB_STAFF_EDIT; active members only)',
  })
  clearPassword(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.clearPassword(req.user.id, organizationId, membershipId);
  }

  @Post('members/:membershipId/invitation-link')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({
    summary: 'Regenerate and return invite link for a pending staff member',
  })
  getInvitationLink(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.getInvitationLink(req.user.id, organizationId, membershipId);
  }

  @Patch('members/:membershipId')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'Update staff member name and/or permissions' })
  updateMember(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
    @Body() dto: UpdateStaffMemberDto,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.updateMember(req.user.id, organizationId, membershipId, dto);
  }

  @Get('members/:membershipId/working-hours')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'Get weekly working hours for a staff member' })
  getWorkingHours(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffWorkingHoursService.getWorkingHours(
      req.user.id,
      organizationId,
      membershipId,
    );
  }

  @Put('members/:membershipId/working-hours')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'Save weekly working hours for a staff member' })
  upsertWorkingHours(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
    @Body() dto: UpsertWorkingHoursDto,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffWorkingHoursService.upsertWorkingHours(
      req.user.id,
      organizationId,
      membershipId,
      dto,
    );
  }

  @Patch('members/:membershipId/enable')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({
    summary: 'Re-enable a disabled staff member (uses one plan seat; no new invitation)',
  })
  enableMember(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.enableMember(req.user.id, organizationId, membershipId);
  }

  @Patch('members/:membershipId/disable')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({
    summary: 'Disable staff member (frees a seat; member cannot access this organization)',
  })
  disableMember(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.disableMember(req.user.id, organizationId, membershipId);
  }

  @Delete('members/:membershipId')
  @UseGuards(JwtAuthGuard)
  @ApiOperation({ summary: 'Remove staff member from organization' })
  removeMember(
    @Req() req: { user: { id: string; organizationId?: string } },
    @Param('membershipId') membershipId: string,
  ) {
    const organizationId = this.staffService.getOrganizationIdFromUser(req.user);
    return this.staffService.removeMember(req.user.id, organizationId, membershipId);
  }
}
