import {
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Patch,
  Post,
  Query,
  UploadedFiles,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Throttle } from '../../common/decorators/throttle.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { MultipartFormDataGuard } from '../../common/guards/multipart-form-data.guard';
import { SuperAdminPermissionsGuard } from '../../common/guards/superadmin-permissions.guard';
import { SuperAdminJwtAuthGuard } from '../../common/guards/super-admin-jwt-auth.guard';
import { JwtPayload } from '../../common/interfaces/jwt-payload.interface';
import { MEDIA_MAX_SIZE_BYTES } from '../../common/media/allowed-media';
import { SuperAdminPermissions } from '../../common/decorators/superadmin-permissions.decorator';
import { AdminPostQueryDto } from './dto/admin-post-query.dto';
import { CreateReelDto } from './dto/create-reel.dto';
import { CreatePostDto } from './dto/create-post.dto';
import { CreateRepostDto } from './dto/create-repost.dto';
import { PostQueryDto } from './dto/post-query.dto';
import { ReelQueryDto } from './dto/reel-query.dto';
import {
  SharePostDto,
  SharePostExternalDto,
  SharePostToFriendDto,
  SharePostToProfileDto,
} from './dto/share-post.dto';
import { UpdateCommentSettingsDto } from './dto/update-comment-settings.dto';
import { UpdatePostDto } from './dto/update-post.dto';
import { PostsService } from './posts.service';
import { SUPERADMIN_PERMISSIONS } from '../superadmin/superadmin-permissions';

@ApiTags('Posts')
@Controller('posts')
export class PostsController {
  constructor(private readonly postsService: PostsService) {}

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, MultipartFormDataGuard)
  @UseInterceptors(
    FileFieldsInterceptor([
      { name: 'imageFiles', maxCount: 10 },
      { name: 'videoFile', maxCount: 1 },
      { name: 'audioFile', maxCount: 1 },
      { name: 'coverImageFile', maxCount: 1 },
    ], { limits: { fileSize: MEDIA_MAX_SIZE_BYTES.postsVideo, files: 13 } }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        content: { type: 'string', example: 'First post #music' },
        contentTop: { type: 'string', example: 'Text above media' },
        contentBottom: { type: 'string', example: 'Text below media' },
        visibility: { type: 'string', enum: ['public', 'followers', 'private'] },
        imageUrls: { type: 'array', items: { type: 'string' } },
        imageCaptions: { type: 'array', items: { type: 'string' } },
        imageAltTexts: { type: 'array', items: { type: 'string' } },
        taggedUserIds: { type: 'array', items: { type: 'string' } },
        collaboratorIds: { type: 'array', items: { type: 'string' } },
        mentionUsernames: { type: 'array', items: { type: 'string' } },
        mentionedUserIds: { type: 'array', items: { type: 'string' } },
        location: { type: 'string', example: 'Riyadh, Saudi Arabia' },
        latitude: { type: 'number', example: 24.7136 },
        longitude: { type: 'number', example: 46.6753 },
        videoUrl: { type: 'string', example: 'https://cdn.example.com/video.mp4' },
        audioUrl: { type: 'string', example: 'https://cdn.example.com/audio.mp3' },
        durationSeconds: { type: 'number', example: 54 },
        thumbnailUrl: { type: 'string', example: 'https://cdn.example.com/cover.jpg' },
        style: { type: 'string', example: 'Sharqi' },
        maqam: { type: 'string', example: 'Hijaz' },
        rhythmSignature: { type: 'string', example: '6/8' },
        waveformPeaks: { type: 'array', items: { type: 'number' } },
        commentsDisabled: { type: 'boolean' },
        commentsFollowersOnly: { type: 'boolean' },
        imageFiles: { type: 'array', items: { type: 'string', format: 'binary' } },
        videoFile: { type: 'string', format: 'binary' },
        audioFile: { type: 'string', format: 'binary' },
        coverImageFile: { type: 'string', format: 'binary' },
      },
    },
  })
  @Post()
  async create(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreatePostDto,
    @UploadedFiles()
    files?: {
      imageFiles?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      audioFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      coverImageFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
    },
  ) {
    return this.postsService.create(
      user.sub,
      dto,
      files?.imageFiles ?? [],
      files?.videoFile?.[0],
      files?.audioFile?.[0],
      files?.coverImageFile?.[0],
    );
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('user/:userId')
  async findUserPosts(
    @CurrentUser() user: JwtPayload,
    @Param('userId') userId: string,
    @Query() query: PostQueryDto,
  ) {
    return this.postsService.findUserPosts(userId, query, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.CONTENT_MODERATE)
  @Get('admin/moderation')
  async findPlatformPosts(@Query() query: AdminPostQueryDto) {
    return this.postsService.findPlatformPosts(query);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, MultipartFormDataGuard)
  @UseInterceptors(
    FileFieldsInterceptor([
      { name: 'videoFile', maxCount: 1 },
      { name: 'coverImageFile', maxCount: 1 },
    ], { limits: { fileSize: MEDIA_MAX_SIZE_BYTES.postsVideo, files: 2 } }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        content: { type: 'string', example: 'New reel from oud session #reel' },
        contentTop: { type: 'string', example: 'Text above reel' },
        contentBottom: { type: 'string', example: 'Text below reel' },
        visibility: { type: 'string', enum: ['public', 'followers', 'private'] },
        videoUrl: { type: 'string', example: 'https://cdn.example.com/reel.mp4' },
        durationSeconds: { type: 'number', example: 42 },
        thumbnailUrl: { type: 'string', example: 'https://cdn.example.com/reel-cover.jpg' },
        style: { type: 'string', example: 'Sharqi' },
        maqam: { type: 'string', example: 'Hijaz' },
        rhythmSignature: { type: 'string', example: '6/8' },
        mentionUsernames: { type: 'array', items: { type: 'string' } },
        videoFile: { type: 'string', format: 'binary' },
        coverImageFile: { type: 'string', format: 'binary' },
      },
    },
  })
  @Post('reels')
  async createReel(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateReelDto,
    @UploadedFiles()
    files?: {
      videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      coverImageFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
    },
  ) {
    return this.postsService.createReel(user.sub, dto, files?.videoFile?.[0], files?.coverImageFile?.[0]);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('reels')
  async findReels(@CurrentUser() user: JwtPayload, @Query() query: ReelQueryDto) {
    return this.postsService.findReels(query, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get(':postId')
  async findById(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.findById(postId, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, MultipartFormDataGuard)
  @UseInterceptors(
    FileFieldsInterceptor([
      { name: 'imageFiles', maxCount: 10 },
      { name: 'videoFile', maxCount: 1 },
      { name: 'audioFile', maxCount: 1 },
      { name: 'coverImageFile', maxCount: 1 },
    ], { limits: { fileSize: MEDIA_MAX_SIZE_BYTES.postsVideo, files: 13 } }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        content: { type: 'string', example: 'Updated content' },
        contentTop: { type: 'string', example: 'Updated text above media' },
        contentBottom: { type: 'string', example: 'Updated text below media' },
        visibility: { type: 'string', enum: ['public', 'followers', 'private'] },
        imageUrls: { type: 'array', items: { type: 'string' } },
        imageCaptions: { type: 'array', items: { type: 'string' } },
        imageAltTexts: { type: 'array', items: { type: 'string' } },
        taggedUserIds: { type: 'array', items: { type: 'string' } },
        collaboratorIds: { type: 'array', items: { type: 'string' } },
        mentionUsernames: { type: 'array', items: { type: 'string' } },
        mentionedUserIds: { type: 'array', items: { type: 'string' } },
        location: { type: 'string', example: 'Jeddah, Saudi Arabia' },
        latitude: { type: 'number', example: 21.5433 },
        longitude: { type: 'number', example: 39.1728 },
        videoUrl: { type: 'string', example: 'https://cdn.example.com/video.mp4' },
        audioUrl: { type: 'string', example: 'https://cdn.example.com/audio.mp3' },
        durationSeconds: { type: 'number', example: 54 },
        thumbnailUrl: { type: 'string', example: 'https://cdn.example.com/cover.jpg' },
        style: { type: 'string', example: 'Sharqi' },
        maqam: { type: 'string', example: 'Hijaz' },
        rhythmSignature: { type: 'string', example: '6/8' },
        waveformPeaks: { type: 'array', items: { type: 'number' } },
        commentsDisabled: { type: 'boolean' },
        commentsFollowersOnly: { type: 'boolean' },
        imageFiles: { type: 'array', items: { type: 'string', format: 'binary' } },
        videoFile: { type: 'string', format: 'binary' },
        audioFile: { type: 'string', format: 'binary' },
        coverImageFile: { type: 'string', format: 'binary' },
      },
    },
  })
  @Patch(':postId')
  async update(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: UpdatePostDto,
    @UploadedFiles()
    files?: {
      imageFiles?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      audioFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
      coverImageFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
    },
  ) {
    return this.postsService.update(
      user.sub,
      postId,
      dto,
      files?.imageFiles ?? [],
      files?.videoFile?.[0],
      files?.audioFile?.[0],
      files?.coverImageFile?.[0],
    );
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Post(':postId/repost')
  async repost(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: CreateRepostDto,
  ) {
    return this.postsService.createRepost(user.sub, postId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch(':postId/comment-settings')
  async updateCommentSettings(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: UpdateCommentSettingsDto,
  ) {
    return this.postsService.updateCommentSettings(user.sub, postId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch(':postId/pin-profile')
  async pinToProfile(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.pinToProfile(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch(':postId/unpin-profile')
  async unpinFromProfile(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.unpinFromProfile(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch(':postId/archive')
  async archive(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.archive(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch(':postId/restore-archive')
  async restoreArchive(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.restoreArchived(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Delete(':postId')
  async remove(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    await this.postsService.remove(user.sub, postId);
    return { success: true };
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.CONTENT_MODERATE)
  @Delete('admin/:postId')
  async removeBySuperAdmin(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    await this.postsService.removeBySuperAdmin(user.email ?? user.sub, postId);
    return { success: true };
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post(':postId/view')
  @Throttle(120, 60_000)
  async registerView(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.registerView(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post(':postId/play')
  @Throttle(120, 60_000)
  async registerPlay(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.registerPlay(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get(':postId/share-sheet')
  async getShareSheet(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.getShareSheet(user.sub, postId);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post(':postId/share/profile')
  async shareToProfile(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: SharePostToProfileDto,
  ) {
    return this.postsService.sharePostToProfile(user.sub, postId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post(':postId/share/friend')
  async shareToFriend(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: SharePostToFriendDto,
  ) {
    return this.postsService.sharePostToFriend(user.sub, postId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post(':postId/share/external')
  async shareExternal(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: SharePostExternalDto,
  ) {
    return this.postsService.sharePostExternal(user.sub, postId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post(':postId/share')
  async registerShare(
    @CurrentUser() user: JwtPayload,
    @Param('postId') postId: string,
    @Body() dto: SharePostDto,
  ) {
    return this.postsService.registerShare(user.sub, postId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Delete(':postId/share')
  async unshare(@CurrentUser() user: JwtPayload, @Param('postId') postId: string) {
    return this.postsService.unsharePost(user.sub, postId);
  }
}
