import { Router } from 'express';
import { createHash, randomInt } from 'crypto';
import { z } from 'zod';
import { pool } from '../db/connection.js';
import { requireAuth } from '../middleware/auth.js';
import { encryptText } from '../services/encryption.js';

const router = Router();

const hashCode = (code) => createHash('sha256').update(code).digest('hex');

// Schema for change request validation
const changeRequestSchema = z.object({
  newAddress: z.string().min(10).max(500)
});

// Schema for verification request validation
const verifyRequestSchema = z.object({
  requestId: z.number().int().positive(),
  code: z.string().regex(/^\d{6}$/)
});

router.post('/change-request', requireAuth, async (req, res) => {
  try {
    const parsed = changeRequestSchema.safeParse(req.body);
    if (!parsed.success) {
      return res.status(400).json({ 
        error: 'Invalid input data',
        details: parsed.error.flatten() 
      });
    }

    // Check if user already has an address
    try {
      const [existingRows] = await pool.query(
        `SELECT id FROM addresses WHERE user_id = ? LIMIT 1`,
        [req.user.userId]
      );

      if (existingRows.length === 0) {
        return res.status(400).json({ 
          error: 'User must have an existing address to request a change' 
        });
      }
    } catch (err) {
      console.error('Error checking existing address:', err);
      return res.status(500).json({ 
        error: 'Internal server error while checking existing address' 
      });
    }

    const verificationCode = String(randomInt(100000, 999999));
    const verificationCodeHash = hashCode(verificationCode);

    try {
      const [result] = await pool.query(
        `INSERT INTO address_change_requests (user_id, new_address_encrypted, verification_code_hash)
         VALUES (?, ?, ?)`,
        [req.user.userId, encryptText(parsed.data.newAddress), verificationCodeHash]
      );

      res.status(201).json({
        requestId: result.insertId,
        postalDispatch: 'pending_letter',
        note: 'Verification code generated for postal letter dispatch.',
        verificationCode
      });
    } catch (err) {
      console.error('Error in address change request:', err);
      return res.status(500).json({ 
        error: 'Internal server error while processing address change request' 
      });
    }
  } catch (err) {
    console.error('Unexpected error in change-request route:', err);
    return res.status(500).json({ 
      error: 'Unexpected internal server error' 
    });
  }
});

router.post('/verify', requireAuth, async (req, res) => {
  try {
    const parsed = verifyRequestSchema.safeParse(req.body);
    if (!parsed.success) {
      return res.status(400).json({ 
        error: 'Invalid input data',
        details: parsed.error.flatten() 
      });
    }

    const { requestId, code } = parsed.data;

    try {
      const [rows] = await pool.query(
        `SELECT id, user_id, new_address_encrypted, verification_code_hash, status
         FROM address_change_requests
         WHERE id = ? LIMIT 1`,
        [requestId]
      );

      const request = rows[0];
      if (!request) return res.status(404).json({ error: 'Request not found' });
      if (request.user_id !== req.user.userId) return res.status(403).json({ error: 'Forbidden' });
      if (request.status !== 'pending_letter') return res.status(409).json({ error: 'Request not pending' });

      if (hashCode(code) !== request.verification_code_hash) {
        return res.status(400).json({ error: 'Invalid verification code' });
      }

      const conn = await pool.getConnection();
      try {
        await conn.beginTransaction();

        await conn.query(
          `UPDATE address_change_requests
           SET status = 'verified', verified_at = CURRENT_TIMESTAMP
           WHERE id = ?`,
          [requestId]
        );

        await conn.query(
          `INSERT INTO addresses (user_id, address_encrypted, postal_verified_at)
           VALUES (?, ?, CURRENT_TIMESTAMP)`,
          [req.user.userId, request.new_address_encrypted]
        );

        await conn.commit();
      } catch (err) {
        await conn.rollback();
        console.error('Error in address verification transaction:', err);
        throw err;
      } finally {
        conn.release();
      }

      res.json({ status: 'verified' });
    } catch (err) {
      console.error('Error in address verification:', err);
      return res.status(500).json({ 
        error: 'Internal server error while verifying address' 
      });
    }
  } catch (err) {
    console.error('Unexpected error in verify route:', err);
    return res.status(500).json({ 
      error: 'Unexpected internal server error' 
    });
  }
});

export default router;