import {
  Injectable,
  BadRequestException,
  NotFoundException,
} from '@nestjs/common';
import { DataSource, EntityManager } from 'typeorm';
import { CouponService } from '../coupons/coupon.service';
import * as crypto from 'crypto';
import PDFDocument = require('pdfkit');
import * as fs from 'fs';
import * as path from 'path';
import * as sharp from 'sharp';

@Injectable()
export class PaymentsService {
  constructor(
    private dataSource: DataSource,
    private couponService: CouponService,
  ) {}

  async createOrder(userId: number, body: any) {
    // 1. Manual Validation
    if (
      !body.entityType ||
      !['plan', 'job_package'].includes(body.entityType)
    ) {
      throw new BadRequestException('Invalid entityType');
    }
    if (!body.entityId) {
      throw new BadRequestException('entityId is required');
    }

    const { entityType, entityId, couponCode, userInfo } = body;

    // 2. Fetch Entity & Calculate Price
    let originalPrice = 0;
    let productInfo = '';

    if (entityType === 'plan') {
      // Check by ID or Code
      const query = isNaN(Number(entityId))
        ? 'SELECT * FROM plans WHERE code = ?'
        : 'SELECT * FROM plans WHERE id = ?';
      const [plan] = await this.dataSource.query(query, [entityId]);

      if (!plan || !plan.is_active)
        throw new BadRequestException('Plan not found or inactive');
      originalPrice = Number(plan.price);
      productInfo = `Plan: ${plan.name}`;
    } else {
      // Check by ID or Code
      const query = isNaN(Number(entityId))
        ? 'SELECT * FROM job_packages WHERE code = ?'
        : 'SELECT * FROM job_packages WHERE id = ?';
      const [pkg] = await this.dataSource.query(query, [entityId]);

      if (!pkg || !pkg.is_active)
        throw new BadRequestException('Package not found or inactive');
      originalPrice = Number(pkg.price);
      productInfo = `Package: ${pkg.name}`;
    }

    // 3. Apply Coupon
    let finalAmount = originalPrice;
    let discount = 0;
    let couponId = null;

    if (couponCode) {
      const coupon = await this.couponService.validateCoupon(
        couponCode,
        userId,
        originalPrice,
      );
      discount = this.couponService.calculateDiscount(coupon, originalPrice);
      finalAmount = originalPrice - discount;
      couponId = coupon.id;
    }

    if (finalAmount < 0) finalAmount = 0;

    // --- GST Calculation ---
    // Fetch GST from config_setting
    const [gstSetting] = await this.dataSource.query(
      `SELECT setting_value FROM config_setting WHERE setting_key = 'gst_percentage'`,
    );

    const baseAmount = finalAmount;
    const gstPercentage = gstSetting
      ? parseFloat(gstSetting.setting_value)
      : 18.0;
    const gstAmount = Number((baseAmount * (gstPercentage / 100)).toFixed(2));
    const totalAmount = Number((baseAmount + gstAmount).toFixed(2));

    // 4. Intent Recognition (Non-Negotiable Payment Intent Law)
    // Identity of intent = receipt. Deterministic ID for intent reuse.
    const receiptId = `JBV_U${userId}_T${entityType}_ID${entityId}`;

    // Check if a payment with this intent (receipt) already exists
    const [existingIntent] = await this.dataSource.query(
      `SELECT id, status FROM payments WHERE user_id = ? AND receipt = ?`,
      [userId, receiptId],
    );

    if (existingIntent && existingIntent.status === 'success') {
      throw new BadRequestException(
        'This purchase has already been successfully fulfilled.',
      );
    }

    // 5. Prepare PayU Details
    const key = process.env.PAYU_KEY || 'test_key';
    const salt = process.env.PAYU_SALT || 'test_salt_v1';

    // Retries must reuse the same intent but can have fresh txn ID for the gateway attempt
    const txnid = `txn_${Date.now()}_${userId}`;
    const amount = totalAmount.toFixed(2); // Send Total Amount (Base + GST) to PayU
    const firstname = userInfo?.firstName || 'User';
    const email = userInfo?.email || 'user@example.com';
    const phone = userInfo?.phone || '9999999999';
    const surl = `${process.env.BASE_API_URL || 'https://jobvumi.com/api'}/payments/success`;
    const furl = `${process.env.BASE_API_URL || 'https://jobvumi.com/api'}/payments/failure`;

    // UDF Mappings for Context
    const udf1 = entityType; // Type of purchase
    const udf2 = String(entityId); // ID of the plan/package
    const udf3 = couponId ? String(couponId) : ''; // Coupon ID if any
    const udf4 = ''; // Reserved
    const udf5 = ''; // Reserved

    // 6. Generate Hash
    // Formula: sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||salt)
    const hashString = `${key}|${txnid}|${amount}|${productInfo}|${firstname}|${email}|${udf1}|${udf2}|${udf3}|${udf4}|${udf5}||||||${salt}`;
    const hash = crypto.createHash('sha512').update(hashString).digest('hex');

    // 7. Intent-based Persistence (State Transition Law)
    if (existingIntent) {
      // Update existing intent (Reusing the same row)
      await this.dataSource.query(
        `UPDATE payments 
                 SET gateway_order_id = ?, status = 'initiated', base_amount = ?, gst_percentage = ?, gst_amount = ?, total_amount = ?, raw_request = ?, created_at = NOW()
                 WHERE id = ?`,
        [
          txnid,
          baseAmount,
          gstPercentage,
          gstAmount,
          totalAmount,
          JSON.stringify({
            key,
            txnid,
            amount,
            productInfo,
            firstname,
            email,
            phone,
            udf1,
            udf2,
            udf3,
          }),
          existingIntent.id,
        ],
      );
    } else {
      // Insert new intent
      await this.dataSource.query(
        `INSERT INTO payments 
                (user_id, base_amount, gst_percentage, gst_amount, total_amount, gateway, gateway_order_id, receipt, status, raw_request, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
        [
          userId,
          baseAmount,
          gstPercentage,
          gstAmount,
          totalAmount,
          'payu',
          txnid, // Storing txnId as gateway_order_id
          receiptId, // Custom JBV receipt
          'initiated',
          JSON.stringify({
            key,
            txnid,
            amount,
            productInfo,
            firstname,
            email,
            phone,
            udf1,
            udf2,
            udf3,
          }),
        ],
      );
    }

    // 8. Return Form Parameters
    return {
      action: process.env.PAYU_PAYMENT_URL,
      key,
      txnid,
      amount,
      productinfo: productInfo,
      firstname,
      email,
      phone,
      surl,
      furl,
      hash,
      udf1,
      udf2,
      udf3,
      udf4,
      udf5,
      receipt: receiptId,
    };
  }

  /**
   * GENERATE OFFLINE INVOICE (For Manual/Custom Plans)
   */
  async createOfflineInvoice(
    userId: number,
    amount: number,
    description: string,
    gstRate = 18,
    manager?: EntityManager,
  ): Promise<number> {
    const execute = async (em: EntityManager) => {
      // Check User Exists
      const [user] = await em.query(`SELECT id FROM users WHERE id = ?`, [
        userId,
      ]);
      if (!user) {
        throw new NotFoundException('User not found');
      }

      // Fetch Default Issuer
      const [issuer] = await em.query(
        `SELECT id, invoice_prefix FROM invoice_issuers WHERE is_default = 1 LIMIT 1`,
      );
      const prefix = issuer?.invoice_prefix || 'JV';
      const issuerId = issuer?.id || null;

      // GST Calc
      const baseAmount = amount;
      const gstAmount = Number((baseAmount * (gstRate / 100)).toFixed(2));
      const totalAmount = Number((baseAmount + gstAmount).toFixed(2));

      const receiptId = `OFF-${Date.now()}-${userId}`;
      // Use Issuer Prefix
      const txnid = `${prefix}-${Date.now()}`;

      // Create Payment Record (Already PAID)
      const result = await em.query(
        `INSERT INTO payments 
              (user_id, invoice_issuer_id, base_amount, gst_percentage, gst_amount, total_amount, gateway, gateway_order_id, receipt, status, raw_request, created_at)
              VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
        [
          userId,
          issuerId, // Store the issuer ID
          baseAmount,
          gstRate,
          gstAmount,
          totalAmount,
          'offline', // Gateway
          txnid, // Order ID with Prefix
          receiptId, // Receipt
          'success', // Status (Already Paid)
          JSON.stringify({
            productInfo: description,
            note: 'Generated via Admin Manual Adjustment',
          }),
        ],
      );

      return result.insertId;
    };

    if (manager) {
      return await execute(manager);
    } else {
      return await this.dataSource.transaction(execute);
    }
  }

  async getInvoices(
    userId: number,
    limit = 20,
    offset = 0,
    startDate?: string,
    endDate?: string,
    status?: string,
  ) {
    let query = `SELECT 
                p.id, 
                p.gateway_order_id as invoiceNo, 
                p.created_at as date, 
                JSON_UNQUOTE(JSON_EXTRACT(p.raw_request, '$.udf1')) as type,
                p.base_amount as baseAmount,
                p.gst_amount as gstAmount,
                p.total_amount as totalAmount,
                p.status
            FROM payments p 
            WHERE p.user_id = ? AND p.status != 'initiated'`;

    const params: any[] = [userId];

    if (startDate) {
      query += ` AND p.created_at >= ?`;
      params.push(startDate);
    }

    if (endDate) {
      query += ` AND p.created_at <= ?`;
      params.push(endDate);
    }

    if (status && status !== 'all') {
      if (status === 'unpaid') {
        query += ` AND p.status IN ('initiated', 'processing')`;
      } else {
        query += ` AND p.status = ?`;
        params.push(status);
      }
    }

    query += ` ORDER BY p.created_at DESC LIMIT ? OFFSET ?`;
    params.push(limit, offset);

    return await this.dataSource.query(query, params);
  }

  async generateInvoicePdf(
    paymentId: number,
  ): Promise<{ buffer: Buffer; filename: string }> {
    const [payment] = await this.dataSource.query(
      `SELECT * FROM payments WHERE id = ?`,
      [paymentId],
    );

    if (!payment) {
      throw new BadRequestException('Invoice not found');
    }

    const rawRequest =
      typeof payment.raw_request === 'string'
        ? JSON.parse(payment.raw_request)
        : payment.raw_request;

    // --- FETCH DYNAMIC COMPANY DATA ---

    // 1. Supplier (Invoice Issuer) - With Bank Details
    let issuerQuery = `
            SELECT ii.*, s.state_name, c.city_name,
                   iba.account_name, iba.bank_name, iba.branch, iba.account_number, iba.ifsc_code, iba.swift_code
            FROM invoice_issuers ii 
            LEFT JOIN state s ON ii.state_id = s.state_id 
            LEFT JOIN city c ON ii.city_id = c.city_id
            LEFT JOIN issuer_bank_accounts iba ON ii.id = iba.invoice_issuer_id AND iba.is_default = 1
            WHERE ii.is_default = 1 
            LIMIT 1
        `;

    if (payment.invoice_issuer_id) {
      issuerQuery = `
                SELECT ii.*, s.state_name, c.city_name,
                       iba.account_name, iba.bank_name, iba.branch, iba.account_number, iba.ifsc_code, iba.swift_code
                FROM invoice_issuers ii 
                LEFT JOIN state s ON ii.state_id = s.state_id 
                LEFT JOIN city c ON ii.city_id = c.city_id
                LEFT JOIN issuer_bank_accounts iba ON ii.id = iba.invoice_issuer_id AND iba.is_default = 1
                WHERE ii.id = ?
                LIMIT 1
            `;
    }

    const [supplier] = await this.dataSource.query(
      issuerQuery,
      payment.invoice_issuer_id ? [payment.invoice_issuer_id] : [],
    );

    // 2. Recipient (Recruiter's Company or User)
    const [recipient] = await this.dataSource.query(
      `SELECT 
                c.*, 
                s.state_name,
                s.gst_code as state_gst_code,
                cit.city_name,
                u.email as user_email,
                u.phone as user_phone
             FROM users u
             LEFT JOIN companies c ON c.user_id = u.id
             LEFT JOIN state s ON c.state_id = s.state_id 
             LEFT JOIN city cit ON c.city_id = cit.city_id
             WHERE u.id = ?
             ORDER BY c.created_at DESC 
             LIMIT 1`,
      [payment.user_id],
    );

    // A4 Size: 595.28 x 841.89
    const doc = new PDFDocument({ margin: 20, size: 'A4' });
    const buffers: Buffer[] = [];

    doc.on('data', buffers.push.bind(buffers));

    return new Promise(async (resolve, reject) => {
      doc.on('end', () => {
        const pdfData = Buffer.concat(buffers);
        const prefix = supplier?.invoice_prefix || 'INV';
        const date = new Date(payment.created_at);
        const dateStr = date
          .toISOString()
          .replace(/[-T:\.Z]/g, '')
          .slice(0, 14);
        const safeFilename = `${prefix}-${dateStr}.pdf`;
        resolve({ buffer: pdfData, filename: safeFilename });
      });

      doc.on('error', reject);

      // --- STYLING CONSTANTS ---
      const baseFont = 'Helvetica';
      const boldFont = 'Helvetica-Bold';
      const margin = 20;
      const pageWidth = 595.28;
      const contentWidth = pageWidth - 2 * margin;
      // Grid Lines
      const drawLine = (x1, y1, x2, y2) =>
        doc.moveTo(x1, y1).lineTo(x2, y2).stroke();

      // 1. MAIN BORDER
      const mainRectHeight = 780; // Adjust as needed
      doc.rect(margin, margin, contentWidth, mainRectHeight).stroke();

      let currentY = margin;

      // 2. HEADER: TAX INVOICE
      doc
        .font(boldFont)
        .fontSize(14)
        .text('TAX INVOICE', margin, currentY + 8, {
          width: contentWidth,
          align: 'center',
        });
      currentY += 30;
      drawLine(margin, currentY, pageWidth - margin, currentY);

      // 3. SELLER & INVOICE META (Split)
      const splitX = 350;
      const row2Height = 110;
      const row2Bottom = currentY + row2Height;

      // Left: Logo & Seller Details
      const leftPad = margin + 5;
      const textY = currentY + 5;

      if (supplier?.logo_url) {
        try {
          const logoPath = path.isAbsolute(supplier.logo_url)
            ? supplier.logo_url
            : path.join(process.cwd(), supplier.logo_url);

          if (fs.existsSync(logoPath)) {
            const logoBuffer = await sharp(logoPath).png().toBuffer();
            doc.image(logoBuffer, leftPad, textY, { width: 60 });
          }
        } catch (e) {
          console.error('Logo error', e);
        }
      }

      const sellerTextX = leftPad + 70; // Offset for logo
      let sellerY = currentY + 5;

      doc
        .font(boldFont)
        .fontSize(10)
        .text(
          supplier?.company_name || 'JOBVUMI Pvt. Ltd.',
          sellerTextX,
          sellerY,
        );
      sellerY += 12;
      doc
        .font(baseFont)
        .fontSize(9)
        .text(
          supplier?.registered_address || 'Address Line 1, City',
          sellerTextX,
          sellerY,
          { width: 250 },
        );
      // Approximate height for address
      const addrHeight = doc.heightOfString(
        supplier?.registered_address || '',
        { width: 250 },
      );
      sellerY += addrHeight + 5;

      doc.text(`GSTIN: ${supplier?.gstin || '-'}`, sellerTextX, sellerY);
      sellerY += 12;
      doc.text(
        `City: ${supplier?.city_name || 'Bengaluru'}`,
        sellerTextX,
        sellerY,
      );
      sellerY += 12;
      doc.text(`State: ${supplier?.state_name || '-'}`, sellerTextX, sellerY);
      sellerY += 12;
      if (supplier?.msme_no) {
        doc.text(`MSME No: ${supplier.msme_no}`, sellerTextX, sellerY);
        sellerY += 12;
      }

      // Right: Invoice Meta
      const rightPad = splitX + 5;
      let metaY = currentY + 5;
      const invoiceNo = payment.gateway_order_id || `INV-${payment.id}`;
      const invDate = new Date(payment.created_at).toLocaleDateString('en-GB', {
        day: '2-digit',
        month: 'short',
        year: 'numeric',
      });

      doc.font(boldFont).text('Invoice No:', rightPad, metaY);
      doc.font(baseFont).text(invoiceNo, rightPad + 60, metaY);
      metaY += 15;

      doc.font(boldFont).text('Dated:', rightPad, metaY);
      doc.font(baseFont).text(invDate, rightPad + 60, metaY);
      metaY += 25;

      let paymentStatusDisplay = 'Unpaid';
      if (payment.status === 'success') {
        paymentStatusDisplay = 'Paid';
      } else if (payment.status === 'failed') {
        paymentStatusDisplay = 'Transaction Failed';
      }

      doc.font(boldFont).text('Mode/Terms of Payment:', rightPad, metaY);
      doc.font(baseFont).text(paymentStatusDisplay, rightPad + 130, metaY);

      // Divider Line Vertical
      drawLine(splitX, currentY, splitX, row2Bottom);
      // Divider Line Horizontal (Bottom of Row 2)
      drawLine(margin, row2Bottom, pageWidth - margin, row2Bottom);

      currentY = row2Bottom;

      // 4. BUYER SECTION
      const row3Height = 100;
      const row3Bottom = currentY + row3Height;

      // Left: Buyer Details
      let buyerY = currentY + 5;
      doc.font(boldFont).text('Buyer (Bill to):', leftPad, buyerY);
      buyerY += 12;

      const buyerName =
        recipient?.company_name ||
        recipient?.name ||
        rawRequest?.firstname ||
        'Valued Customer';
      // Construct Address: Location, City, State, Pincode
      const loc = recipient?.location ? recipient.location + ', ' : '';
      const city = recipient?.city_name ? recipient.city_name + ', ' : '';
      const state = recipient?.state_name ? recipient.state_name + ', ' : '';
      const pin = recipient?.pincode || '';

      let buyerAddr = (loc + city + state + pin).trim();
      if (buyerAddr.endsWith(',')) buyerAddr = buyerAddr.slice(0, -1);

      if (!buyerAddr) buyerAddr = rawRequest?.address || 'Address Not Provided';

      const buyerGstin = recipient?.gst_number || rawRequest?.gstin || '-';
      let buyerPan = recipient?.pan || rawRequest?.pan || '-';
      if (!buyerPan || buyerPan === 'null' || buyerPan === 'undefined')
        buyerPan = '-';
      const showPan = buyerPan !== '-' && buyerPan.trim() !== '';

      doc.font(baseFont).text(buyerName, leftPad, buyerY);
      buyerY += 12;
      doc.text(buyerAddr, leftPad, buyerY, { width: 300 });
      const buyerAddrH = doc.heightOfString(buyerAddr, { width: 300 });
      buyerY += buyerAddrH + 5;

      doc.font(boldFont).text('GSTIN:', leftPad, buyerY);
      doc.font(baseFont).text(buyerGstin, leftPad + 40, buyerY);
      buyerY += 12;

      if (showPan) {
        doc.font(boldFont).text('PAN:', leftPad, buyerY);
        doc.font(baseFont).text(buyerPan, leftPad + 40, buyerY);
        buyerY += 12;
      }

      const posState = recipient?.state_name || '-';
      const posCode = recipient?.state_gst_code
        ? `(${recipient.state_gst_code})`
        : '';

      doc.font(boldFont).text('Place of Supply:', leftPad, buyerY);
      doc.font(baseFont).text(`${posState} ${posCode}`, leftPad + 85, buyerY);

      // Right: Terms of Delivery
      let deliveryY = currentY + 5;
      doc.font(boldFont).text('Terms of Delivery:', rightPad, deliveryY);
      deliveryY += 12;
      doc.font(baseFont).text('—', rightPad, deliveryY);

      // Lines
      drawLine(splitX, currentY, splitX, row3Bottom);
      drawLine(margin, row3Bottom, pageWidth - margin, row3Bottom);

      currentY = row3Bottom;

      // 5. ITEMS TABLE
      // Columns: Sl No(30), Particulars(250), SAC(50), Qty(30), Rate(80), Amount(115)
      // X Coords:
      const col1 = margin;
      const col2 = col1 + 30; // 50
      const col3 = col2 + 250; // 300
      const col4 = col3 + 60; // 350
      const col5 = col4 + 40; // 400
      const col6 = col5 + 80; // 480
      // End is 595 - 20 = 575

      // Header Row
      const headerH = 20;
      const headerTextY = currentY + 6;

      doc.font(boldFont).fontSize(9);
      doc.text('Sl No.', col1, headerTextY, { width: 30, align: 'center' });
      doc.text('Particulars', col2 + 5, headerTextY, {
        width: 240,
        align: 'left',
      });
      doc.text('SAC', col3, headerTextY, { width: 60, align: 'center' });
      doc.text('Qty', col4, headerTextY, { width: 40, align: 'center' });
      doc.text('Rate', col5, headerTextY, { width: 80, align: 'right' });
      doc.text('Amount(INR)', col6, headerTextY, { width: 95, align: 'right' });

      drawLine(
        margin,
        currentY + headerH,
        pageWidth - margin,
        currentY + headerH,
      );

      currentY += headerH;

      // Content Left Vertical Lines (we draw them at the end of section to match height)

      // Item Row
      const itemY = currentY + 10;
      const desc = rawRequest?.productInfo || 'Recruitment Services';
      const sac = '998519'; // Fixed SAC Code
      const qty = '1';
      const rate = Number(payment.base_amount).toFixed(2);
      const amount = Number(payment.base_amount).toFixed(2);

      doc.font(baseFont).fontSize(9);
      doc.text('1', col1, itemY, { width: 30, align: 'center' });
      doc.text(desc, col2 + 5, itemY, { width: 240 });
      doc.text(sac, col3, itemY, { width: 60, align: 'center' });
      doc.text(qty, col4, itemY, { width: 40, align: 'center' });
      doc.text(rate, col5, itemY, { width: 80, align: 'right' });
      doc.text(amount, col6, itemY, { width: 95, align: 'right' });

      let loopY = itemY + 20; // Move down

      // Determine IGST or CGST/SGST based on state
      // Logic: if recipient state != supplier state => IGST, else CGST+SGST
      const isInterState = supplier?.state_id !== recipient?.state_id;

      doc.font(baseFont);
      if (payment.gst_amount > 0) {
        if (isInterState) {
          doc.text('IGST Output', col2 + 5, loopY, {
            align: 'right',
            width: 240 + 60 + 40 + 80,
          }); // Span till Rate col
          doc.text(Number(payment.gst_amount).toFixed(2), col6, loopY, {
            width: 95,
            align: 'right',
          });
          loopY += 15;
        } else {
          const halfTax = Number(payment.gst_amount) / 2;
          doc.text('CGST Output', col2 + 5, loopY, {
            align: 'right',
            width: 240 + 60 + 40 + 80,
          });
          doc.text(halfTax.toFixed(2), col6, loopY, {
            width: 95,
            align: 'right',
          });
          loopY += 15;
          doc.text('SGST Output', col2 + 5, loopY, {
            align: 'right',
            width: 240 + 60 + 40 + 80,
          });
          doc.text(halfTax.toFixed(2), col6, loopY, {
            width: 95,
            align: 'right',
          });
          loopY += 15;
        }
      }

      // Total Row
      doc.font(boldFont);
      doc.text('Total', col2 + 5, loopY, {
        align: 'right',
        width: 240 + 60 + 40 + 80,
      });
      doc.text(Number(payment.total_amount).toFixed(2), col6, loopY, {
        width: 95,
        align: 'right',
      });
      loopY += 20;

      const itemsBottom = loopY;
      drawLine(margin, itemsBottom, pageWidth - margin, itemsBottom);

      // Vertical Lines for Items Table
      // (Only drawing them from header bottom to items bottom)
      const vStart = row3Bottom;
      const vEnd = itemsBottom;
      drawLine(col2, vStart, col2, vEnd);
      drawLine(col3, vStart, col3, vEnd);
      drawLine(col4, vStart, col4, vEnd);
      drawLine(col5, vStart, col5, vEnd);
      drawLine(col6, vStart, col6, vEnd);

      currentY = itemsBottom;

      // 6. TAX SUMMARY
      // Header
      const summaryH = 20;
      const sY = currentY + 6;

      // Custom Columns for Summary
      const sc1 = margin;
      const sc2 = sc1 + 60; // SAC
      const sc3 = sc2 + 100; // Value
      const sc4 = sc3 + 100; // Central
      const sc5 = sc4 + 100; // State

      doc.font(boldFont).fontSize(9);
      doc.text('SAC', sc1, sY, { width: 60, align: 'center' });
      doc.text('Taxable Value', sc2, sY, { width: 100, align: 'right' });
      doc.text('Central Tax', sc3, sY, { width: 100, align: 'center' });
      doc.text('State Tax', sc4, sY, { width: 100, align: 'center' });
      doc.text('Integrated Tax', sc5, sY, { width: 100, align: 'center' });

      drawLine(
        margin,
        currentY + summaryH,
        pageWidth - margin,
        currentY + summaryH,
      );
      currentY += summaryH;

      // Data
      const rowH = 20;
      const rY = currentY + 6;

      doc.font(baseFont);
      doc.text(sac, sc1, rY, { width: 60, align: 'center' });
      doc.text(Number(payment.base_amount).toFixed(2), sc2, rY, {
        width: 100,
        align: 'right',
      });

      if (isInterState) {
        // IGST Only
        doc.text('0%', sc3, rY, { width: 50, align: 'right' });
        doc.text('0', sc3 + 50, rY, { width: 50, align: 'right' });
        doc.text('0%', sc4, rY, { width: 50, align: 'right' });
        doc.text('0', sc4 + 50, rY, { width: 50, align: 'right' });
        doc.text(`${payment.gst_percentage}%`, sc5, rY, {
          width: 50,
          align: 'right',
        });
        doc.text(Number(payment.gst_amount).toFixed(2), sc5 + 50, rY, {
          width: 50,
          align: 'right',
        });
      } else {
        // CGST + SGST
        const halfRate = Number(payment.gst_percentage) / 2;
        const halfTax = Number(payment.gst_amount) / 2;

        doc.text(`${halfRate}%`, sc3, rY, { width: 50, align: 'right' });
        doc.text(halfTax.toFixed(2), sc3 + 50, rY, {
          width: 50,
          align: 'right',
        });
        doc.text(`${halfRate}%`, sc4, rY, { width: 50, align: 'right' });
        doc.text(halfTax.toFixed(2), sc4 + 50, rY, {
          width: 50,
          align: 'right',
        });
        doc.text('0%', sc5, rY, { width: 50, align: 'right' });
        doc.text('0', sc5 + 50, rY, { width: 50, align: 'right' });
      }

      currentY += rowH;
      drawLine(margin, currentY, pageWidth - margin, currentY);

      // 7. FOOTER SECTION
      const footerTop = currentY;
      const footerSplitX = 350; // Match header split

      // Left: Declarations
      let footerLeftY = footerTop + 10;
      doc
        .font(boldFont)
        .text(`Company's PAN: ${supplier?.pan || '-'}`, leftPad, footerLeftY);
      footerLeftY += 12;
      doc.text(`Company's CIN: ${supplier?.cin || '-'}`, leftPad, footerLeftY);
      footerLeftY += 20;

      doc.text('Declaration', leftPad, footerLeftY);
      footerLeftY += 12;
      doc
        .font(baseFont)
        .text(
          supplier?.declaration_text ||
            'We declare that this invoice shows the actual price of the goods/services described and that all particulars are true and correct.',
          leftPad,
          footerLeftY,
          { width: 300 },
        );

      // Right: Bank Details
      let footerRightY = footerTop + 10;
      const footerRightPad = footerSplitX + 10;
      doc
        .font(boldFont)
        .text("Company's Bank Details", footerRightPad, footerRightY);
      footerRightY += 15;

      doc.font(baseFont);
      doc.text(
        `Name: ${supplier?.account_name || supplier?.company_name || '-'}`,
        footerRightPad,
        footerRightY,
      );
      footerRightY += 12;
      doc.text(
        `Bank: ${supplier?.bank_name || '-'}`,
        footerRightPad,
        footerRightY,
      );
      footerRightY += 12;
      doc.text(
        `Branch: ${supplier?.branch || '-'}`,
        footerRightPad,
        footerRightY,
      );
      footerRightY += 12;
      doc.text(
        `A/c No: ${supplier?.account_number || '-'}`,
        footerRightPad,
        footerRightY,
      );
      footerRightY += 12;
      doc.text(
        `IFSC: ${supplier?.ifsc_code || '-'}`,
        footerRightPad,
        footerRightY,
      );
      footerRightY += 12;
      doc.text(
        `SWIFT: ${supplier?.swift_code || '-'}`,
        footerRightPad,
        footerRightY,
      );

      // 8. JURISDICTION & SIGNATORY
      const signY = footerTop + 120;
      const boxBottom = signY + 50;

      // Horizontal Line separating Bank Details from Signatory
      drawLine(margin, signY - 10, pageWidth - margin, signY - 10);

      // Vertical Line separating Left/Right (extends through both sections)
      drawLine(footerSplitX, footerTop, footerSplitX, boxBottom);

      const jurisCity = supplier?.city_name || 'Bengaluru';
      doc
        .font(baseFont)
        .fontSize(9)
        .text(
          `All disputes subject to ${supplier?.jurisdiction_text} jurisdiction only.` ||
            `All disputes subject to ${jurisCity} jurisdiction only.`,
          leftPad,
          signY,
        );

      doc
        .font(boldFont)
        .text(
          supplier?.company_name || 'JOBVUMI Pvt. Ltd.',
          footerRightPad,
          signY,
        );
      doc.text('Authorised Signatory', footerRightPad, signY + 30);

      // Final Bottom Line
      drawLine(margin, boxBottom, pageWidth - margin, boxBottom);

      // Computer generated note
      doc
        .font(baseFont)
        .fontSize(8)
        .text(
          supplier?.footer_note ||
            'This is a computer-generated invoice and does not require signature',
          margin,
          boxBottom + 10,
          { width: contentWidth, align: 'center' },
        );

      doc.end();
    });
  }
}
