import {
  Body,
  BadRequestException,
  Controller,
  Get,
  Header,
  HttpCode,
  Patch,
  Param,
  ParseIntPipe,
  Post,
  Request,
  StreamableFile,
  UnauthorizedException,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import { FileInterceptor } from '@nestjs/platform-express';
import { memoryStorage } from 'multer';
import { FlyerImportResponse } from './dto/flyer-import.response';
import { UpdateFlyerItemDto } from './dto/update-flyer-item.dto';
import { FlyerImportService } from './flyer-import.service';

const ALLOWED_MIMES = [
  'application/pdf',
  'application/octet-stream',
  'text/plain',
  'image/png',
  'image/jpeg',
  'image/webp',
];

@Controller('flyer-import')
export class FlyerImportController {
  constructor(private readonly flyerImportService: FlyerImportService) {}

  @Post('parse')
  @HttpCode(200)
  @Throttle({ default: { ttl: 60_000, limit: 10 } })
  @UseInterceptors(
    FileInterceptor('file', {
      storage: memoryStorage(),
      limits: { fileSize: 15 * 1024 * 1024 },
    }),
  )
  async parseFlyer(
    @UploadedFile() file?: Express.Multer.File,
    @Request() req?: any,
  ): Promise<FlyerImportResponse> {
    if (!file?.buffer) {
      throw new BadRequestException('Ingen fil skickades med.');
    }
    if (!ALLOWED_MIMES.includes(file.mimetype)) {
      throw new BadRequestException('Otillåten filtyp. Använd PDF, textfil eller bild (PNG, JPEG, WebP).');
    }

    const userId = this.getUserId(req);

    return this.flyerImportService.parseAndMatch(file, userId);
  }

  @Get('sessions/latest')
  @Throttle({ default: { ttl: 60_000, limit: 30 } })
  async getLatestSession(@Request() req?: any): Promise<FlyerImportResponse> {
    const userId = this.getUserId(req);
    return this.flyerImportService.getLatestSession(userId);
  }

  @Get('sessions/:sessionId')
  @Throttle({ default: { ttl: 60_000, limit: 30 } })
  async getSession(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Request() req?: any,
  ): Promise<FlyerImportResponse> {
    const userId = this.getUserId(req);
    return this.flyerImportService.getSession(sessionId, userId);
  }

  @Get('sessions/:sessionId/source')
  @Throttle({ default: { ttl: 60_000, limit: 30 } })
  @Header('Cache-Control', 'private, max-age=300')
  async getSessionSource(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Request() req?: any,
  ): Promise<StreamableFile> {
    const userId = this.getUserId(req);
    const source = await this.flyerImportService.getSessionSource(sessionId, userId);
    return new StreamableFile(source.data, {
      disposition: `inline; filename="${source.fileName.replace(/"/g, '')}"`,
      type: source.mimeType,
      length: source.contentLength,
    });
  }

  @Patch('sessions/:sessionId/items/:itemId')
  @HttpCode(200)
  @Throttle({ default: { ttl: 60_000, limit: 60 } })
  async updateSessionItem(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Param('itemId', ParseIntPipe) itemId: number,
    @Request() req: any,
    @Body() dto: UpdateFlyerItemDto,
  ) {
    const userId = this.getUserId(req);
    return this.flyerImportService.updateSessionItem(sessionId, itemId, userId, dto);
  }

  private getUserId(req?: any): number {
    const userId =
      typeof req?.user?.id === 'number'
        ? req.user.id
        : typeof req?.user?.userId === 'number'
          ? req.user.userId
          : undefined;

    if (!userId) {
      throw new UnauthorizedException('Kunde inte identifiera användaren.');
    }

    return userId;
  }
}
