import {
  Controller,
  Get,
  Post,
  Query,
  Param,
  Body,
  Request,
  Inject,
  UseGuards,
} from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { SupportService } from "./support.service.js";
import { createZodDto, ZodResponse } from "nestjs-zod";
import { Public } from "@bff/modules/auth/decorators/public.decorator.js";
import { RateLimit, RateLimitGuard } from "@bff/core/rate-limiting/index.js";
import {
  supportCaseFilterSchema,
  supportCaseListSchema,
  supportCaseSchema,
  createCaseRequestSchema,
  createCaseResponseSchema,
  publicContactRequestSchema,
  caseMessageListSchema,
  addCaseCommentRequestSchema,
  addCaseCommentResponseSchema,
  type SupportCaseList,
  type SupportCase,
  type CreateCaseResponse,
  type CaseMessageList,
  type AddCaseCommentResponse,
} from "@customer-portal/domain/support";
import type { RequestWithUser } from "@bff/modules/auth/auth.types.js";
import { hashEmailForLogs } from "./support.logging.js";
import type { ActionMessageResponse } from "@customer-portal/domain/common";
import { actionMessageResponseSchema } from "@customer-portal/domain/common";

class SupportCaseFilterDto extends createZodDto(supportCaseFilterSchema) {}
class CreateCaseRequestDto extends createZodDto(createCaseRequestSchema) {}
class PublicContactRequestDto extends createZodDto(publicContactRequestSchema) {}
class SupportCaseListDto extends createZodDto(supportCaseListSchema) {}
class SupportCaseDto extends createZodDto(supportCaseSchema) {}
class CreateCaseResponseDto extends createZodDto(createCaseResponseSchema) {}
class CaseMessageListDto extends createZodDto(caseMessageListSchema) {}
class AddCaseCommentRequestDto extends createZodDto(addCaseCommentRequestSchema) {}
class AddCaseCommentResponseDto extends createZodDto(addCaseCommentResponseSchema) {}
class ActionMessageResponseDto extends createZodDto(actionMessageResponseSchema) {}

@Controller("support")
export class SupportController {
  constructor(
    private readonly supportService: SupportService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  @Get("cases")
  @ZodResponse({ description: "List support cases", type: SupportCaseListDto })
  async listCases(
    @Request() req: RequestWithUser,
    @Query() filters: SupportCaseFilterDto
  ): Promise<SupportCaseList> {
    return this.supportService.listCases(req.user.id, filters);
  }

  @Get("cases/:id")
  @ZodResponse({ description: "Get support case", type: SupportCaseDto })
  async getCase(
    @Request() req: RequestWithUser,
    @Param("id") caseId: string
  ): Promise<SupportCase> {
    return this.supportService.getCase(req.user.id, caseId);
  }

  /**
   * Get all messages for a case (conversation view)
   *
   * Returns a unified timeline of EmailMessages and public CaseComments,
   * sorted chronologically for displaying a conversation thread.
   */
  @Get("cases/:id/messages")
  @ZodResponse({ description: "Get case messages", type: CaseMessageListDto })
  async getCaseMessages(
    @Request() req: RequestWithUser,
    @Param("id") caseId: string
  ): Promise<CaseMessageList> {
    return this.supportService.getCaseMessages(req.user.id, caseId, req.user.email);
  }

  /**
   * Add a comment to a case (customer reply via portal)
   *
   * Creates a public CaseComment visible to both customer and agents.
   */
  @Post("cases/:id/comments")
  @ZodResponse({ description: "Add case comment", type: AddCaseCommentResponseDto })
  async addCaseComment(
    @Request() req: RequestWithUser,
    @Param("id") caseId: string,
    @Body() body: AddCaseCommentRequestDto
  ): Promise<AddCaseCommentResponse> {
    return this.supportService.addCaseComment(req.user.id, caseId, body);
  }

  @Post("cases")
  @ZodResponse({ description: "Create support case", type: CreateCaseResponseDto })
  async createCase(
    @Request() req: RequestWithUser,
    @Body() body: CreateCaseRequestDto
  ): Promise<CreateCaseResponse> {
    return this.supportService.createCase(req.user.id, body);
  }

  /**
   * Public contact form endpoint
   *
   * Creates a Lead or Case in Salesforce for unauthenticated users.
   * Rate limited to prevent spam.
   */
  @Post("contact")
  @Public()
  @UseGuards(RateLimitGuard)
  @RateLimit({ limit: 5, ttl: 300 }) // 5 requests per 5 minutes
  @ZodResponse({
    description: "Public contact form submission",
    type: ActionMessageResponseDto,
  })
  async publicContact(@Body() body: PublicContactRequestDto): Promise<ActionMessageResponse> {
    this.logger.log("Public contact form submission", { emailHash: hashEmailForLogs(body.email) });

    try {
      await this.supportService.createPublicContactRequest(body);

      return {
        message: "Your message has been received. We will get back to you within 24 hours.",
      };
    } catch (error) {
      this.logger.error("Failed to process public contact form", {
        error: error instanceof Error ? error.message : String(error),
        emailHash: hashEmailForLogs(body.email),
      });
      throw error;
    }
  }
}
