import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Patch,
  Delete,
  Query,
  Req,
  ParseIntPipe,
  UploadedFiles,
  UseInterceptors,
  Logger,
} from '@nestjs/common';
import { FilesInterceptor } from '@nestjs/platform-express';
import { CompaniesService } from './companies.service';
import { CreateCompanyDto } from './dto/create-company.dto';
import { UpdateCompanyDto } from './dto/update-company.dto';
import { CompanyMergeService } from './services/company-merge.service';

@Controller('companies')
export class CompaniesController {
  private readonly logger = new Logger('CompaniesController');

   constructor(
    private readonly companiesService: CompaniesService,
    private readonly mergeService: CompanyMergeService,
  ) {}
  // ── Helper: extract current user id from JWT ────────────────────────────
  private getCurrentUserId(req: Request): number {
    const user = (req as any).user;
    const id = user?.id ?? user?.userId ?? user?.sub;
    if (id === undefined || id === null) {
      throw new Error('User id not found on request.user');
    }
    return Number(id);
  }

  @Post()
  @UseInterceptors(FilesInterceptor('documents'))
  async create(
    @UploadedFiles() files: Express.Multer.File[],
    @Body() dto: CreateCompanyDto,
  ) {
    if (files?.length) {
      dto.documents = files.map((file) => ({
        originalName: file.originalname,
        fileName: file.filename,
        filePath: `uploads/company-documents/${file.filename}`,
      }));
    }
    return this.companiesService.create(dto);
  }

  @Patch(':id')
  @UseInterceptors(FilesInterceptor('documents'))
  async update(
    @Param('id') id: string,
    @UploadedFiles() files: Express.Multer.File[],
    @Body() dto: UpdateCompanyDto,
  ) {
    if (files?.length) {
      dto.documents = files.map((file) => ({
        originalName: file.originalname,
        fileName: file.filename,
        filePath: `uploads/company-documents/${file.filename}`,
      }));
    }
    return this.companiesService.update(+id, dto);
  }

  // ✅ Static routes BEFORE :id
  @Get('analytics/certification-body')
  getAnalyticsByCertBody() {
    return this.companiesService.getAnalyticsByCertBody();
  }

  @Get('migrate')
  migrateUniqueCompanies() {
    return this.companiesService.migrateUniqueCompanies();
  }

  // 🆕 ISSUE 4 FIX — Backfill normalized_name for companies with NULL values
  //    Safe to run multiple times. Reports duplicates without auto-deleting.
  @Get('backfill-normalized-names')
  backfillNormalizedNames() {
    return this.companiesService.backfillNormalizedNames();
  }

  // ═══════════════════════════════════════════════════════════════════════════
  // 🆕 COMPANY MERGE — find duplicates, merge, view history
  //    Must be BEFORE @Get(':id') or NestJS treats "merge" as a company ID
  // ═══════════════════════════════════════════════════════════════════════════

  @Get('merge/duplicates')
  async findDuplicates() {
    return this.mergeService.findDuplicateGroups();
  }

  @Post('merge')
  async mergeCompanies(
    @Body() body: { keep_id: number; remove_id: number },
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    return this.mergeService.mergeCompanies(body.keep_id, body.remove_id, userId);
  }

  @Get('merge/history')
  async mergeHistory() {
    return this.mergeService.getMergeHistory();
  }

  @Get()
  findAll(
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('search') search?: string,
  ) {
    const pageNumber = page ? parseInt(page, 10) : 1;
    const pageSize = limit ? parseInt(limit, 10) : 10; // ✅ default 10
    return this.companiesService.findAll({
      page: pageNumber,
      limit: pageSize,
      search,
    });
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.companiesService.findOne(+id);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.companiesService.remove(+id);
  }

  // ═══════════════════════════════════════════════════════════════════════════
  // 🆕 ISSUE 5 & 6 — CLIENT PORTAL ACCESS CONTROL ENDPOINTS
  //    All under /companies/:id/portal-access
  // ═══════════════════════════════════════════════════════════════════════════

  /**
   * GET /companies/:id/portal-users
   * List all portal users for this company with their access status.
   */
  @Get(':id/portal-users')
  async getPortalUsers(@Param('id', ParseIntPipe) id: number) {
    return this.companiesService.getPortalUsers(id);
  }

  /**
   * POST /companies/:id/portal-access
   * Grant portal access to a user for this company.
   * Body: { user_id: number, email: string }
   */
  @Post(':id/portal-access')
  async grantPortalAccess(
    @Param('id', ParseIntPipe) companyId: number,
    @Body() body: { user_id: number; email: string },
    @Req() req: Request,
  ) {
    const grantedById = this.getCurrentUserId(req);
    this.logger.log(
      `POST /companies/${companyId}/portal-access — user_id=${body.user_id} email=${body.email} by=${grantedById}`,
    );
    return this.companiesService.grantPortalAccess(
      companyId,
      body.user_id,
      body.email,
      grantedById,
    );
  }

  /**
   * PATCH /companies/:id/portal-access/:userId/disable
   * Disable a specific user's portal access (instant, reversible).
   */
  @Patch(':id/portal-access/:userId/disable')
  async disablePortalAccess(
    @Param('id', ParseIntPipe) companyId: number,
    @Param('userId', ParseIntPipe) userId: number,
    @Req() req: Request,
  ) {
    const disabledById = this.getCurrentUserId(req);
    this.logger.log(
      `PATCH /companies/${companyId}/portal-access/${userId}/disable — by=${disabledById}`,
    );
    return this.companiesService.disablePortalAccess(companyId, userId, disabledById);
  }

  /**
   * PATCH /companies/:id/portal-access/:userId/enable
   * Re-enable a previously disabled user's portal access.
   */
  @Patch(':id/portal-access/:userId/enable')
  async enablePortalAccess(
    @Param('id', ParseIntPipe) companyId: number,
    @Param('userId', ParseIntPipe) userId: number,
    @Req() req: Request,
  ) {
    const enabledById = this.getCurrentUserId(req);
    this.logger.log(
      `PATCH /companies/${companyId}/portal-access/${userId}/enable — by=${enabledById}`,
    );
    return this.companiesService.enablePortalAccess(companyId, userId, enabledById);
  }

  /**
   * POST /companies/:id/portal-access/disable-all
   * Emergency kill switch — disable ALL portal users for this company instantly.
   */
  @Post(':id/portal-access/disable-all')
  async disableAllPortalAccess(
    @Param('id', ParseIntPipe) companyId: number,
    @Req() req: Request,
  ) {
    const disabledById = this.getCurrentUserId(req);
    this.logger.log(
      `POST /companies/${companyId}/portal-access/disable-all — by=${disabledById}`,
    );
    return this.companiesService.disableAllPortalAccess(companyId, disabledById);
  }

  /**
   * DELETE /companies/:id/portal-access/:userId
   * Permanently revoke (hard delete) — admin only. 
   * Use disable in most cases (it's reversible).
   */
  @Delete(':id/portal-access/:userId')
  async revokePortalAccess(
    @Param('id', ParseIntPipe) companyId: number,
    @Param('userId', ParseIntPipe) userId: number,
  ) {
    this.logger.log(
      `DELETE /companies/${companyId}/portal-access/${userId} — permanent revoke`,
    );
    return this.companiesService.revokePortalAccess(companyId, userId);
  }
}
