import {
  Controller,
  Get,
  Post,
  Patch,
  Delete,
  Param,
  Body,
  Query,
  HttpCode,
  HttpStatus,
  Logger,
  ParseUUIDPipe,
  Req,
  UploadedFile,
  UseInterceptors,
  BadRequestException,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiQuery,
  ApiConsumes,
} from '@nestjs/swagger';
import { FileInterceptor } from '@nestjs/platform-express';
import { ProjectsService } from './projects.service';
import { CreateProjectDto, UpdateProjectDto, CreateFromTweetDto, CreateFromYoutubeDto, CreateFromDocumentDto, CreateFromExtractedTextDto } from './dto/project.dto';

@ApiTags('projects')
@ApiBearerAuth()
@Controller('projects')
export class ProjectsController {
  private readonly logger = new Logger(ProjectsController.name);

  constructor(private readonly projectsService: ProjectsService) {}

  /**
   * Yeni bir video projesi oluşturur (DRAFT durumunda).
   */
  @Post()
  @ApiOperation({ summary: 'Yeni video projesi oluştur' })
  @ApiResponse({ status: 201, description: 'Proje başarıyla oluşturuldu' })
  async create(@Body() dto: CreateProjectDto, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Yeni proje oluşturuluyor: "${dto.title}"`);
    return this.projectsService.create(userId, dto);
  }

  /**
   * Kullanıcının tüm projelerini listeler.
   */
  @Get()
  @ApiOperation({ summary: 'Tüm projeleri listele' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'status', required: false, type: String })
  @ApiResponse({ status: 200, description: 'Proje listesi' })
  async findAll(
    @Req() req: any,
    @Query('page') page?: number,
    @Query('limit') limit?: number,
    @Query('status') status?: string,
  ) {
    const userId = req.user?.id || req.user?.sub;
    return this.projectsService.findAll(userId, {
      page: page || 1,
      limit: limit || 10,
      status,
    });
  }

  /**
   * Tek bir projeyi sahneleri ve medya asset'leriyle birlikte getirir.
   */
  @Get(':id')
  @ApiOperation({ summary: 'Proje detaylarını getir' })
  @ApiResponse({ status: 200, description: 'Proje detayları' })
  @ApiResponse({ status: 404, description: 'Proje bulunamadı' })
  async findOne(@Param('id', ParseUUIDPipe) id: string, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    return this.projectsService.findOne(userId, id);
  }

  /**
   * Projeyi günceller (sadece DRAFT durumundaki projeler güncellenebilir).
   */
  @Patch(':id')
  @ApiOperation({ summary: 'Projeyi güncelle' })
  @ApiResponse({ status: 200, description: 'Proje güncellendi' })
  async update(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateProjectDto,
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Proje güncelleniyor: ${id}`);
    return this.projectsService.update(userId, id, dto);
  }

  /**
   * Projeyi soft-delete ile siler.
   */
  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Projeyi sil (soft delete)' })
  @ApiResponse({ status: 204, description: 'Proje silindi' })
  async remove(@Param('id', ParseUUIDPipe) id: string, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Proje siliniyor: ${id}`);
    return this.projectsService.remove(userId, id);
  }

  /**
   * AI ile senaryo üretimini tetikler.
   */
  @Post(':id/generate-script')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'AI ile senaryo üret (Gemini)' })
  @ApiResponse({ status: 200, description: 'Senaryo üretildi ve kaydedildi' })
  async generateScript(@Param('id', ParseUUIDPipe) id: string, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Senaryo üretimi başlatılıyor: ${id}`);
    return this.projectsService.generateScript(userId, id);
  }

  /**
   * Senaryoyu onaylar ve video üretim kuyruğuna gönderir.
   */
  @Post(':id/approve')
  @HttpCode(HttpStatus.ACCEPTED)
  @ApiOperation({ summary: 'Senaryoyu onayla ve video üretimini başlat' })
  @ApiResponse({ status: 202, description: 'Video üretimi kuyruğa eklendi' })
  async approveAndStartGeneration(
    @Param('id', ParseUUIDPipe) id: string,
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Proje onaylanıyor ve kuyruğa gönderiliyor: ${id}`);
    return this.projectsService.approveAndQueueGeneration(userId, id);
  }

  /**
   * X/Twitter tweet URL'sinden otomatik proje oluşturur ve senaryo üretir.
   * Tweet çekilir → prompt'a dönüştürülür → AI senaryo üretir → proje kaydedilir.
   */
  @Post('from-tweet')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'X/Twitter tweet\'ten proje oluştur' })
  @ApiResponse({ status: 201, description: 'Tweet\'ten proje oluşturuldu ve senaryo üretildi' })
  @ApiResponse({ status: 400, description: 'Geçersiz tweet URL\'si veya tweet bulunamadı' })
  async createFromTweet(@Body() dto: CreateFromTweetDto, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Tweet'ten proje oluşturuluyor: ${dto.tweetUrl}`);
    return this.projectsService.createFromTweet(userId, dto);
  }

  /**
   * YouTube URL'sinden otomatik proje oluşturur ve senaryo üretir.
   */
  @Post('from-youtube')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'YouTube videosundan proje oluştur' })
  @ApiResponse({ status: 201, description: 'YouTube videosundan proje oluşturuldu ve senaryo üretildi' })
  async createFromYoutube(@Body() dto: CreateFromYoutubeDto, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`YouTube'dan proje oluşturuluyor: ${dto.youtubeUrl}`);
    return this.projectsService.createFromYoutube(userId, dto);
  }

  /**
   * Yüklenen dokümandan (Word, PDF, Excel vb.) otomatik proje oluşturur.
   */
  @Post('from-document')
  @HttpCode(HttpStatus.CREATED)
  @UseInterceptors(FileInterceptor('file'))
  @ApiConsumes('multipart/form-data')
  @ApiOperation({ summary: 'Dosyadan/Dokümandan proje oluştur' })
  @ApiResponse({ status: 201, description: 'Belgeden proje oluşturuldu ve senaryo üretildi' })
  async createFromDocument(
    @UploadedFile() file: Express.Multer.File,
    @Body() dto: CreateFromDocumentDto,
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Dosyadan proje oluşturuluyor: ${file?.originalname}`);
    if (!file) {
      throw new BadRequestException('Dosya yüklenmedi');
    }
    return this.projectsService.createFromDocument(userId, file, dto);
  }

  /**
   * Doküman yüklenip metni çıkarılır ve video konu önerileri üretilir.
   */
  @Post('extract-document-topics')
  @HttpCode(HttpStatus.OK)
  @UseInterceptors(FileInterceptor('file'))
  @ApiConsumes('multipart/form-data')
  @ApiOperation({ summary: 'Dosyadan metin çıkar ve konu önerileri al' })
  @ApiResponse({ status: 200, description: 'Metin ve konular başarıyla çıkarıldı' })
  async extractDocumentTopics(
    @UploadedFile() file: Express.Multer.File,
    @Req() req: any,
  ) {
    this.logger.log(`Dosyadan metin ve konular çıkarılıyor: ${file?.originalname}`);
    if (!file) {
      throw new BadRequestException('Dosya yüklenmedi');
    }
    return this.projectsService.extractDocumentTopics(file);
  }

  /**
   * Extracted text ve seçilen konu üzerinden doğrudan proje oluşturur.
   */
  @Post('document-from-topic')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Seçilen konu ve metin ile proje oluştur' })
  @ApiResponse({ status: 201, description: 'Seçilen konu baz alınarak proje oluşturuldu' })
  async createFromTopic(@Body() dto: CreateFromExtractedTextDto, @Req() req: any) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Metin ve konu üzerinden proje oluşturuluyor. Konu: ${dto.topic}`);
    return this.projectsService.createFromExtractedText(userId, dto);
  }

  /**
   * Tekil sahne güncelleme (narrasyon, görsel prompt, süre).
   */
  @Patch(':id/scenes/:sceneId')
  @ApiOperation({ summary: 'Sahneyi güncelle' })
  @ApiResponse({ status: 200, description: 'Sahne güncellendi' })
  async updateScene(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('sceneId', ParseUUIDPipe) sceneId: string,
    @Body() body: { narrationText?: string; visualPrompt?: string; subtitleText?: string; duration?: number },
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Sahne güncelleniyor: ${sceneId} (proje: ${id})`);
    return this.projectsService.updateScene(userId, id, sceneId, body);
  }

  /**
   * Tekil sahneyi AI ile yeniden üretir.
   */
  @Post(':id/scenes/:sceneId/regenerate')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Sahneyi AI ile yeniden üret' })
  @ApiResponse({ status: 200, description: 'Sahne yeniden üretildi' })
  async regenerateScene(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('sceneId', ParseUUIDPipe) sceneId: string,
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Sahne yeniden üretiliyor: ${sceneId} (proje: ${id})`);
    return this.projectsService.regenerateScene(userId, id, sceneId);
  }

  /**
   * Sahne için ID bazında görsel üret (Gemini AI).
   * Kullanıcı custom prompt sağlarsa, önce prompt güncellenir ardından resim üretilir.
   */
  @Post(':id/scenes/:sceneId/generate-image')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Sahne görselini üret' })
  @ApiResponse({ status: 200, description: 'Görsel üretildi' })
  async generateSceneImage(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('sceneId', ParseUUIDPipe) sceneId: string,
    @Body() body: { customPrompt?: string },
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Sahne görseli üretiliyor: ${sceneId} (proje: ${id})`);
    return this.projectsService.generateSceneImage(userId, id, sceneId, body?.customPrompt);
  }

  /**
   * Sahne görselini 4K olarak yeniden boyutlandırır (Upscale)
   */
  @Post(':id/scenes/:sceneId/upscale-image')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Sahne görselini upscale (4K) yap' })
  @ApiResponse({ status: 200, description: 'Görsel başarıyla upscale edildi' })
  async upscaleSceneImage(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('sceneId', ParseUUIDPipe) sceneId: string,
    @Req() req: any,
  ) {
    const userId = req.user?.id || req.user?.sub;
    this.logger.log(`Sahne görseli upscale ediliyor: ${sceneId} (proje: ${id})`);
    return this.projectsService.upscaleSceneImage(userId, id, sceneId);
  }
}
