import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseUUIDPipe,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { PermissionGuard } from '../../auth/guards/permission.guard';
import { Permissions } from '../../auth/decorators/permissions.decorator';
import { AccessLevel, ModuleName } from '../../entities/role-permission.entity';
import { successResponse } from '../../common/responses/api-response';
import { SupplierCostPriceService } from './supplier-cost-price.service';
import {
  CreateSupplierCostPriceDto,
  UpdateSupplierCostPriceDto,
  BulkApplySupplierCostPriceDto,
} from './dto';

/**
 * Supplier cost-price endpoints. Gated by the SUPPLIER permission
 * module since a tenant's ops / admin manages cost configuration
 * alongside the supplier master rows themselves.
 *
 *   GET    /supplier-cost-prices?supplier_id=…   — list for a supplier
 *   GET    /supplier-cost-prices/lookup          — resolve best match
 *   POST   /supplier-cost-prices                 — upsert single row
 *   POST   /supplier-cost-prices/bulk            — bulk-apply shortcut
 *   PATCH  /supplier-cost-prices/:id             — edit existing row
 *   DELETE /supplier-cost-prices/:id             — soft delete
 */
@Controller('supplier-cost-prices')
@UseGuards(JwtAuthGuard, PermissionGuard)
export class SupplierCostPriceController {
  constructor(private readonly service: SupplierCostPriceService) {}

  @Get()
  @Permissions({ module: ModuleName.SUPPLIER, accessLevel: AccessLevel.VIEW })
  async list(@Query('supplier_id', ParseUUIDPipe) supplier_id: string) {
    const data = await this.service.findBySupplier(supplier_id);
    return successResponse(data, 'Supplier cost prices fetched');
  }

  /**
   * Resolve the cost for a specific transport item at quote / booking
   * save time — used by the quote editor's selling-below-cost check.
   * Returns null data (200) when no cost is configured yet; callers
   * treat that as "no guard triggered".
   */
  @Get('lookup')
  @Permissions({ module: ModuleName.SUPPLIER, accessLevel: AccessLevel.VIEW })
  async lookup(
    @Query('supplier_id', ParseUUIDPipe) supplier_id: string,
    @Query('transport_service_id', ParseUUIDPipe) transport_service_id: string,
    // vehicle_type_id is required for PVT, omitted for SIC. When the
    // caller is asking about an SIC line they should pass mode=SIC
    // (and skip the vehicle id) — service-side normalises NULL.
    @Query('vehicle_type_id') vehicle_type_id?: string,
    @Query('mode') modeRaw?: string,
    @Query('season_id') season_id?: string,
    /** YYYY-MM-DD — alternative to season_id. Movement Chart passes
     *  the viewed date so seasonal cost cells (Peak / HSS / …) resolve
     *  without the client knowing season UUIDs. */
    @Query('date') date?: string,
  ) {
    const mode: 'PVT' | 'SIC' = modeRaw === 'SIC' ? 'SIC' : 'PVT';
    const data = await this.service.findBestMatch({
      supplier_id,
      transport_service_id,
      vehicle_type_id: mode === 'SIC' ? null : vehicle_type_id || null,
      mode,
      season_id: season_id || null,
      date: date || null,
    });
    return successResponse(data, data ? 'Cost price matched' : 'No cost price configured');
  }

  @Post()
  @Permissions({ module: ModuleName.SUPPLIER, accessLevel: AccessLevel.CREATE })
  async upsert(@Body() dto: CreateSupplierCostPriceDto) {
    const result = await this.service.upsert(dto);
    return successResponse(result, result.created ? 'Cost price created' : 'Cost price updated');
  }

  @Post('bulk')
  @Permissions({ module: ModuleName.SUPPLIER, accessLevel: AccessLevel.EDIT })
  async bulk(@Body() dto: BulkApplySupplierCostPriceDto) {
    const result = await this.service.bulkApply(dto);
    return successResponse(result, `${result.applied} cost prices applied`);
  }

  @Patch(':id')
  @Permissions({ module: ModuleName.SUPPLIER, accessLevel: AccessLevel.EDIT })
  async update(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateSupplierCostPriceDto) {
    const result = await this.service.update(id, dto);
    return successResponse(result, result.message);
  }

  @Delete(':id')
  @Permissions({ module: ModuleName.SUPPLIER, accessLevel: AccessLevel.DELETE })
  async remove(@Param('id', ParseUUIDPipe) id: string) {
    const result = await this.service.remove(id);
    return successResponse(result, result.message);
  }
}
