import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  Req,
  UseGuards,
} from "@nestjs/common";
import { Request } from "express";
import { AuthenticatedGuard } from "../auth/authenticated.guard";
import { AbilityGuard } from "../auth/ability.guard";
import { RequireAbility } from "../auth/require-ability.decorator";
import { AuditService } from "../common/audit.service";
import { CustomersService } from "./customers.service";
import { CreateCustomerDto } from "./create-customer.dto";
import { UpdateCustomerDto } from "./update-customer.dto";

@UseGuards(AuthenticatedGuard, AbilityGuard)
@Controller("customers")
export class CustomersController {
  constructor(
    private readonly customers: CustomersService,
    private readonly audit: AuditService,
  ) {}

  private actingId(req: Request): string {
    return (req.user as { id: string }).id;
  }

  @Get("stats")
  stats() {
    return this.customers.stats();
  }

  @Get()
  list(
    @Query("query") query?: string,
    @Query("page") page?: string,
    @Query("pageSize") pageSize?: string,
    @Query("line") line?: "utility" | "insurance" | "both",
    @Query("includeArchived") includeArchived?: string,
  ) {
    const p = Math.max(1, Number(page) || 1);
    const ps = Math.min(100, Math.max(1, Number(pageSize) || 25));
    return this.customers.list({
      query,
      page: p,
      pageSize: ps,
      line,
      includeArchived: includeArchived === "true",
    });
  }

  @Get(":id")
  detail(@Param("id") id: string) {
    return this.customers.detail(id);
  }

  @Post()
  @RequireAbility("customer:create")
  async create(@Body() dto: CreateCustomerDto, @Req() req: Request) {
    const c = await this.customers.create(dto);
    void this.audit.log(this.actingId(req), "customer.create", { customerId: c.id, name: c.name });
    return c;
  }

  @Patch(":id")
  @RequireAbility("customer:update")
  async update(
    @Param("id") id: string,
    @Body() dto: UpdateCustomerDto,
    @Req() req: Request,
  ) {
    const c = await this.customers.update(id, dto);
    void this.audit.log(this.actingId(req), "customer.update", { customerId: id });
    return c;
  }

  @Delete(":id")
  @RequireAbility("customer:delete")
  async archive(@Param("id") id: string, @Req() req: Request) {
    const c = await this.customers.archive(id);
    void this.audit.log(this.actingId(req), "customer.archive", { customerId: id });
    return c;
  }

  @Post(":id/restore")
  @RequireAbility("customer:delete")
  async restore(@Param("id") id: string, @Req() req: Request) {
    const c = await this.customers.restore(id);
    void this.audit.log(this.actingId(req), "customer.restore", { customerId: id });
    return c;
  }
}
