
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/contexts/AuthContext';
import { useToast } from '@/hooks/use-toast';
import { sendEmailViaSMTP } from '@/lib/sendEmailViaSMTP';
import { generateOwnerNotificationProofPdf } from '@/lib/ownerNotificationPdfGenerator';

const NotifyOwnersContext = createContext();

export function NotifyOwnersProvider({ children }) {
  const { user } = useAuth();
  const { toast } = useToast();
  
  const [clients, setClients] = useState([]);
  const [selectedClientId, setSelectedClientId] = useState('');
  const [owners, setOwners] = useState([]);
  const [loading, setLoading] = useState(false);
  const [history, setHistory] = useState([]);
  const [templates, setTemplates] = useState([]);

  useEffect(() => {
    fetchClients();
    fetchTemplates();
  }, []);

  useEffect(() => {
    if (selectedClientId) {
      fetchOwners(selectedClientId);
      fetchHistory(selectedClientId);
    } else {
      setOwners([]);
      setHistory([]);
    }
  }, [selectedClientId]);

  const fetchClients = async () => {
    try {
        const { data, error } = await supabase
          .from('associations')
          .select('id, name')
          .eq('status', 'active')
          .order('name');
        
        if (error) throw error;
        setClients(data || []);
        if (data && data.length > 0 && !selectedClientId) {
          setSelectedClientId(data[0].id);
        }
    } catch (err) {
        console.error("Error fetching associations:", err.message);
    }
  };

  const fetchTemplates = async () => {
    try {
        const { data, error } = await supabase
          .from('email_templates')
          .select('*')
          .order('name');
        if (error) throw error;
        setTemplates(data || []);
    } catch (err) {
        console.error("Error fetching templates:", err.message);
    }
  };

  const fetchOwners = async (associationId) => {
    setLoading(true);
    try {
        const { data, error } = await supabase
          .from('owners')
          .select('id, first_name, last_name, email, electronic_consent, mailing_address')
          .eq('association_id', associationId)
          .eq('status', 'active');
        
        if (error) throw error;
        setOwners(data || []);
    } catch (err) {
        console.error("Error fetching owners:", err.message);
        toast({ variant: "destructive", title: "Access Error", description: "Failed to load owners." });
    } finally {
        setLoading(false);
    }
  };

  const fetchHistory = async (associationId) => {
    try {
        const { data, error } = await supabase
          .from('owner_notification_proofs')
          .select('*')
          .eq('association_id', associationId)
          .order('created_at', { ascending: false });

        if (error) throw error;
        setHistory(data || []);
    } catch (err) {
        console.error("Error fetching history:", err.message);
    }
  };

  const getOwnersByConsent = useCallback((onlyConsented = false) => {
    if (!owners) return [];
    if (onlyConsented) {
      return owners.filter(o => o.electronic_consent && o.email);
    }
    return owners.filter(o => o.email); 
  }, [owners]);

  const sendNotification = async ({ subject, body, senderId, senderName, senderEmail, cc = [], bcc = [], attachments = [], targetGroup = 'all', customOwners = [] }) => {
    if (!selectedClientId) return { success: false, error: "No association selected" };
    if (!user) return { success: false, error: "User session expired or unauthorized." };
    if (!senderId) return { success: false, error: "No email sender selected." };
    
    setLoading(true);
    try {
        const clientInfo = clients.find(c => c.id === selectedClientId) || { name: 'Association' };
        const ownersToNotify = targetGroup === 'selected'
          ? (customOwners || []).filter(o => o.email)
          : getOwnersByConsent(targetGroup === 'consented');
        
        if (ownersToNotify.length === 0) {
            throw new Error('No valid email recipients found in selected group.');
        }

        let successCount = 0;
        const failedEmails = [];
        const perOwnerStatus = [];
        let lastError = null;

        const formattedBody = body.replace(/\n/g, '<br />');

        // Collect all owner emails for BCC — send the message TO the sender, BCC owners
        const allOwnerEmails = [];
        for (const owner of ownersToNotify) {
            const ownerName = [owner.first_name, owner.last_name].filter(Boolean).join(' ') || 'Owner';
            allOwnerEmails.push(owner.email);
            perOwnerStatus.push({ name: ownerName, email: owner.email, status: 'pending' });
        }

        // Chunk BCC list into smaller batches to avoid SMTP server connection limits
        // (Hostinger and most providers cap recipients per envelope at ~50-100).
        // Each batch is a separate edge function invocation with a fresh SMTP connection.
        const BATCH_SIZE = 25;
        const bccBatches = [];
        for (let i = 0; i < allOwnerEmails.length; i += BATCH_SIZE) {
            bccBatches.push(allOwnerEmails.slice(i, i + BATCH_SIZE));
        }

        for (let i = 0; i < bccBatches.length; i++) {
            const batchBcc = bccBatches[i];
            // Only attach manual cc/bcc on the first batch to avoid duplicates.
            const batchCc = i === 0 ? cc : [];
            const extraBcc = i === 0 ? bcc : [];

            try {
              const result = await sendEmailViaSMTP({
                sender_id: senderId,
                recipient_email: senderEmail,
                cc: batchCc,
                bcc: [...batchBcc, ...extraBcc],
                subject,
                htmlBody: formattedBody,
                attachments,
                debug: false
              });

              if (result.success) {
                successCount += batchBcc.length;
                batchBcc.forEach(email => {
                  const entry = perOwnerStatus.find(o => o.email === email);
                  if (entry) entry.status = 'accepted';
                });
              } else {
                lastError = result.error;
                batchBcc.forEach(email => {
                  const entry = perOwnerStatus.find(o => o.email === email);
                  if (entry) { entry.status = 'failed'; entry.error = result.error; }
                  failedEmails.push(email);
                });
              }
            } catch (sendErr) {
              lastError = sendErr.message;
              batchBcc.forEach(email => {
                const entry = perOwnerStatus.find(o => o.email === email);
                if (entry) { entry.status = 'failed'; entry.error = sendErr.message; }
                failedEmails.push(email);
              });
              console.error(`Error sending BCC batch ${i + 1}:`, sendErr);
            }

            // Brief pause between batches to be gentle with the SMTP server.
            if (i < bccBatches.length - 1) {
              await new Promise(r => setTimeout(r, 1500));
            }
        }

        if (successCount === 0 && failedEmails.length > 0) {
            throw new Error(lastError || 'All emails failed to send. Please check your sender SMTP configuration in Email Settings.');
        }

        // Generate proof PDF
        let proofUrl = null;
        let validationId = crypto.randomUUID();
        try {
          const proofResult = await generateOwnerNotificationProofPdf({
            associationName: clientInfo.name,
            subject,
            body,
            owners: perOwnerStatus.map(o => ({
              first_name: o.name.split(' ')[0],
              last_name: o.name.split(' ').slice(1).join(' '),
              email: o.email,
              status: o.status
            })),
            attachments,
            senderName: senderName || 'System',
            senderEmail: senderEmail || ''
          });
          if (proofResult && proofResult.publicUrl) {
            proofUrl = proofResult.publicUrl;
            validationId = proofResult.validationId || validationId;
          } else if (proofResult?.error) {
            throw proofResult.error;
          }
        } catch (pdfErr) {
          console.error("Failed to generate proof PDF:", pdfErr);
        }

        // Save proof record
        const deliveryStatus = `Accepted by SMTP: ${successCount}, Failed: ${failedEmails.length}`;
        const { error: proofError } = await supabase.from('owner_notification_proofs').insert([{
            association_id: selectedClientId,
            subject,
            body,
            owners_notified: perOwnerStatus,
            attachments: attachments.map(a => ({ name: a.name, url: a.url })),
            delivery_status: deliveryStatus,
            validation_id: validationId,
            proof_url: proofUrl,
            created_by: user.id 
        }]);

        if (proofError) {
            console.error("Failed to save proof:", proofError);
        }

        fetchHistory(selectedClientId);
        
        return { 
            success: true, 
            count: successCount, 
            failed: failedEmails.length,
            validationId,
            proofUrl,
            failedEmails,
            deliveryStatus
        };

    } catch (err) {
        console.error("Error in sendNotification:", err);
        return { success: false, error: err.message };
    } finally {
        setLoading(false);
    }
  };

  // Send/forward a proof document via email
  const sendProofEmail = async ({ proofRecord, senderId, recipientEmails }) => {
    if (!senderId || !recipientEmails || recipientEmails.length === 0) {
      return { success: false, error: "Sender and at least one recipient are required." };
    }

    const proofAttachments = proofRecord.proof_url ? [{
      name: `Notification_Proof_${proofRecord.validation_id?.substring(0, 8) || 'doc'}.pdf`,
      url: proofRecord.proof_url,
      path: proofRecord.proof_url,
    }] : [];

    const htmlBody = `
      <div style="font-family: Arial, sans-serif; max-width: 600px;">
        <h2 style="color: #2c3e50;">Proof of Notification</h2>
        <p>Attached is the cryptographic proof document for the following notification:</p>
        <table style="width: 100%; border-collapse: collapse; margin: 16px 0;">
          <tr><td style="padding: 8px; font-weight: bold; border-bottom: 1px solid #eee;">Subject:</td><td style="padding: 8px; border-bottom: 1px solid #eee;">${proofRecord.subject || 'N/A'}</td></tr>
          <tr><td style="padding: 8px; font-weight: bold; border-bottom: 1px solid #eee;">Sent:</td><td style="padding: 8px; border-bottom: 1px solid #eee;">${new Date(proofRecord.created_at).toLocaleString()}</td></tr>
          <tr><td style="padding: 8px; font-weight: bold; border-bottom: 1px solid #eee;">Delivery:</td><td style="padding: 8px; border-bottom: 1px solid #eee;">${proofRecord.delivery_status || 'N/A'}</td></tr>
          <tr><td style="padding: 8px; font-weight: bold;">Validation ID:</td><td style="padding: 8px; font-family: monospace;">${proofRecord.validation_id || 'N/A'}</td></tr>
        </table>
        ${proofRecord.proof_url ? `<p><a href="${proofRecord.proof_url}" style="color: #2980b9;">View Proof Document Online</a></p>` : ''}
        <p style="color: #999; font-size: 12px; margin-top: 24px;">This is an automated verification document.</p>
      </div>
    `;

    try {
      const result = await sendEmailViaSMTP({
        sender_id: senderId,
        recipient_email: recipientEmails,
        subject: `Proof of Notification: ${proofRecord.subject || 'Owner Notification'}`,
        htmlBody,
        attachments: proofAttachments,
        debug: false
      });
      return result;
    } catch (err) {
      return { success: false, error: err.message };
    }
  };

  return (
    <NotifyOwnersContext.Provider value={{
      clients,
      selectedClientId,
      setSelectedClientId,
      owners,
      loading,
      history,
      templates,
      getOwnersByConsent,
      sendNotification,
      sendProofEmail,
      refreshHistory: () => fetchHistory(selectedClientId),
      refreshTemplates: fetchTemplates
    }}>
      {children}
    </NotifyOwnersContext.Provider>
  );
}

export const useNotifyOwners = () => useContext(NotifyOwnersContext);
