import {
  Controller,
  Post,
  Get,
  Query,
  UseGuards,
  UseInterceptors,
  UploadedFile,
  Res,
  BadRequestException,
} from "@nestjs/common";
import { FileInterceptor } from "@nestjs/platform-express";
import { Response } from "express";
import { ImportExportService } from "./services/import-export.service";
import { ExportQueryDto, ExportFormat, ImportResponseDto } from "./dto";
import { AuthGuard } from "../auth/guards/auth.guard";
import { WorkspaceGuard, PermissionGuard } from "../common/guards";
import { Workspace, Permission, RequirePermission } from "../common/decorators";
import { CurrentUser } from "../auth/decorators/current-user.decorator";
import type { AuthUser } from "../auth/types/better-auth-request.interface";

/**
 * Controller for knowledge import/export endpoints
 * All endpoints require authentication and workspace context
 */
@Controller("knowledge")
@UseGuards(AuthGuard, WorkspaceGuard, PermissionGuard)
export class ImportExportController {
  constructor(private readonly importExportService: ImportExportService) {}

  /**
   * POST /api/knowledge/import
   * Import knowledge entries from uploaded file (.md or .zip)
   * Requires: MEMBER role or higher
   */
  @Post("import")
  @RequirePermission(Permission.WORKSPACE_MEMBER)
  @UseInterceptors(
    FileInterceptor("file", {
      limits: {
        fileSize: 50 * 1024 * 1024, // 50MB max file size
      },
      fileFilter: (_req, file, callback) => {
        // Only accept .md and .zip files
        const allowedMimeTypes = [
          "text/markdown",
          "application/zip",
          "application/x-zip-compressed",
        ];
        const allowedExtensions = [".md", ".zip"];
        const fileExtension = file.originalname
          .toLowerCase()
          .slice(file.originalname.lastIndexOf("."));

        if (allowedMimeTypes.includes(file.mimetype) || allowedExtensions.includes(fileExtension)) {
          callback(null, true);
        } else {
          callback(
            new BadRequestException("Invalid file type. Only .md and .zip files are accepted."),
            false
          );
        }
      },
    })
  )
  async importEntries(
    @Workspace() workspaceId: string,
    @CurrentUser() user: AuthUser,
    @UploadedFile() file: Express.Multer.File | undefined
  ): Promise<ImportResponseDto> {
    if (!file) {
      throw new BadRequestException("No file uploaded");
    }

    const result = await this.importExportService.importEntries(workspaceId, user.id, file);

    return {
      success: result.failed === 0,
      totalFiles: result.totalFiles,
      imported: result.imported,
      failed: result.failed,
      results: result.results,
    };
  }

  /**
   * GET /api/knowledge/export
   * Export knowledge entries as a zip file
   * Query params:
   *   - format: 'markdown' (default) or 'json'
   *   - entryIds: optional array of entry IDs to export (exports all if not provided)
   * Requires: Any workspace member
   */
  @Get("export")
  @RequirePermission(Permission.WORKSPACE_ANY)
  async exportEntries(
    @Workspace() workspaceId: string,
    @Query() query: ExportQueryDto,
    @Res() res: Response
  ): Promise<void> {
    const format = query.format ?? ExportFormat.MARKDOWN;
    const entryIds = query.entryIds;

    const { stream, filename } = await this.importExportService.exportEntries(
      workspaceId,
      format,
      entryIds
    );

    // Set response headers
    res.setHeader("Content-Type", "application/zip");
    res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);

    // Pipe the archive stream to response
    stream.pipe(res);
  }
}
