import { v4 as uuidv4 } from "uuid";
import bcrypt from "bcryptjs";
import db from "../models/index.js";
import { logAudit } from "../utils/auditLogger.js";
import { sendEmail, renderTemplate } from "../utils/emailService.js";
import { baseEmailLayout } from "../utils/emailTemplates/baseLayout.js";
import PsbService from "../thirdParties/psbService.js";

const { KybApplication, KybDocument, KybDirector, KybHistory, Merchant, sequelize } = db;

class AdminKybController {
  /**
   * Get all KYB applications (with optional status filter)
   * @route GET /admin/kyb
   */
  static async getAllApplications(req, res) {
    try {
      const { status, limit = 50, page = 1 } = req.query;
      const where = {};
      if (status && status !== "All") {
        where.status = status;
      }

      const offset = (Number(page) - 1) * Number(limit);
      const { count, rows } = await KybApplication.findAndCountAll({
        where,
        order: [["createdAt", "DESC"]],
        limit: Number(limit),
        offset,
      });

      return res.status(200).json({
        success: true,
        data: rows,
        pagination: {
          total: count,
          page: Number(page),
          limit: Number(limit),
          totalPages: Math.ceil(count / Number(limit)),
        },
      });
    } catch (error) {
      console.error("❌ getAllApplications error:", error);
      return res.status(500).json({ success: false, message: "Failed to fetch KYB applications", error: error.message });
    }
  }

  /**
   * Get single KYB application details by ID
   * @route GET /admin/kyb/:id
   */
  static async getApplicationById(req, res) {
    try {
      const { id } = req.params;
      const application = await KybApplication.findByPk(id, {
        include: [
          { model: KybDocument, as: "documents" },
          { model: KybDirector, as: "directors" },
          { model: KybHistory, as: "history" },
          { model: Merchant, as: "merchant", attributes: ["id", "businessName", "email", "status", "isLiveMode", "kybStatus"] },
        ],
      });

      if (!application) {
        return res.status(404).json({ success: false, message: "KYB application not found" });
      }

      return res.status(200).json({ success: true, data: application });
    } catch (error) {
      console.error("❌ getApplicationById error:", error);
      return res.status(500).json({ success: false, message: "Failed to fetch KYB application details", error: error.message });
    }
  }

  /**
   * Update KYB application status & promote merchant to Live mode on approval
   * @route PATCH /admin/kyb/:id/status
   */
  static async updateStatus(req, res) {
    const t = await sequelize.transaction();
    try {
      const { id } = req.params;
      const { status, reason, documentIdToReject } = req.body;
      const adminId = req.user?.id || req.admin?.id || "system_admin";

      const validStatuses = [
        "Approved",
        "Rejected",
        "Under Review",
        "Additional Documents Required",
      ];
      if (!validStatuses.includes(status)) {
        await t.rollback();
        return res.status(400).json({ success: false, message: `Invalid status. Must be one of: ${validStatuses.join(", ")}` });
      }

      const application = await KybApplication.findByPk(id, { transaction: t });
      if (!application) {
        await t.rollback();
        return res.status(404).json({ success: false, message: "KYB application not found" });
      }

      const previousStatus = application.status;
      application.status = status;
      if (reason) {
        application.rejectionReason = reason;
      }

      await application.save({ transaction: t });

      // If SuperAdmin approves KYB, promote merchant to Live Mode & issue Live API keys and Live 9PSB bank account number
      if (application.merchantId) {
        const merchant = await Merchant.findByPk(application.merchantId, { transaction: t });
        if (merchant) {
          if (status === "Approved") {
            const rawLiveSecret = `sk_live_${uuidv4().replace(/-/g, '')}`;
            const livePublicKey = `pk_live_${uuidv4().replace(/-/g, '').slice(0, 24)}`;
            const hashedLiveSecret = await bcrypt.hash(rawLiveSecret, 10);

            let liveAccountNumber = merchant.merchantAccountNumber;
            let liveBankName = merchant.bankName;

            // If current account is sandbox (starts with '99') or missing, provision live 9PSB virtual account
            if (!liveAccountNumber || liveAccountNumber.startsWith('99')) {
              try {
                const reference = `MCH-LIVE-${uuidv4().slice(0, 8)}`;
                const psbAccount = await PsbService.createStaticAccount({
                  reference,
                  amount: 0,
                  description: `Live merchant settlement account for ${merchant.businessName}`,
                  name: merchant.businessName,
                });
                if (psbAccount && psbAccount.customer?.account?.number) {
                  liveAccountNumber = psbAccount.customer.account.number;
                  liveBankName = psbAccount.customer.account.bankName || "9PSB";
                }
              } catch (psbErr) {
                console.error("⚠️ Live 9PSB Account creation error during KYB approval:", psbErr.message);
              }
            }

            await merchant.update({
              isLiveMode: true,
              kybStatus: "approved",
              merchantAccountNumber: liveAccountNumber,
              bankName: liveBankName || "9PSB",
              livePublicKey: merchant.livePublicKey || livePublicKey,
              livePrivateKey: merchant.livePrivateKey || hashedLiveSecret,
            }, { transaction: t });
          } else if (status === "Rejected") {
            await merchant.update({ kybStatus: "rejected", isLiveMode: false }, { transaction: t });
          } else if (status === "Under Review") {
            await merchant.update({ kybStatus: "in_review" }, { transaction: t });
          }
        }
      }

      // If rejecting a specific document
      if (status === "Additional Documents Required" && documentIdToReject) {
        const doc = await KybDocument.findOne({ where: { id: documentIdToReject, applicationId: id }, transaction: t });
        if (doc) {
          doc.status = "Rejected";
          doc.rejectionReason = reason;
          await doc.save({ transaction: t });
        }
      }

      await KybHistory.create({
        applicationId: application.id,
        adminId,
        action: `Status Changed to ${status}`,
        previousStatus,
        newStatus: status,
        comment: reason || `Admin marked application as ${status}`,
      }, { transaction: t });

      logAudit({
        userId: adminId,
        userType: "admin",
        action: "KYB_STATUS_UPDATED",
        details: { applicationId: id, newStatus: status, reason },
        req,
      });

      await t.commit();

      // Trigger Email to Merchant based on Status
      let slug = "";
      if (status === "Under Review") {
        slug = "kyb_under_review";
      } else if (status === "Approved") {
        slug = "kyb_approved";
      } else if (status === "Rejected") {
        slug = "kyb_rejected";
      } else if (status === "Additional Documents Required") {
        slug = "kyb_additional_docs";
      }

      if (slug) {
        const emailParams = await renderTemplate(slug, {
          merchantName: application.merchant.businessName,
          reason: reason || "",
        });

        if (emailParams) {
          sendEmail(application.merchant.email, emailParams.subject, emailParams.html).catch(() => {});
        }
      }

      return res.status(200).json({
        success: true,
        message: `Application status updated to ${status}.`,
        data: application,
      });
    } catch (error) {
      await t.rollback();
      console.error("Error updating KYB application status:", error);
      return res.status(500).json({ success: false, message: "Internal server error" });
    }
  }
}

export default AdminKybController;
