import { Controller, Post, Get, Body, Logger } from '@nestjs/common';
import { StrapiService } from './strapi.service';
import { Public } from './auth/public.decorator';

interface WebhookBody {
  event:
    | 'entry.create'
    | 'entry.update'
    | 'entry.delete'
    | 'entry.publish'
    | 'entry.unpublish';
  model: string;
  entry: {
    documentId: string;
  };
}

@Controller('webhooks/strapi')
export class StrapiController {
  private readonly logger = new Logger(StrapiController.name);

  constructor(private readonly strapiService: StrapiService) {}

  @Post('article')
  @Public()
  async handleArticleWebhook(@Body() body: WebhookBody) {
    this.logger.log(`Received article webhook: ${JSON.stringify(body)}`);
    const { event, model, entry } = body;

    if (model !== 'article') {
      this.logger.warn(`Ignored: not an article, model: ${model}`);
      return { message: 'Ignored: not an article' };
    }

    await this.strapiService.handleWebhook(event, {
      documentId: entry.documentId,
      model,
    });
    return { message: 'Webhook processed successfully' };
  }

  @Post('live-blog')
  @Public()
  async handleLiveBlogWebhook(@Body() body: WebhookBody) {
    this.logger.log(`Received live-blog webhook: ${JSON.stringify(body)}`);
    const { event, model, entry } = body;

    if (model !== 'live-blog') {
      this.logger.warn(`Ignored: not a live blog, model: ${model}`);
      return { message: 'Ignored: not a live blog' };
    }

    await this.strapiService.handleWebhook(event, {
      documentId: entry.documentId,
      model,
    });
    return { message: 'Live blog webhook processed successfully' };
  }

  @Post()
  @Public()
  async handleGenericWebhook(@Body() body: unknown) {
    this.logger.log(`Received generic webhook: ${JSON.stringify(body)}`);

    // Type guard to check if body is an object
    if (typeof body !== 'object' || body === null) {
      this.logger.warn(`Invalid webhook payload: ${JSON.stringify(body)}`);
      return { message: 'Invalid payload' };
    }

    const bodyObj = body as Record<string, unknown>;

    // Try to extract event and model from different possible payload structures
    const event = (bodyObj.event || bodyObj.type) as string;
    const model = (bodyObj.model || bodyObj.contentType) as string;
    const entry = bodyObj.entry || bodyObj.data || bodyObj;

    if (!event || !model) {
      this.logger.warn(
        `Cannot process webhook: missing event or model. Payload: ${JSON.stringify(body)}`,
      );
      return { message: 'Cannot process: missing event or model' };
    }

    const entryObj = entry as Record<string, unknown>;
    const documentId = (entryObj.documentId ||
      entryObj.id ||
      (entryObj.document as Record<string, unknown>)?.id) as string;

    if (!documentId) {
      this.logger.warn(
        `Cannot process webhook: missing documentId. Payload: ${JSON.stringify(body)}`,
      );
      return { message: 'Cannot process: missing documentId' };
    }

    // Validate event type
    const validEvents = [
      'entry.create',
      'entry.update',
      'entry.delete',
      'entry.publish',
      'entry.unpublish',
    ];
    if (!validEvents.includes(event)) {
      this.logger.warn(`Invalid event type: ${event}`);
      return { message: 'Invalid event type' };
    }

    await this.strapiService.handleWebhook(
      event as
        | 'entry.create'
        | 'entry.update'
        | 'entry.delete'
        | 'entry.publish'
        | 'entry.unpublish',
      { documentId, model },
    );
    return { message: 'Webhook processed successfully' };
  }

  @Post('sync/all')
  @Public()
  async syncAllArticles() {
    await this.strapiService.syncArticles();
    return { message: 'Articles sync completed' };
  }

  @Get('sync/all')
  @Public()
  async syncAllArticlesGet() {
    await this.strapiService.syncArticles();
    return { message: 'Articles sync completed' };
  }

  @Post('sync/live-blogs')
  @Public()
  async syncAllLiveBlogs() {
    await this.strapiService.syncLiveBlogs();
    return { message: 'Live blogs sync completed' };
  }

  @Post('sync/everything')
  @Public()
  async syncEverything() {
    await Promise.all([
      this.strapiService.syncArticles(),
      this.strapiService.syncLiveBlogs(),
    ]);
    return { message: 'Full sync completed' };
  }
}
