// billing.controller.ts

import {
  Body,
  Controller,
  Headers,
  Post,
  Req,
  Get,
  Res,
  Query,
  UseGuards,
  NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { BillingService } from './billing.service';
import { Course } from '../course/course.entity';
import Stripe from 'stripe';
import { ConfigService } from '@nestjs/config';
import express from 'express';

@Controller('billing')
export class BillingController {
  constructor(
    private billing: BillingService,
    private config: ConfigService,
    @InjectRepository(Course) private courseRepo: Repository<Course>,
  ) { }

  // One-time charge
  @UseGuards(JwtAuthGuard)
  @Post('checkout')
  async checkout(@Body() body: { courseId: number }, @Req() req) {
    const course = await this.courseRepo.findOne({
      where: { id: body.courseId },
    });
    if (!course) throw new Error('Course not found');
    return this.billing.createOneTimeCheckout(req.user.id, course, {
      allowPromotionCodes: true,
      automaticTax: false,
    });
  }

  // Webhook (needs RAW body)
  // @Post('webhook')
  // async webhook(@Req() req: RawBodyRequest<Request>, @Headers('stripe-signature') signature: string) {
  //   console.log('Stripe Webhook received');
  //   // Verify signature and parse event
  //   // Note: in a real app, you should store the stripe instance somewhere else (not as "any" in another service)
  //   const stripe = (this.billing as any).stripe as Stripe;
  //   console.log('Stripe Webhook received 1');
  //   const secret = this.config.get<string>('STRIPE_WEBHOOK_SECRET')!;
  //   console.log(secret);
  //   let event: Stripe.Event;

  //   try {
  //     // @ts-ignore rawBody provided in main.ts
  //     event = stripe.webhooks.constructEvent(req.rawBody, signature, secret);
  //     console.log('✅ Verified event:', event.type);
  //     console.log(event);
  //   } catch (err) {
  //     console.error('❌ Verification failed:', err.message);
  //     return { received: err };
  //   }

  //   switch (event.type) {
  //     case 'checkout.session.completed':
  //       await this.billing.activateEnrollmentFromCheckout(event.data.object as Stripe.Checkout.Session);
  //       break;
  //     // handle refunds/cancellations if you need
  //   }
  //   return { received: true };
  // }
  @Post('webhook')
  async webhook(
    @Req() req: any,
    @Headers('stripe-signature') signature: string,
  ) {
    const stripe = (this.billing as any).stripe as Stripe;
    const secret = this.config.get<string>('STRIPE_WEBHOOK_SECRET')!;
    let event: Stripe.Event;

    try {
      // 👉 if req.rawBody is missing, use Buffer.from(req.body)
      const body = req.rawBody ?? Buffer.from(req.body);
      event = stripe.webhooks.constructEvent(body, signature, secret);
      console.log('✅ Verified event:', event.type);
    } catch (err: any) {
      console.error('❌ Verification failed:', err.message);
      return { received: err.message };
    }

    if (event.type === 'checkout.session.completed') {
      const session = event.data.object as Stripe.Checkout.Session;
      await this.billing.activateEnrollmentFromCheckout(session);
    }

    return { received: true };
  }
  @Get('success')
  async success(
    @Query('session_id') sessionId: string,
    @Res() res: express.Response,
  ) {
    const baseUrl = process.env.APP_BASE_URL_FRONT;
    if (!baseUrl) {
      throw new NotFoundException(
        'NEXT_PUBLIC_APP_BASE_URL_FRONT is not defined',
      );
    }
    const enroll = await this.billing.confirmCheckoutSession(sessionId);

    if (!enroll) {
      throw new NotFoundException(
        'Enrollment not found or payment not completed',
      );
    }

    return res.redirect(
      `${baseUrl}/billing/success?session_id=${sessionId}&course_id=${enroll.course.id}`,
    );
  }
  @Get('cancel')
  cancel() {
    // optional: return something simple for the UI
    return { status: 'cancelled' };
  }
}
