import {
  Controller,
  Get,
  Post,
  Put,
  Patch,
  Delete,
  Body,
  Param,
  Query,
  UseInterceptors,
  UploadedFile,
  BadRequestException,
  OnModuleInit,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiTags, ApiBearerAuth, ApiConsumes, ApiBody } from '@nestjs/swagger';
import { diskStorage } from 'multer';
import { extname } from 'path';
import { CmsService } from './cms.service';
import {
  CreateProjectDto,
  UpdateProjectDto,
  ReorderProjectsDto,
  UpdateSiteContentDto,
  CreateClientDto,
  UpdateClientDto,
} from './dto';
import { Public, Roles } from '../../common/decorators';

// Generate unique filename
const storage = diskStorage({
  destination: './uploads',
  filename: (req, file, cb) => {
    const uniqueName = `${Date.now()}-${Math.round(Math.random() * 1e9)}${extname(file.originalname)}`;
    cb(null, uniqueName);
  },
});

@ApiTags('CMS')
@Controller('cms')
export class CmsController implements OnModuleInit {
  constructor(private readonly cmsService: CmsService) { }

  async onModuleInit() {
    await this.cmsService.seedDefaultProjects();
    await this.cmsService.seedAdminUser();
  }

  // ── Public Endpoints ────────────────────────────

  @Public()
  @Get('projects')
  findAllProjects() {
    return this.cmsService.findAllProjects();
  }

  @Public()
  @Get('content')
  findAllContent(@Query('locale') locale?: string) {
    return this.cmsService.findAllContent(locale);
  }

  @Public()
  @Get('content/:section')
  findContentBySection(
    @Param('section') section: string,
    @Query('locale') locale?: string,
  ) {
    return this.cmsService.findContentBySection(section, locale ?? 'tr');
  }

  // ── Admin: Projects ─────────────────────────────

  @ApiBearerAuth()
  @Roles('admin')
  @Post('projects')
  createProject(@Body() dto: CreateProjectDto) {
    return this.cmsService.createProject(dto);
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Put('projects/:id')
  updateProject(@Param('id') id: string, @Body() dto: UpdateProjectDto) {
    return this.cmsService.updateProject(id, dto);
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Delete('projects/:id')
  deleteProject(@Param('id') id: string) {
    return this.cmsService.deleteProject(id);
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Post('projects/:id/restore')
  restoreProject(@Param('id') id: string) {
    return this.cmsService.restoreProject(id);
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Patch('projects/reorder')
  reorderProjects(@Body() dto: ReorderProjectsDto) {
    return this.cmsService.reorderProjects(dto);
  }

  // ── Admin: Site Content ─────────────────────────

  @ApiBearerAuth()
  @Roles('admin')
  @Put('content/:section')
  upsertContent(
    @Param('section') section: string,
    @Query('locale') locale: string = 'tr',
    @Body() dto: UpdateSiteContentDto,
  ) {
    return this.cmsService.upsertContent(section, locale, dto);
  }

  // ── Admin: Media Upload ─────────────────────────

  @ApiBearerAuth()
  @Roles('admin')
  @Post('upload')
  @UseInterceptors(FileInterceptor('file', { storage }))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: { file: { type: 'string', format: 'binary' } },
    },
  })
  async uploadFile(
    @UploadedFile() file: Express.Multer.File,
  ) {
    try {
      if (!file) {
        throw new BadRequestException('Dosya bulunamadı');
      }
      if (!file.mimetype.startsWith('image/')) {
        throw new BadRequestException('Sadece görsel dosyaları yüklenebilir');
      }
      const url = `/uploads/${file.filename}`;
      const media = await this.cmsService.createMediaFile({
        filename: file.filename,
        originalName: file.originalname,
        mimetype: file.mimetype,
        path: file.path,
        url,
        size: file.size,
      });
      return media;
    } catch (err) {
      throw err;
    }
  }

  @Public()
  @Get('media')
  findAllMedia() {
    return this.cmsService.findAllMedia();
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Delete('media/:id')
  deleteMedia(@Param('id') id: string) {
    return this.cmsService.deleteMedia(id);
  }

  // ── Public: Clients ─────────────────────────

  @Public()
  @Get('clients')
  findAllClients() {
    return this.cmsService.findAllClients();
  }

  // ── Admin: Clients ─────────────────────────

  @ApiBearerAuth()
  @Roles('admin')
  @Post('clients')
  createClient(@Body() dto: CreateClientDto) {
    return this.cmsService.createClient(dto);
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Put('clients/:id')
  updateClient(@Param('id') id: string, @Body() dto: UpdateClientDto) {
    return this.cmsService.updateClient(id, dto);
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Delete('clients/:id')
  deleteClient(@Param('id') id: string) {
    return this.cmsService.deleteClient(id);
  }

  // ── Admin: Audit Logs ───────────────────────

  @ApiBearerAuth()
  @Roles('admin')
  @Get('audit-logs')
  findAuditLogs(
    @Query('entity') entity?: string,
    @Query('action') action?: string,
    @Query('limit') limit?: string,
    @Query('offset') offset?: string,
  ) {
    return this.cmsService.findAuditLogs({
      entity,
      action,
      limit: limit ? parseInt(limit, 10) : 50,
      offset: offset ? parseInt(offset, 10) : 0,
    });
  }

  @ApiBearerAuth()
  @Roles('admin')
  @Get('audit-logs/:entity/:entityId')
  findEntityAuditLogs(
    @Param('entity') entity: string,
    @Param('entityId') entityId: string,
  ) {
    return this.cmsService.findAuditLogsByEntity(entity, entityId);
  }
}
