import {
  BadRequestException,
  Body,
  Controller,
  Post,
  Res,
} from '@nestjs/common';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import type { Response } from 'express';
import { ConfigService } from '@nestjs/config';
import { EasebuzzService } from './easebuzz.service';
import { WalletService } from './wallet.service';

@ApiTags('easebuzz')
@Controller('easebuzz')
export class EasebuzzController {
  constructor(
    private readonly easebuzz: EasebuzzService,
    private readonly wallet: WalletService,
    private readonly config: ConfigService,
  ) {}

  @Post('return')
  @ApiOkResponse({ description: 'Easebuzz payment return (surl/furl)' })
  async handleReturn(@Body() body: any, @Res() res: Response) {
    const payload = body && typeof body === 'object' ? body : {};
    const attemptId = (payload.udf1 ?? '').toString();
    const status = (payload.status ?? '').toString().toLowerCase();
    const hintPurpose = (payload.udf5 ?? '').toString().trim().toUpperCase();

    const okHash = this.easebuzz.verifyResponseHash(payload);
    if (!okHash) {
      throw new BadRequestException('Invalid payment signature');
    }
    if (!attemptId) throw new BadRequestException('Missing attempt');

    const allowOrigins = (() => {
      const originsRaw = (process.env.CORS_ORIGINS ?? '').toString();
      const list = originsRaw
        .split(',')
        .map((s) => s.trim())
        .filter(Boolean);
      const cfgBase = (this.config.get<string>('payments.publicUrl') ?? '')
        .toString()
        .trim();
      if (cfgBase) list.push(cfgBase);
      return Array.from(new Set(list));
    })();

    const isAllowedBase = (base: string) => {
      try {
        const u = new URL(base);
        if (!(u.protocol === 'http:' || u.protocol === 'https:')) return false;
        // In development, when CORS_ORIGINS is empty, we allow returning to the
        // portal origin provided via udf6 to avoid cross-origin logout issues.
        const nodeEnv = (process.env.NODE_ENV ?? '').toString().toLowerCase();
        const allowAllDev = allowOrigins.length === 0 && nodeEnv !== 'production';
        if (allowAllDev) return true;
        const origin = u.origin;
        return allowOrigins.some((o) => {
          try {
            return new URL(o).origin === origin;
          } catch {
            return false;
          }
        });
      } catch {
        return false;
      }
    };

    const configuredBase = (
      this.config.get<string>('payments.publicUrl') ?? ''
    )
      .toString()
      .trim()
      .replace(/\/+$/, '');

    const storedPortalHint =
      (await this.wallet.getPaymentAttemptPortalOrigin(attemptId)) || '';
    const publicBase = (
      storedPortalHint && isAllowedBase(storedPortalHint)
        ? storedPortalHint
        : configuredBase
    ).replace(/\/+$/, '');

    const to = (pathWithQuery: string) =>
      publicBase ? `${publicBase}${pathWithQuery}` : pathWithQuery;

    try {
      if (status === 'success') {
        if (hintPurpose === 'WALLET_TOPUP') {
          await this.wallet.applyWalletTopupOnSuccess({
            attemptId,
            easebuzzPayload: payload,
          });
          return res.redirect(to(`/wallet?payment=success`));
        }

        await this.wallet.applyPlanPurchaseOnSuccess({
          attemptId,
          easebuzzPayload: payload,
        });
        return res.redirect(to(`/dashboard?payment=success`));
      }
      return res.redirect(
        hintPurpose === 'WALLET_TOPUP'
          ? to(`/wallet?payment=failed`)
          : to(`/dashboard?payment=failed`),
      );
    } catch {
      return res.redirect(
        hintPurpose === 'WALLET_TOPUP'
          ? to(`/wallet?payment=failed`)
          : to(`/dashboard?payment=failed`),
      );
    }
  }
}
