const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const { supabase } = require('../config/supabase');

/**
 * Middleware to verify JWT token
 */
function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No token provided' });
  }

  try {
    const token = authHeader.split(' ')[1];
    req.user = jwt.verify(token, process.env.JWT_SECRET);
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

// Apply auth middleware to all routes
router.use(authMiddleware);

/**
 * Generate invitation token
 * Format: ABC-123-XYZ (easy to type, 9 chars)
 */
function generateInviteToken() {
  const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // no I, O, 0, 1 to avoid confusion
  let token = '';
  for (let i = 0; i < 9; i++) {
    if (i === 3 || i === 6) token += '-';
    token += chars[crypto.randomInt(chars.length)];
  }
  return token;
}

/**
 * POST /api/invitations
 * Creates an invitation for someone to access a beneficiary
 */
router.post('/', async (req, res) => {
  try {
    const userId = req.user.userId;
    const { beneficiaryId, role, email } = req.body;

    if (!beneficiaryId || !role) {
      return res.status(400).json({ error: 'beneficiaryId and role are required' });
    }

    if (!['caretaker', 'owner', 'installer'].includes(role)) {
      return res.status(400).json({ error: 'Invalid role. Must be: caretaker, owner, or installer' });
    }

    // Check user has owner access to beneficiary
    const { data: access, error: accessError } = await supabase
      .from('user_access')
      .select('role')
      .eq('accessor_id', userId)
      .eq('beneficiary_id', beneficiaryId)
      .single();

    if (accessError || !access || access.role !== 'owner') {
      return res.status(403).json({ error: 'Only owner can create invitations' });
    }

    // Generate unique token
    let inviteToken = generateInviteToken();
    let attempts = 0;
    while (attempts < 5) {
      const { data: existing } = await supabase
        .from('invitations')
        .select('id')
        .eq('token', inviteToken)
        .single();

      if (!existing) break;
      inviteToken = generateInviteToken();
      attempts++;
    }

    // Create invitation (expires in 7 days)
    const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);

    const { data: invitation, error } = await supabase
      .from('invitations')
      .insert({
        beneficiary_id: beneficiaryId,
        invited_by: userId,
        token: inviteToken,
        role,
        email: email?.toLowerCase() || null,
        expires_at: expiresAt.toISOString()
      })
      .select()
      .single();

    if (error) {
      console.error('Create invitation error:', error);
      return res.status(500).json({ error: 'Failed to create invitation' });
    }

    // TODO: Send invitation email if email provided

    res.json({
      success: true,
      invitation: {
        id: invitation.id,
        code: invitation.token,
        role: invitation.role,
        expiresAt: invitation.expires_at
      }
    });

  } catch (error) {
    console.error('Create invitation error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/invitations/accept
 * Accepts an invitation code
 */
router.post('/accept', async (req, res) => {
  try {
    const userId = req.user.userId;
    const { code } = req.body;

    if (!code) {
      return res.status(400).json({ error: 'Code is required' });
    }

    // Find valid invitation
    const { data: invitation, error: findError } = await supabase
      .from('invitations')
      .select('*')
      .eq('token', code.toUpperCase())
      .is('accepted_by', null)
      .gt('expires_at', new Date().toISOString())
      .single();

    if (findError || !invitation) {
      return res.status(404).json({ error: 'Invalid or expired invitation code' });
    }

    // Check if email restriction matches (if set)
    if (invitation.email) {
      const { data: user } = await supabase
        .from('users')
        .select('email')
        .eq('id', userId)
        .single();

      if (user.email.toLowerCase() !== invitation.email.toLowerCase()) {
        return res.status(403).json({ error: 'This invitation is for a different email address' });
      }
    }

    // Check if user already has access
    const { data: existingAccess } = await supabase
      .from('user_access')
      .select('id')
      .eq('accessor_id', userId)
      .eq('beneficiary_id', invitation.beneficiary_id)
      .single();

    if (existingAccess) {
      // Update invitation as accepted but don't create duplicate access
      await supabase
        .from('invitations')
        .update({
          accepted_by: userId,
          accepted_at: new Date().toISOString()
        })
        .eq('id', invitation.id);

      return res.json({
        success: true,
        message: 'You already have access to this beneficiary'
      });
    }

    // Create user_access record
    const { error: accessError } = await supabase
      .from('user_access')
      .insert({
        accessor_id: userId,
        beneficiary_id: invitation.beneficiary_id,
        role: invitation.role,
        granted_by: invitation.invited_by
      });

    if (accessError) {
      console.error('Create access error:', accessError);
      return res.status(500).json({ error: 'Failed to grant access' });
    }

    // Mark invitation as accepted
    await supabase
      .from('invitations')
      .update({
        accepted_by: userId,
        accepted_at: new Date().toISOString()
      })
      .eq('id', invitation.id);

    // Get beneficiary info
    const { data: beneficiary } = await supabase
      .from('users')
      .select('id, email, first_name, last_name')
      .eq('id', invitation.beneficiary_id)
      .single();

    res.json({
      success: true,
      message: 'Invitation accepted',
      beneficiary: {
        id: beneficiary?.id,
        firstName: beneficiary?.first_name,
        lastName: beneficiary?.last_name,
        email: beneficiary?.email
      },
      role: invitation.role
    });

  } catch (error) {
    console.error('Accept invitation error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/invitations
 * Lists pending invitations created by user
 */
router.get('/', async (req, res) => {
  try {
    const userId = req.user.userId;

    // Get invitations
    const { data: invitations, error } = await supabase
      .from('invitations')
      .select('id, token, role, email, beneficiary_id, expires_at, accepted_at, created_at')
      .eq('invited_by', userId)
      .order('created_at', { ascending: false });

    if (error) {
      console.error('List invitations error:', error);
      return res.status(500).json({ error: 'Failed to list invitations' });
    }

    // Get beneficiary details for each invitation
    const result = [];
    for (const inv of (invitations || [])) {
      const { data: beneficiary } = await supabase
        .from('users')
        .select('id, first_name, last_name')
        .eq('id', inv.beneficiary_id)
        .single();

      result.push({
        id: inv.id,
        code: inv.token,
        role: inv.role,
        email: inv.email,
        expiresAt: inv.expires_at,
        acceptedAt: inv.accepted_at,
        createdAt: inv.created_at,
        beneficiary: beneficiary ? {
          id: beneficiary.id,
          firstName: beneficiary.first_name,
          lastName: beneficiary.last_name
        } : null,
        status: inv.accepted_at ? 'accepted' :
                new Date(inv.expires_at) < new Date() ? 'expired' : 'pending'
      });
    }

    res.json({ invitations: result });

  } catch (error) {
    console.error('List invitations error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * DELETE /api/invitations/:id
 * Revokes a pending invitation
 */
router.delete('/:id', async (req, res) => {
  try {
    const userId = req.user.userId;
    const invitationId = parseInt(req.params.id, 10);

    // Check invitation belongs to user and is not accepted
    const { data: invitation, error: findError } = await supabase
      .from('invitations')
      .select('*')
      .eq('id', invitationId)
      .eq('invited_by', userId)
      .single();

    if (findError || !invitation) {
      return res.status(404).json({ error: 'Invitation not found' });
    }

    if (invitation.accepted_at) {
      return res.status(400).json({ error: 'Cannot revoke accepted invitation' });
    }

    // Delete invitation
    const { error } = await supabase
      .from('invitations')
      .delete()
      .eq('id', invitationId);

    if (error) {
      return res.status(500).json({ error: 'Failed to revoke invitation' });
    }

    res.json({ success: true });

  } catch (error) {
    console.error('Revoke invitation error:', error);
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;
