const dbConnect = require('../configs/dbConnection.js');
const { sendOtp, verifyOtp } = require('../../smsapi/model/smsModel');
const { verifyCaptcha } = require('../utils/verifyCaptcha.js');
const bcrypt = require('bcryptjs');
const { sendSignupEmail } = require('../../emailapi/model/mailModel');
// ✅ Same crypto utils used in signupController — handles AES encrypt + HMAC hash
const { encrypt, hashMobile, hashEmail } = require('./cryptoUtil');

// ─────────────────────────────────────────────────────────────────────────────
// CONSTANTS
// ─────────────────────────────────────────────────────────────────────────────

const LEGAL_ENTITY_TYPES = [
  'Proprietorship', 'Partnership', 'LLP',
  'Private Limited Company', 'Public Limited Company',
  'OPC', 'Trust', 'Society', 'Individual',
];

const ENTITY_MANDATORY_DOCS = {
  'Proprietorship':          ['panCardUrl', 'businessProofUrl'],
  'Partnership':             ['panCardUrl', 'partnershipDeedUrl'],
  'LLP':                     ['panCardUrl', 'incorporationCertificateUrl'],
  'Private Limited Company': ['panCardUrl', 'incorporationCertificateUrl'],
  'Public Limited Company':  ['panCardUrl', 'incorporationCertificateUrl'],
  'OPC':                     ['panCardUrl', 'incorporationCertificateUrl'],
  'Trust':                   ['panCardUrl', 'businessProofUrl'],
  'Society':                 ['panCardUrl', 'businessProofUrl'],
  'Individual':              ['panCardUrl'],
};

// ─────────────────────────────────────────────────────────────────────────────
// HELPERS
// ─────────────────────────────────────────────────────────────────────────────

function isValidPan(pan) {
  return /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(pan);
}

function isValidGst(gst) {
  return /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/.test(gst);
}

async function trySendMail(email, user, mobile, userId, type) {
  try {
    await sendSignupEmail(email, user, mobile, userId, type);
  } catch (err) {
    console.error(`Mail error (${type}):`, err);
  }
}

function validateMandatoryDocs(legalEntityType, isGstRegistered, docs) {
  const required = [...(ENTITY_MANDATORY_DOCS[legalEntityType] || ['panCardUrl'])];
  if (isGstRegistered) required.push('gstCertificateUrl');
  const missing = required.filter(field => !docs[field]);
  return { required, missing };
}

// ─────────────────────────────────────────────────────────────────────────────
// STEP 1 — CheckUser → POST /agent/form
// Validates full form + sends OTP. No DB insert here.
// ─────────────────────────────────────────────────────────────────────────────

exports.CheckUser = async (req, res) => {
  try {
    const {
      user, email, mobile, password, captchaToken,
      businessName, proprietorshipName, tradeName,
      legalName, legalEntityType,
      businessAddress, businessCity, businessState,
      businessPinCode, businessCountry,
      repName, repDesignation, repMobile, repEmail,
      isGstRegistered, gstNumber,
      panNumber, udyamNumber,
      panCardUrl, gstCertificateUrl, incorporationCertificateUrl,
      partnershipDeedUrl, businessProofUrl, letterHeadUrl,
      addressProofUrl, cancelledChequeUrl, representativeIdProofUrl,
      legalNameDocumentUrl, udyamCertificateUrl,
    } = req.body;

    console.log('CheckUser payload:', user, email, mobile, legalEntityType);

    // ── Personal validation ───────────────────────────────────────────────────
    const missingPersonal = [];
    if (!user)     missingPersonal.push('user');
    if (!email)    missingPersonal.push('email');
    if (!mobile)   missingPersonal.push('mobile');
    if (!password) missingPersonal.push('password');
    if (missingPersonal.length > 0) {
      await trySendMail(email, user, mobile, null, 'error');
      return res.status(400).json({ error: `Missing personal fields: ${missingPersonal.join(', ')}` });
    }

    // ── Business validation ───────────────────────────────────────────────────
    const missingBusiness = [];
    if (!businessName)    missingBusiness.push('businessName');
    if (!legalName)       missingBusiness.push('legalName');
    if (!legalEntityType) missingBusiness.push('legalEntityType');
    if (!businessAddress) missingBusiness.push('businessAddress');
    if (!businessCity)    missingBusiness.push('businessCity');
    if (!businessState)   missingBusiness.push('businessState');
    if (!businessPinCode) missingBusiness.push('businessPinCode');
    if (!repName)         missingBusiness.push('repName');
    if (!repDesignation)  missingBusiness.push('repDesignation');
    if (!repMobile)       missingBusiness.push('repMobile');
    if (!repEmail)        missingBusiness.push('repEmail');
    if (!panNumber)       missingBusiness.push('panNumber');
    if (missingBusiness.length > 0) {
      return res.status(400).json({ error: `Missing business fields: ${missingBusiness.join(', ')}` });
    }

    if (!LEGAL_ENTITY_TYPES.includes(legalEntityType)) {
      return res.status(400).json({ error: `Invalid legalEntityType. Allowed: ${LEGAL_ENTITY_TYPES.join(', ')}` });
    }

    if (!isValidPan(panNumber.toUpperCase())) {
      return res.status(400).json({ error: 'Invalid PAN format. Example: ABCDE1234F' });
    }

    if (isGstRegistered && !gstNumber) {
      return res.status(400).json({ error: 'gstNumber is required when isGstRegistered is true' });
    }
    if (isGstRegistered && gstNumber && !isValidGst(gstNumber.toUpperCase())) {
      return res.status(400).json({ error: 'Invalid GST number format' });
    }

    const docUrls = {
      panCardUrl, gstCertificateUrl, incorporationCertificateUrl,
      partnershipDeedUrl, businessProofUrl, letterHeadUrl,
      addressProofUrl, cancelledChequeUrl, representativeIdProofUrl,
      legalNameDocumentUrl, udyamCertificateUrl,
    };
    const { required, missing: missingDocs } = validateMandatoryDocs(legalEntityType, isGstRegistered, docUrls);
    if (missingDocs.length > 0) {
      return res.status(400).json({
        error: `Missing mandatory document URLs for ${legalEntityType}: ${missingDocs.join(', ')}`,
        mandatoryDocuments: required,
      });
    }

    // ── Captcha (uncomment when live) ─────────────────────────────────────────
    // const captchaResponse = await verifyCaptcha(captchaToken);
    // if (!captchaResponse.success) {
    //   return res.status(400).json({ error: 'Captcha verification failed' });
    // }

    // ── Duplicate check via HASH columns ─────────────────────────────────────
    // hashMobile/hashEmail normalize internally before hashing,
    // exactly the same way registerUser does — so lookup always matches.
    const mobileHash = hashMobile(mobile.toString());
    const emailHash  = hashEmail(email.toString());

    const [existingRows] = await dbConnect.query(
      `SELECT uid FROM alogin WHERE umob_hash = ? OR umail_hash = ?`,
      [mobileHash, emailHash]
    );
    if (existingRows.length > 0) {
      await trySendMail(email, user, mobile, null, 'exists');
      return res.status(409).json({ error: 'Mobile or email already registered' });
    }

    // ── Send OTP ──────────────────────────────────────────────────────────────
    const formattedMobile = '+91' + String(mobile).replace(/\D/g, '').replace(/^0|^91/, '');
    const sendSmsResponse = await sendOtp(formattedMobile, 'BOBROSOTP');
    if (!sendSmsResponse) {
      return res.status(500).json({ error: 'Failed to send OTP' });
    }

    return res.status(200).json({
      msg: 'OTP sent successfully. Please verify to complete registration.',
      sendSmsResponse,
      mandatoryDocuments: required,
    });

  } catch (error) {
    console.error('Error in CheckUser:', error);
    return res.status(500).json({ error: error.message });
  }
};

console.log('🚨 registerUser loaded:', new Date().toISOString());

// ─────────────────────────────────────────────────────────────────────────────
// STEP 2 — registerUser → POST /agent/register
// OTP verify → encrypt/hash → INSERT alogin + agentSignUpDocument + agent_services
// ─────────────────────────────────────────────────────────────────────────────

exports.registerUser = async (req, res) => {
  try {
    const {
      user, email, mobile, password, otp,
      businessName, proprietorshipName, tradeName,
      legalName, legalEntityType,
      businessAddress, businessCity, businessState,
      businessPinCode, businessCountry,
      repName, repDesignation, repMobile, repEmail,
      isGstRegistered, gstNumber,
      panNumber, udyamNumber,
      panCardUrl, gstCertificateUrl, incorporationCertificateUrl,
      partnershipDeedUrl, businessProofUrl, letterHeadUrl,
      addressProofUrl, cancelledChequeUrl, representativeIdProofUrl,
      legalNameDocumentUrl, udyamCertificateUrl,
    } = req.body;

    console.log('registerUser payload:', user, email, mobile, legalEntityType);

    // ── Field validation ──────────────────────────────────────────────────────
    if (!user || !email || !mobile || !password || !otp) {
      return res.status(400).json({ error: 'All personal fields + otp are required.' });
    }
    if (!businessName || !legalName || !legalEntityType || !businessAddress ||
        !businessCity || !businessState || !businessPinCode ||
        !repName || !repDesignation || !repMobile || !repEmail || !panNumber) {
      return res.status(400).json({ error: 'All business details are required.' });
    }

    // ── Mandatory doc validation ──────────────────────────────────────────────
    const docUrls = {
      panCardUrl, gstCertificateUrl, incorporationCertificateUrl,
      partnershipDeedUrl, businessProofUrl, letterHeadUrl,
      addressProofUrl, cancelledChequeUrl, representativeIdProofUrl,
      legalNameDocumentUrl, udyamCertificateUrl,
    };
    const { missing: missingDocs, required } = validateMandatoryDocs(legalEntityType, isGstRegistered, docUrls);
    if (missingDocs.length > 0) {
      return res.status(400).json({
        error: `Missing mandatory document URLs for ${legalEntityType}: ${missingDocs.join(', ')}`,
        mandatoryDocuments: required,
      });
    }

    // ── OTP verify ────────────────────────────────────────────────────────────
    const isOtpValid = await verifyOtp(mobile, otp);
    if (!isOtpValid || isOtpValid.Details === 'OTP Mismatch') {
      return res.status(400).json({ error: 'OTP verification failed' });
    }

    // ── Encrypt + Hash mobile & email (mirrors signupController exactly) ──────
    //
    //  encrypt(value)     → AES-256-CBC → { data: hexString, iv: hexString }
    //                       data is stored in umob / umail columns
    //                       iv   is stored in umob_iv / umail_iv columns
    //
    //  hashMobile(value)  → HMAC-SHA256 of normalized mobile (last 10 digits)
    //                       stored in umob_hash — used for fast duplicate lookup
    //                       also used as uuser (login identifier)
    //
    //  hashEmail(value)   → HMAC-SHA256 of lowercased+trimmed email
    //                       stored in umail_hash — used for fast duplicate lookup
    //
    const mobileStr = mobile.toString();
    const emailStr  = email.toString();

    const mobileHash      = hashMobile(mobileStr);  // HMAC hash
    const emailHash       = hashEmail(emailStr);     // HMAC hash
    const encryptedMobile = encrypt(mobileStr);      // { data, iv }
    const encryptedEmail  = encrypt(emailStr);       // { data, iv }

    console.log('HASH_SALT check:', process.env.HASH_SALT ? 'SET ✅' : 'MISSING ❌');
    console.log('ENCRYPT_KEY check:', process.env.ENCRYPT_KEY ? 'SET ✅' : 'MISSING ❌');

    // bcrypt hash of password (same as signupController — 10 rounds)
    const hashedPassword = await bcrypt.hash(password, 10);

    // ── Transaction ───────────────────────────────────────────────────────────
    const conn = await dbConnect.getConnection();
    try {
      await conn.beginTransaction();

      // ── 1. INSERT into alogin ─────────────────────────────────────────────
      //
      //  Column mapping (what goes where and why):
      //
      //  uuser       = mobileHash         ← login identifier (same as ulogin)
      //  upass       = hashedPassword      ← bcrypt hash
      //  umob        = encryptedMobile.data← AES encrypted mobile (NOT raw)
      //  uname       = user                ← plain name, no PII risk
      //  umail       = encryptedEmail.data ← AES encrypted email (NOT raw)
      //  umob_hash   = mobileHash          ← for duplicate check & lookup
      //  umob_iv     = encryptedMobile.iv  ← needed to AES-decrypt umob later
      //  umail_iv    = encryptedEmail.iv   ← needed to AES-decrypt umail later
      //  umail_hash  = emailHash           ← for duplicate check & lookup
      //
      const [aloginResult] = await conn.query(
        `INSERT INTO alogin (
          uuser,        upass,    umob,   uname,
          ubal,         ucred,    umail,  uadd,
          ucity,        ustate,   upin,   ucrate,
          did,          uflag,    ustatus, onboardingStatus,
          businessName, proprietorshipName, tradeName, legalName,
          legalEntityType, businessAddress, businessCity, businessState,
          businessPinCode, businessCountry,
          repName, repDesignation, repMobile, repEmail,
          isGstRegistered, gstNumber,
          panNumber, udyamNumber,
          pwdchangedate,
          umob_hash, umob_iv, umail_iv, umail_hash
        ) VALUES (
          ?,  ?,  ?,  ?,
          0,  0,  ?,  'Nil',
          'Nil', 'Nil', 'Nil', 0,
          'Admin', 'Inactive', 'PENDING_KYC', 'Pending Review',
          ?,  ?,  ?,  ?,
          ?,  ?,  ?,  ?,
          ?,  ?,
          ?,  ?,  ?,  ?,
          ?,  ?,
          ?,  ?,
          NOW(),
          ?,  ?,  ?,  ?
        )`,
        [
          // ── Row 1: uuser, upass, umob (encrypted!), uname
          mobileHash,           hashedPassword,
          encryptedMobile.data, user,

          // ── umail (encrypted!)
          encryptedEmail.data,

          // ── Business fields
          businessName,         proprietorshipName || null,
          tradeName    || null, legalName,
          legalEntityType,      businessAddress,
          businessCity,         businessState,
          businessPinCode,      businessCountry || 'India',

          // ── Rep fields
          repName, repDesignation, repMobile, repEmail,

          // ── GST
          isGstRegistered ? 1 : 0, gstNumber || null,

          // ── PAN + Udyam
          panNumber.toUpperCase(), udyamNumber || null,

          // ── Crypto columns (THE FIX — these were being skipped before)
          mobileHash,           encryptedMobile.iv,
          encryptedEmail.iv,    emailHash,
        ]
      );

      const newUserId = aloginResult.insertId;

      // ── 2. INSERT into agentSignUpDocument ────────────────────────────────
      await conn.query(
        `INSERT INTO agentSignUpDocument (
          onboardingId, temporaryRegistrationId,
          legalNameDocumentUrl, panCardUrl, gstCertificateUrl,
          incorporationCertificateUrl, partnershipDeedUrl, udyamCertificateUrl,
          businessProofUrl, letterHeadUrl, addressProofUrl,
          cancelledChequeUrl, representativeIdProofUrl,
          verificationStatus, uploadedAt
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'Pending', NOW())`,
        [
          newUserId,                      newUserId,
          legalNameDocumentUrl     || null, panCardUrl            || null,
          gstCertificateUrl        || null, incorporationCertificateUrl || null,
          partnershipDeedUrl       || null, udyamCertificateUrl   || null,
          businessProofUrl         || null, letterHeadUrl         || null,
          addressProofUrl          || null, cancelledChequeUrl    || null,
          representativeIdProofUrl || null,
        ]
      );

      // ── 3. agent_services default row ─────────────────────────────────────
      await conn.query(
        `INSERT INTO agent_services (uid) VALUES (?)`,
        [newUserId]
      );

      await conn.commit();
      console.log('New agent registered (PENDING_KYC):', newUserId);
      await trySendMail(email, user, mobile, newUserId, 'success');

      return res.status(201).json({
        msg: 'Registration successful. Your application is under admin review.',
        userId: newUserId,
        status: 'PENDING_KYC',
        mandatoryDocuments: required,
      });

    } catch (txErr) {
      await conn.rollback();
      throw txErr;
    } finally {
      conn.release();
    }

  } catch (error) {
    console.error('Error in registerUser:', error);
    if (error.code === 'ER_DUP_ENTRY') {
      await trySendMail(req.body.email, req.body.user, req.body.mobile, null, 'exists');
      return res.status(409).json({ error: 'Mobile or email already registered' });
    }
    await trySendMail(req.body.email, req.body.user, req.body.mobile, null, 'error');
    return res.status(500).json({ error: error.message });
  }
};