import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Query,
  ParseIntPipe,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiQuery,
} from '@nestjs/swagger';
import { FreeScoutService } from './freescout.service';
import {
  ListConversationsDto,
  CreateConversationDto,
  ReplyToConversationDto,
  CreateCustomerDto,
  ListCustomersDto,
  ConversationResponseDto,
  MailboxResponseDto,
  CustomerResponseDto,
  TagResponseDto,
} from './freescout.types';
import { RequirePermissions } from '../../../../auth/permissions/permissions.decorator';
import { Permission } from '../../../../auth/permissions/permissions.enum';

/**
 * FreeScout Integration Controller
 *
 * REST API endpoints for FreeScout helpdesk integration.
 */
@ApiTags('Integrations - FreeScout')
@ApiBearerAuth()
@Controller('integrations/freescout')
export class FreeScoutController {
  constructor(private readonly freeScoutService: FreeScoutService) {}

  // ============ Health & Status ============

  @Post('test')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Test FreeScout connection' })
  @ApiResponse({
    status: 200,
    description: 'Connection test result',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        message: { type: 'string' },
        latency: { type: 'number' },
      },
    },
  })
  @ApiResponse({ status: 401, description: 'Authentication failed' })
  @ApiResponse({ status: 503, description: 'Service unavailable' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async testConnection() {
    return this.freeScoutService.testConnection();
  }

  @Get('health')
  @ApiOperation({ summary: 'Get FreeScout connector health status' })
  @ApiResponse({
    status: 200,
    description: 'Health status',
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', enum: ['connected', 'error', 'not_configured'] },
        lastCheck: { type: 'string', format: 'date-time' },
        latency: { type: 'number' },
        error: { type: 'string' },
      },
    },
  })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getHealth() {
    return this.freeScoutService.checkHealth();
  }

  // ============ Conversations ============

  @Get('conversations')
  @ApiOperation({ summary: 'List conversations' })
  @ApiQuery({ name: 'mailboxId', required: false, type: Number })
  @ApiQuery({ name: 'status', required: false, enum: ['active', 'pending', 'closed', 'spam'] })
  @ApiQuery({ name: 'assignedTo', required: false, type: Number })
  @ApiQuery({ name: 'tag', required: false, type: String })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({
    status: 200,
    description: 'List of conversations',
    schema: {
      type: 'object',
      properties: {
        conversations: { type: 'array', items: { $ref: '#/components/schemas/ConversationResponseDto' } },
        pagination: {
          type: 'object',
          properties: {
            page: { type: 'number' },
            pageSize: { type: 'number' },
            total: { type: 'number' },
            totalPages: { type: 'number' },
          },
        },
      },
    },
  })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listConversations(@Query() query: ListConversationsDto) {
    return this.freeScoutService.listConversations(query);
  }

  @Get('conversations/:id')
  @ApiOperation({ summary: 'Get a conversation by ID' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Conversation details', type: ConversationResponseDto })
  @ApiResponse({ status: 404, description: 'Conversation not found' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getConversation(@Param('id', ParseIntPipe) id: number) {
    return this.freeScoutService.getConversation(id);
  }

  @Post('conversations')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new conversation' })
  @ApiResponse({ status: 201, description: 'Conversation created', type: ConversationResponseDto })
  @ApiResponse({ status: 400, description: 'Invalid input' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async createConversation(@Body() data: CreateConversationDto) {
    return this.freeScoutService.createConversation(data);
  }

  @Post('conversations/:id/reply')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Reply to a conversation' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Reply added', type: ConversationResponseDto })
  @ApiResponse({ status: 404, description: 'Conversation not found' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async replyToConversation(
    @Param('id', ParseIntPipe) id: number,
    @Body() data: ReplyToConversationDto,
  ) {
    return this.freeScoutService.replyToConversation(id, data);
  }

  @Post('conversations/:id/close')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Close a conversation' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Conversation closed', type: ConversationResponseDto })
  @ApiResponse({ status: 404, description: 'Conversation not found' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async closeConversation(@Param('id', ParseIntPipe) id: number) {
    return this.freeScoutService.closeConversation(id);
  }

  @Post('conversations/:id/reopen')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Reopen a conversation' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Conversation reopened', type: ConversationResponseDto })
  @ApiResponse({ status: 404, description: 'Conversation not found' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async reopenConversation(@Param('id', ParseIntPipe) id: number) {
    return this.freeScoutService.reopenConversation(id);
  }

  // ============ Mailboxes ============

  @Get('mailboxes')
  @ApiOperation({ summary: 'List all mailboxes' })
  @ApiResponse({
    status: 200,
    description: 'List of mailboxes',
    type: [MailboxResponseDto],
  })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listMailboxes() {
    return this.freeScoutService.listMailboxes();
  }

  @Get('mailboxes/:id')
  @ApiOperation({ summary: 'Get a mailbox by ID' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Mailbox details', type: MailboxResponseDto })
  @ApiResponse({ status: 404, description: 'Mailbox not found' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getMailbox(@Param('id', ParseIntPipe) id: number) {
    return this.freeScoutService.getMailbox(id);
  }

  // ============ Customers ============

  @Get('customers')
  @ApiOperation({ summary: 'List customers' })
  @ApiQuery({ name: 'email', required: false, type: String })
  @ApiQuery({ name: 'query', required: false, type: String })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({
    status: 200,
    description: 'List of customers',
    schema: {
      type: 'object',
      properties: {
        customers: { type: 'array', items: { $ref: '#/components/schemas/CustomerResponseDto' } },
        pagination: {
          type: 'object',
          properties: {
            page: { type: 'number' },
            pageSize: { type: 'number' },
            total: { type: 'number' },
            totalPages: { type: 'number' },
          },
        },
      },
    },
  })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listCustomers(@Query() query: ListCustomersDto) {
    return this.freeScoutService.listCustomers(query);
  }

  @Get('customers/:id')
  @ApiOperation({ summary: 'Get a customer by ID' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Customer details', type: CustomerResponseDto })
  @ApiResponse({ status: 404, description: 'Customer not found' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getCustomer(@Param('id', ParseIntPipe) id: number) {
    return this.freeScoutService.getCustomer(id);
  }

  @Post('customers')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new customer' })
  @ApiResponse({ status: 201, description: 'Customer created', type: CustomerResponseDto })
  @ApiResponse({ status: 400, description: 'Invalid input' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async createCustomer(@Body() data: CreateCustomerDto) {
    return this.freeScoutService.createCustomer(data);
  }

  // ============ Tickets (Facade over Conversations for Frontend) ============

  @Get('tickets')
  @ApiOperation({ summary: 'List tickets (conversations)' })
  @ApiQuery({ name: 'status', required: false, enum: ['active', 'pending', 'closed', 'spam'] })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({ status: 200, description: 'List of tickets' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listTickets(@Query() query: ListConversationsDto) {
    return this.freeScoutService.listConversations(query);
  }

  @Get('tickets/:id')
  @ApiOperation({ summary: 'Get a ticket by ID' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Ticket details' })
  @ApiResponse({ status: 404, description: 'Ticket not found' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getTicket(@Param('id', ParseIntPipe) id: number) {
    return this.freeScoutService.getConversation(id);
  }

  @Post('tickets/:id/status')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Update ticket status' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Status updated' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async updateTicketStatus(
    @Param('id', ParseIntPipe) id: number,
    @Body('status') status: string,
  ) {
    if (status === 'closed' || status === 'resolved') {
      return this.freeScoutService.closeConversation(id);
    }
    if (status === 'open') {
      return this.freeScoutService.reopenConversation(id);
    }
    return { success: true, message: `Status update to ${status} acknowledged` };
  }

  // ============ Tags ============

  @Get('tags')
  @ApiOperation({ summary: 'List all tags' })
  @ApiResponse({ status: 200, description: 'List of tags', type: [TagResponseDto] })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listTags() {
    return this.freeScoutService.listTags();
  }

  @Post('conversations/:id/tags')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Add tags to a conversation' })
  @ApiParam({ name: 'id', type: Number })
  @ApiResponse({ status: 200, description: 'Tags added' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async addTagsToConversation(
    @Param('id', ParseIntPipe) id: number,
    @Body() body: { tags: string[] },
  ) {
    await this.freeScoutService.addTagsToConversation(id, body.tags);
    return { success: true, message: 'Tags added successfully' };
  }
}
