import {
  Controller,
  Get,
  Post,
  Patch,
  Delete,
  Body,
  Param,
  Query,
  Req,
  ParseUUIDPipe,
  HttpCode,
  HttpStatus,
  UseGuards,
  NotFoundException,
} from '@nestjs/common';
import { Request } from 'express';
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiParam,
} from '@nestjs/swagger';
import { ContactsService } from './contacts.service';
import { CreateContactDto } from './dto/create-contact.dto';
import { UpdateContactDto } from './dto/update-contact.dto';
import { QueryContactsDto } from './dto/query-contacts.dto';
import { AddOwnerDto } from '../common/dto/owner.dto';
import { OwnersService } from '../owners/owners.service';
import { GraphService } from '../graph/graph.service';
import { CurrentUser, JwtPayload } from '../common/decorators';
import { TenantGuard } from '../auth/guards/tenant.guard';
import {
  paginatedResponse,
  singleResponse,
} from '../common/dto/pagination.dto';

@ApiTags('Contacts')
@ApiBearerAuth('access-token')
@UseGuards(TenantGuard)
@Controller('contacts')
export class ContactsController {
  constructor(
    private readonly contactsService: ContactsService,
    private readonly ownersService: OwnersService,
    private readonly graphService: GraphService,
  ) {}

  @Post()
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Kontakt erstellen' })
  async create(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateContactDto,
  ) {
    const contact = await this.contactsService.create(
      user.tenantId!,
      user.sub,
      dto,
    );
    return singleResponse(contact);
  }

  @Get()
  @ApiOperation({ summary: 'Kontakte auflisten (paginiert, filterbar)' })
  async findAll(
    @CurrentUser() user: JwtPayload,
    @Query() query: QueryContactsDto,
  ) {
    const result = await this.contactsService.findAll(user.tenantId!, query);
    return paginatedResponse(
      result.data,
      result.total,
      result.page,
      result.pageSize,
    );
  }

  @Get('lookup')
  @ApiOperation({ summary: 'Kontakt anhand E-Mail-Adresse suchen' })
  async lookupByEmail(
    @CurrentUser() user: JwtPayload,
    @Query('email') email: string,
  ) {
    const contact = await this.contactsService.findByEmail(user.tenantId!, email);
    if (!contact) throw new NotFoundException('Kein Kontakt mit dieser E-Mail-Adresse gefunden');
    return singleResponse(contact);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Kontakt-Details abrufen' })
  @ApiParam({ name: 'id', type: 'string', format: 'uuid' })
  async findOne(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    const contact = await this.contactsService.findOne(user.tenantId!, id);
    return singleResponse(contact);
  }

  @Patch(':id')
  @ApiOperation({ summary: 'Kontakt aktualisieren' })
  @ApiParam({ name: 'id', type: 'string', format: 'uuid' })
  async update(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateContactDto,
  ) {
    const contact = await this.contactsService.update(
      user.tenantId!,
      id,
      user.sub,
      dto,
    );
    return singleResponse(contact);
  }

  @Delete(':id')
  @ApiOperation({ summary: 'Kontakt loeschen' })
  @ApiParam({ name: 'id', type: 'string', format: 'uuid' })
  async remove(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    const contact = await this.contactsService.remove(user.tenantId!, id);
    return singleResponse(contact);
  }

  // --------------------------------------------------------
  // Outlook Sync
  // --------------------------------------------------------

  @Post(':id/push-to-outlook')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'CRM-Kontakt in Outlook-Kontakte pushen / synchronisieren' })
  @ApiParam({ name: 'id', type: 'string', format: 'uuid' })
  async pushToOutlook(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Req() req: Request,
  ) {
    const contact = await this.contactsService.findOne(user.tenantId!, id);
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const result = await this.graphService.pushContactToOutlook(jwt, {
      firstName: contact.firstName,
      lastName: contact.lastName,
      companyName: contact.companyName,
      email: contact.email,
      phone: contact.phone,
      mobile: contact.mobile,
      position: contact.position,
      department: contact.department,
      street: contact.street,
      zip: contact.zip,
      city: contact.city,
      state: contact.state,
      country: contact.country,
      website: contact.website,
      notes: contact.notes,
    });
    return { success: true, data: result };
  }

  // --------------------------------------------------------
  // Owner Endpoints
  // --------------------------------------------------------

  @Post(':id/owners')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Owner zu Kontakt hinzufuegen' })
  @ApiParam({ name: 'id', type: 'string', format: 'uuid' })
  async addOwner(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: AddOwnerDto,
  ) {
    const owner = await this.ownersService.addContactOwner(
      user.tenantId!,
      id,
      dto,
    );
    return singleResponse(owner);
  }

  @Delete(':id/owners/:userId')
  @ApiOperation({ summary: 'Owner von Kontakt entfernen' })
  @ApiParam({ name: 'id', type: 'string', format: 'uuid' })
  @ApiParam({ name: 'userId', type: 'string', format: 'uuid' })
  async removeOwner(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Param('userId', ParseUUIDPipe) userId: string,
  ) {
    const owner = await this.ownersService.removeContactOwner(
      user.tenantId!,
      id,
      userId,
    );
    return singleResponse(owner);
  }
}
