import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  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 { PoliciesService } from "./policies.service";
import {
  AdjusterDto,
  PolicyTypeDto,
  ProviderDto,
  UpdateAdjusterDto,
  UpdatePolicyTypeDto,
  UpdateProviderDto,
} from "./lookup.dto";

/**
 * Insurance reference data: providers, policy types, adjusters. Reading is open
 * to any authenticated user (the policy form needs the options); mutating needs
 * "lookup:manage" (MANAGER+).
 */
@UseGuards(AuthenticatedGuard, AbilityGuard)
@Controller("lookups")
export class LookupsController {
  constructor(
    private readonly policies: PoliciesService,
    private readonly audit: AuditService,
  ) {}

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

  @Get()
  list() {
    return this.policies.listLookups();
  }

  @Post("providers")
  @RequireAbility("lookup:manage")
  async createProvider(@Body() dto: ProviderDto, @Req() req: Request) {
    const row = await this.policies.createProvider(dto);
    void this.audit.log(this.actingId(req), "lookup.provider.create", {
      providerId: row.id,
      name: row.name,
    });
    return row;
  }
  @Patch("providers/:id")
  @RequireAbility("lookup:manage")
  async updateProvider(
    @Param("id") id: string,
    @Body() dto: UpdateProviderDto,
    @Req() req: Request,
  ) {
    const row = await this.policies.updateProvider(id, dto);
    void this.audit.log(this.actingId(req), "lookup.provider.update", {
      providerId: id,
    });
    return row;
  }
  @Delete("providers/:id")
  @RequireAbility("lookup:manage")
  async removeProvider(@Param("id") id: string, @Req() req: Request) {
    const row = await this.policies.removeProvider(id);
    void this.audit.log(this.actingId(req), "lookup.provider.delete", {
      providerId: id,
    });
    return row;
  }

  @Post("policy-types")
  @RequireAbility("lookup:manage")
  async createType(@Body() dto: PolicyTypeDto, @Req() req: Request) {
    const row = await this.policies.createPolicyType(dto);
    void this.audit.log(this.actingId(req), "lookup.policyType.create", {
      policyTypeId: row.id,
      name: row.name,
    });
    return row;
  }
  @Patch("policy-types/:id")
  @RequireAbility("lookup:manage")
  async updateType(
    @Param("id") id: string,
    @Body() dto: UpdatePolicyTypeDto,
    @Req() req: Request,
  ) {
    const row = await this.policies.updatePolicyType(id, dto);
    void this.audit.log(this.actingId(req), "lookup.policyType.update", {
      policyTypeId: id,
    });
    return row;
  }
  @Delete("policy-types/:id")
  @RequireAbility("lookup:manage")
  async removeType(@Param("id") id: string, @Req() req: Request) {
    const row = await this.policies.removePolicyType(id);
    void this.audit.log(this.actingId(req), "lookup.policyType.delete", {
      policyTypeId: id,
    });
    return row;
  }

  @Post("adjusters")
  @RequireAbility("lookup:manage")
  async createAdjuster(@Body() dto: AdjusterDto, @Req() req: Request) {
    const row = await this.policies.createAdjuster(dto);
    void this.audit.log(this.actingId(req), "lookup.adjuster.create", {
      adjusterId: row.id,
    });
    return row;
  }
  @Patch("adjusters/:id")
  @RequireAbility("lookup:manage")
  async updateAdjuster(
    @Param("id") id: string,
    @Body() dto: UpdateAdjusterDto,
    @Req() req: Request,
  ) {
    const row = await this.policies.updateAdjuster(id, dto);
    void this.audit.log(this.actingId(req), "lookup.adjuster.update", {
      adjusterId: id,
    });
    return row;
  }
  @Delete("adjusters/:id")
  @RequireAbility("lookup:manage")
  async removeAdjuster(@Param("id") id: string, @Req() req: Request) {
    const row = await this.policies.removeAdjuster(id);
    void this.audit.log(this.actingId(req), "lookup.adjuster.delete", {
      adjusterId: id,
    });
    return row;
  }
}
