import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { prisma } from '@/server/db/client';
import { authOptions } from '@/server/auth/config';
import { WhatsAppService } from '@/server/services/notifications/whatsapp.service';
import { EmailService } from '@/server/services/notifications/email.service';
import { addMonths } from 'date-fns';
import { generateTransactionId } from '@/server/services/billing/invoice.service';
import { disconnectPPPoEUser } from '@/server/services/radius/coa-handler.service';
import { sendPushToUser } from '@/server/services/notifications/push-templates.service';
import { nowWIB } from '@/lib/timezone';

function formatBankAccountsWA(bankAccounts: any): string {
  if (!bankAccounts) return '';
  let accounts: Array<{ bankName?: string; bank?: string; accountNumber?: string; accountName?: string }> = [];
  try {
    accounts = Array.isArray(bankAccounts) ? bankAccounts : JSON.parse(String(bankAccounts));
  } catch { return ''; }
  if (!accounts.length) return '';
  const lines = accounts.map(a =>
    `🏦 ${a.bankName || a.bank || '-'}\n   📋 No. Rek: ${a.accountNumber || '-'}\n   👤 A/N: ${a.accountName || '-'}`
  );
  return `━━━━━━━━━━━━━━━━━━━━━━\n🏦 *Transfer Manual ke Rekening:*\n${lines.join('\n\n')}`;
}

function formatBankAccountsHtml(bankAccounts: any): string {
  if (!bankAccounts) return '';
  let accounts: Array<{ bankName?: string; bank?: string; accountNumber?: string; accountName?: string }> = [];
  try {
    accounts = Array.isArray(bankAccounts) ? bankAccounts : JSON.parse(String(bankAccounts));
  } catch { return ''; }
  if (!accounts.length) return '';
  const rows = accounts.map(a =>
    `<tr><td style="padding:8px;border:1px solid #bae6fd;">${a.bankName || a.bank || '-'}</td><td style="padding:8px;border:1px solid #bae6fd;">${a.accountNumber || '-'}</td><td style="padding:8px;border:1px solid #bae6fd;">${a.accountName || '-'}</td></tr>`
  ).join('');
  return `<div style="margin:20px 0;"><p style="font-weight:bold;">💳 Informasi Rekening Pembayaran:</p><table style="width:100%;border-collapse:collapse;background:#f0f9ff;"><thead><tr><th style="padding:8px;border:1px solid #bae6fd;background:#e0f2fe;">Bank</th><th style="padding:8px;border:1px solid #bae6fd;background:#e0f2fe;">No. Rekening</th><th style="padding:8px;border:1px solid #bae6fd;background:#e0f2fe;">Atas Nama</th></tr></thead><tbody>${rows}</tbody></table></div>`;
}

// GET - Get single manual payment
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params;
    const manualPayment = await prisma.manualPayment.findUnique({
      where: { id },
      include: {
        invoice: true,
        user: {
          include: {
            profile: true,
            area: true,
          },
        },
      },
    });
    
    if (!manualPayment) {
      return NextResponse.json(
        { success: false, error: 'Manual payment not found' },
        { status: 404 }
      );
    }
    
    return NextResponse.json({
      success: true,
      data: manualPayment,
    });
  } catch (error) {
    console.error('Get manual payment error:', error);
    return NextResponse.json(
      { success: false, error: 'Failed to fetch manual payment' },
      { status: 500 }
    );
  }
}

// PATCH - Approve or reject manual payment
export async function PATCH(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const body = await request.json();
    const { action, rejectionReason } = body;

    const session = await getServerSession(authOptions);
    if (!session?.user) {
      return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 });
    }
    const role = (session.user as any)?.role;
    const allowedRoles = ['SUPER_ADMIN', 'FINANCE', 'CUSTOMER_SERVICE'];
    if (!role || !allowedRoles.includes(role)) {
      return NextResponse.json({ success: false, error: 'Forbidden' }, { status: 403 });
    }
    const approvedBy = (session.user as any)?.name || session.user.email || 'Admin';

    if (!action || (action !== 'APPROVE' && action !== 'REJECT')) {
      return NextResponse.json(
        { success: false, error: 'Invalid action' },
        { status: 400 }
      );
    }
    
    if (action === 'REJECT' && !rejectionReason) {
      return NextResponse.json(
        { success: false, error: 'Rejection reason is required' },
        { status: 400 }
      );
    }
    
    const manualPayment = await prisma.manualPayment.findUnique({
      where: { id: params.id },
      include: {
        invoice: true,
        user: {
          include: {
            profile: true,
            area: true,
          },
        },
      },
    });
    
    if (!manualPayment) {
      return NextResponse.json(
        { success: false, error: 'Manual payment not found' },
        { status: 404 }
      );
    }
    
    if (manualPayment.status !== 'PENDING') {
      return NextResponse.json(
        { success: false, error: 'Manual payment already processed' },
        { status: 400 }
      );
    }
    
    if (action === 'APPROVE') {
      // Approve payment
      const company = await prisma.company.findFirst();

      // Compute expiry before transaction (reads)
      const currentExpiry = manualPayment.user.expiredAt || new Date();
      const validityValue = manualPayment.user.profile.validityValue;
      const validityUnit = manualPayment.user.profile.validityUnit;

      let newExpiry = new Date(currentExpiry);

      switch (validityUnit) {
        case 'MONTHS':
          newExpiry = addMonths(newExpiry, validityValue);
          break;
        case 'DAYS':
          newExpiry.setDate(newExpiry.getDate() + validityValue);
          break;
        case 'HOURS':
          newExpiry.setHours(newExpiry.getHours() + validityValue);
          break;
        case 'MINUTES':
          newExpiry.setMinutes(newExpiry.getMinutes() + validityValue);
          break;
      }

      // ============================================
      // CHECK FOR PACKAGE CHANGE IN INVOICE METADATA
      // ============================================
      let newProfileId = manualPayment.user.profileId;
      let newProfileData = manualPayment.user.profile;
      let isPackageChange = false;
      if (manualPayment.invoice && manualPayment.invoice.additionalFees) {
        try {
          const fees = manualPayment.invoice.additionalFees as any;
          if (fees.items && Array.isArray(fees.items)) {
            const pkgItem = fees.items.find((item: any) =>
              (item.metadata?.type === 'package_change' || item.metadata?.type === 'package_upgrade') &&
              item.metadata?.newPackageId
            );
            if (pkgItem) {
              isPackageChange = true;
              newProfileId = pkgItem.metadata.newPackageId;
              const foundProfile = await prisma.pppoeProfile.findUnique({ where: { id: newProfileId } });
              if (foundProfile) {
                newProfileData = foundProfile as any;
                console.log(`[Manual Payment APPROVE] Package change: ${pkgItem.metadata.oldPackageName} → ${pkgItem.metadata.newPackageName} (expiry PRESERVED)`);
              }
            }
          }
        } catch (e) {
          console.error('[Manual Payment APPROVE] Failed to parse additionalFees:', e);
        }
      }

      // For package change: preserve existing expiredAt, do NOT extend
      const finalExpiry = isPackageChange ? currentExpiry : newExpiry;
      const paymentId = await generateTransactionId();
      const approvedAt = new Date();

      // Atomic transaction: all related records written together
      await prisma.$transaction(async (tx) => {
        await tx.manualPayment.update({
          where: { id: params.id },
          data: {
            status: 'APPROVED',
            approvedBy,
            approvedAt,
          },
        });

        await tx.invoice.update({
          where: { id: manualPayment.invoiceId },
          data: {
            status: 'PAID',
            paidAt: approvedAt,
          },
        });

        await tx.pppoeUser.update({
          where: { id: manualPayment.userId },
          data: {
            expiredAt: finalExpiry,
            status: 'active',
            lastPaymentDate: approvedAt,
            ...(newProfileId !== manualPayment.user.profileId && { profileId: newProfileId }),
          },
        });

        await tx.payment.create({
          data: {
            id: paymentId,
            invoiceId: manualPayment.invoiceId,
            amount: manualPayment.invoice.amount,
            method: 'manual_transfer',
            status: 'success',
            paidAt: approvedAt,
          },
        });
      });

      // ============================================
      // SYNC RADIUS - Update group + CoA disconnect
      // ============================================
      try {
        const activeProfile = newProfileData;
        if (activeProfile && 'groupName' in activeProfile) {
          // Update password in radcheck
          await prisma.$executeRaw`
            INSERT INTO radcheck (username, attribute, op, value)
            VALUES (${manualPayment.user.username}, 'Cleartext-Password', ':=', ${manualPayment.user.password})
            ON DUPLICATE KEY UPDATE value = ${manualPayment.user.password}
          `;
          // Update radusergroup to new profile
          await prisma.$executeRaw`
            DELETE FROM radusergroup WHERE username = ${manualPayment.user.username}
          `;
          await prisma.$executeRaw`
            INSERT INTO radusergroup (username, groupname, priority)
            VALUES (${manualPayment.user.username}, ${(activeProfile as any).groupName}, 1)
          `;
          // Remove isolation entries
          await prisma.radcheck.deleteMany({
            where: { username: manualPayment.user.username, attribute: 'Auth-Type' }
          });
          await prisma.radreply.deleteMany({
            where: { username: manualPayment.user.username, attribute: 'Reply-Message' }
          });
          // CoA disconnect to force re-auth
          const coaResult = await disconnectPPPoEUser(manualPayment.user.username);
          console.log(`[Manual Payment APPROVE] CoA: ${coaResult.success ? 'disconnected for re-auth' : coaResult.error}`);
        }
      } catch (radiusErr) {
        console.error('[Manual Payment APPROVE] RADIUS sync error:', radiusErr);
      }

      // ============================================
      // FCM PUSH NOTIFICATION TO CUSTOMER
      // ============================================
      try {
        await sendPushToUser(manualPayment.userId, 'payment-success', {
          customerName: manualPayment.user.name,
          username: manualPayment.user.username,
          invoiceNumber: manualPayment.invoice.invoiceNumber,
          amount: manualPayment.invoice.amount,
          profileName: (newProfileData as any)?.name || '',
          expiredDate: finalExpiry,
          companyName: company?.name || '',
          companyPhone: company?.phone || '',
        });
      } catch (pushErr) {
        console.error('[Manual Payment APPROVE] FCM push error:', pushErr);
      }
      
      // Send notifications
      const customerName = manualPayment.user.name;
      const invoiceNumber = manualPayment.invoice.invoiceNumber;
      const amount = new Intl.NumberFormat('id-ID', {
        style: 'currency',
        currency: 'IDR',
        minimumFractionDigits: 0,
      }).format(manualPayment.invoice.amount);
      
      // WhatsApp notification
      const whatsappTemplate = await prisma.whatsapp_templates.findFirst({
        where: { type: 'manual-payment-approval' },
      });
      
      if (whatsappTemplate && whatsappTemplate.isActive) {
        let message = whatsappTemplate.message
          .replace(/{{customerName}}/g, customerName)
          .replace(/{{customerUsername}}/g, manualPayment.user.username)
          .replace(/{{customerId}}/g, (manualPayment.user as any)?.customerId || '-')
          .replace(/{{invoiceNumber}}/g, invoiceNumber)
          .replace(/{{amount}}/g, amount)
          .replace(/{{expiredDate}}/g, newExpiry.toLocaleDateString('id-ID'))
          .replace(/{{profileName}}/g, (manualPayment.user as any)?.profile?.name || '-')
          .replace(/{{area}}/g, (manualPayment.user as any)?.area?.name || '-')
          .replace(/{{companyName}}/g, company?.name || '')
          .replace(/{{companyPhone}}/g, company?.phone || '')
          .replace(/{{bankAccounts}}/g, formatBankAccountsWA(company?.bankAccounts));
        
        try {
          await WhatsAppService.sendMessage({ phone: manualPayment.user.phone, message });
        } catch (error) {
          console.error('Failed to send WhatsApp notification:', error);
        }
      }
      
      // Email notification
      if (manualPayment.user.email) {
        const emailTemplate = await prisma.emailTemplate.findFirst({
          where: { type: 'manual-payment-approval' },
        });
        
        if (emailTemplate && emailTemplate.isActive) {
          const variables = {
            customerName,
            customerId: (manualPayment.user as any)?.customerId || '-',
            customerUsername: manualPayment.user.username,
            invoiceNumber,
            amount,
            expiredDate: newExpiry.toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric', timeZone: 'Asia/Jakarta' }),
            profileName: (manualPayment.user as any)?.profile?.name || '-',
            area: (manualPayment.user as any)?.area?.name || '-',
            companyName: company?.name || '',
            companyPhone: company?.phone || '',
            companyEmail: company?.email || '',
            baseUrl: company?.baseUrl || '',
            bankAccounts: formatBankAccountsHtml(company?.bankAccounts),
          };
          
          try {
            let emailBody = emailTemplate.htmlBody;
            for (const [key, value] of Object.entries(variables)) {
              emailBody = emailBody.replace(new RegExp(`{{${key}}}`, 'g'), String(value));
            }
            
            await EmailService.send({
              to: manualPayment.user.email,
              toName: customerName,
              subject: emailTemplate.subject,
              html: emailBody,
            });
          } catch (error) {
            console.error('Failed to send email notification:', error);
          }
        }
      }
      
      // Create notification
      const pkgChangeMsg = newProfileId !== manualPayment.user.profileId
        ? ` | Paket diubah ke ${(newProfileData as any)?.name || newProfileId}`
        : '';
      await prisma.notification.create({
        data: {
          type: 'manual_payment_approved',
          title: 'Pembayaran Disetujui',
          message: `Pembayaran manual untuk ${customerName} (${invoiceNumber}) telah disetujui${pkgChangeMsg}`,
          link: `/admin/manual-payments`,
          createdAt: nowWIB(),
        },
      });
      
      return NextResponse.json({
        success: true,
        message: 'Manual payment approved successfully',
        packageChanged: newProfileId !== manualPayment.user.profileId,
        newProfileId: newProfileId !== manualPayment.user.profileId ? newProfileId : undefined,
      });
    } else {
      // Reject payment
      const company = await prisma.company.findFirst();
      
      await prisma.manualPayment.update({
        where: { id: params.id },
        data: {
          status: 'REJECTED',
          rejectionReason,
          approvedBy,
          approvedAt: new Date(),
        },
      });
      
      // Send rejection notifications
      const customerName = manualPayment.user.name;
      const invoiceNumber = manualPayment.invoice.invoiceNumber;
      const amount = new Intl.NumberFormat('id-ID', {
        style: 'currency',
        currency: 'IDR',
        minimumFractionDigits: 0,
      }).format(manualPayment.invoice.amount);
      
      // WhatsApp notification
      const whatsappTemplate = await prisma.whatsapp_templates.findFirst({
        where: { type: 'manual-payment-rejection' },
      });
      
      if (whatsappTemplate && whatsappTemplate.isActive) {
        let message = whatsappTemplate.message
          .replace(/{{customerName}}/g, customerName)
          .replace(/{{customerUsername}}/g, manualPayment.user.username)
          .replace(/{{customerId}}/g, (manualPayment.user as any)?.customerId || '-')
          .replace(/{{invoiceNumber}}/g, invoiceNumber)
          .replace(/{{amount}}/g, amount)
          .replace(/{{rejectionReason}}/g, rejectionReason)
          .replace(/{{paymentLink}}/g, `${company?.baseUrl}/pay-manual?token=${manualPayment.invoice.paymentToken}`)
          .replace(/{{profileName}}/g, (manualPayment.user as any)?.profile?.name || '-')
          .replace(/{{area}}/g, (manualPayment.user as any)?.area?.name || '-')
          .replace(/{{companyName}}/g, company?.name || '')
          .replace(/{{companyPhone}}/g, company?.phone || '')
          .replace(/{{bankAccounts}}/g, formatBankAccountsWA(company?.bankAccounts));
        
        try {
          await WhatsAppService.sendMessage({ phone: manualPayment.user.phone, message });
        } catch (error) {
          console.error('Failed to send WhatsApp notification:', error);
        }
      }
      
      // Email notification
      if (manualPayment.user.email) {
        const emailTemplate = await prisma.emailTemplate.findFirst({
          where: { type: 'manual-payment-rejection' },
        });
        
        if (emailTemplate && emailTemplate.isActive) {
          const variables = {
            customerName,
            customerId: (manualPayment.user as any)?.customerId || '-',
            customerUsername: manualPayment.user.username,
            invoiceNumber,
            amount,
            rejectionReason,
            paymentLink: `${company?.baseUrl}/pay-manual?token=${manualPayment.invoice.paymentToken}`,
            profileName: (manualPayment.user as any)?.profile?.name || '-',
            area: (manualPayment.user as any)?.area?.name || '-',
            companyName: company?.name || '',
            companyPhone: company?.phone || '',
            companyEmail: company?.email || '',
            baseUrl: company?.baseUrl || '',
            bankAccounts: formatBankAccountsHtml(company?.bankAccounts),
          };
          
          try {
            let emailBody = emailTemplate.htmlBody;
            for (const [key, value] of Object.entries(variables)) {
              emailBody = emailBody.replace(new RegExp(`{{${key}}}`, 'g'), String(value));
            }
            
            await EmailService.send({
              to: manualPayment.user.email,
              toName: customerName,
              subject: emailTemplate.subject,
              html: emailBody,
            });
          } catch (error) {
            console.error('Failed to send email notification:', error);
          }
        }
      }
      
      // Create notification
      await prisma.notification.create({
        data: {
          type: 'manual_payment_rejected',
          title: 'Pembayaran Ditolak',
          message: `Pembayaran manual untuk ${customerName} (${invoiceNumber}) ditolak: ${rejectionReason}`,
          link: `/admin/manual-payments`,
          createdAt: nowWIB(),
        },
      });

      // ============================================
      // FCM PUSH NOTIFICATION TO CUSTOMER (REJECT)
      // ============================================
      try {
        await sendPushToUser(manualPayment.userId, 'payment-rejected', {
          customerName: manualPayment.user.name,
          invoiceNumber: manualPayment.invoice.invoiceNumber,
          amount: manualPayment.invoice.amount,
          customBody: rejectionReason,
          companyName: company?.name || '',
          companyPhone: company?.phone || '',
        });
      } catch (pushErr) {
        console.error('[Manual Payment REJECT] FCM push error:', pushErr);
      }

      return NextResponse.json({
        success: true,
        message: 'Manual payment rejected',
      });
    }
  } catch (error) {
    console.error('Process manual payment error:', error);
    return NextResponse.json(
      { success: false, error: 'Failed to process manual payment' },
      { status: 500 }
    );
  }
}

// DELETE - Delete manual payment (admin only)
export async function DELETE(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const session = await getServerSession(authOptions);
    if (!session?.user) {
      return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 });
    }
    const deleteRole = (session.user as any)?.role;
    if (!deleteRole || !['SUPER_ADMIN', 'FINANCE'].includes(deleteRole)) {
      return NextResponse.json({ success: false, error: 'Forbidden' }, { status: 403 });
    }

    await prisma.manualPayment.delete({
      where: { id: params.id },
    });
    
    return NextResponse.json({
      success: true,
      message: 'Manual payment deleted successfully',
    });
  } catch (error) {
    console.error('Delete manual payment error:', error);
    return NextResponse.json(
      { success: false, error: 'Failed to delete manual payment' },
      { status: 500 }
    );
  }
}
