import { supabase } from '@/integrations/supabase/client';
import { jsPDF } from 'jspdf';
import autoTable from 'jspdf-autotable';
import { format } from 'date-fns';

const getEndOfDay = (date) => {
  if (!date || !(date instanceof Date) || isNaN(date)) {
    return new Date();
  }
  const end = new Date(date);
  end.setHours(23, 59, 59, 999);
  return end;
};

const isValidDate = (d) => d instanceof Date && !isNaN(d);

const ensureAddress = (addr) => {
  if (!addr || addr.trim() === '') return 'Association-level';
  return addr;
};

const cleanText = (text) => {
  if (!text) return '';
  return text.replace(/<[^>]*>/g, '').replace(/&nbsp;/g, ' ').trim();
};

export const formatCurrency = (amount) => {
  const value = parseFloat(amount);
  if (isNaN(value)) return '$0.00';
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  }).format(value);
};

export const fetchStatusReportsData = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) throw new Error("Invalid dates passed to fetchStatusReportsData");
  
  const adjustedEndDate = getEndOfDay(endDate);

  let query = supabase
    .from('status_updates')
    .select('*')
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .order('created_at', { ascending: false });

  if (associationId) query = query.eq('association_id', associationId);
  
  const { data, error } = await query;
  if (error) throw error;
  
  return data.map(item => ({
    ...item,
    content: cleanText(item.content),
    title: cleanText(item.title)
  }));
};

export const fetchOwnerReportsData = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) throw new Error("Invalid dates passed to fetchOwnerReportsData");

  const adjustedEndDate = getEndOfDay(endDate);

  let query = supabase
    .from('owner_updates')
    .select('*')
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .order('created_at', { ascending: false });

  if (associationId) {
    query = query.eq('association_id', associationId);
  }

  const { data, error } = await query;
  if (error) throw error;
  
  return data.map(item => ({
    ...item,
    content: cleanText(item.content)
  }));
};

export const fetchViolationsReportData = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) throw new Error("Invalid dates passed to fetchViolationsReportData");

  const adjustedEndDate = getEndOfDay(endDate);

  // Note: violations table doesn't exist yet in the schema - this is a placeholder
  // that will work once the table is created
  console.warn('fetchViolationsReportData: violations table may not exist yet');
  return [];
};

export const fetchEstoppelsReportData = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) throw new Error("Invalid dates passed to fetchEstoppelsReportData");

  const adjustedEndDate = getEndOfDay(endDate);

  let query = supabase
    .from('estoppels')
    .select('*')
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .order('created_at', { ascending: false });

  if (associationId) query = query.eq('association_id', associationId);

  const { data, error } = await query;
  if (error) throw error;

  return data.map(item => ({
    ...item,
    address: ensureAddress(item.address),
    notes: cleanText(item.notes)
  }));
};

export const fetchCallLogsData = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) throw new Error("Invalid dates passed to fetchCallLogsData");

  const adjustedEndDate = getEndOfDay(endDate);

  let query = supabase
    .from('call_logs')
    .select('*')
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .order('created_at', { ascending: false });

  if (associationId) query = query.eq('association_id', associationId);

  const { data, error } = await query;
  if (error) throw error;

  return data.map(item => ({
    ...item,
    notes: cleanText(item.notes)
  }));
};

export const fetchStandardizedCollectionsReport = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) throw new Error("Invalid dates passed to fetchStandardizedCollectionsReport");

  const adjustedEndDate = getEndOfDay(endDate);

  let query = supabase
    .from('collections')
    .select(`
      *,
      owners (
        first_name,
        last_name
      )
    `)
    .lte('created_at', adjustedEndDate.toISOString())
    .order('created_at', { ascending: false });

  if (associationId) query = query.eq('association_id', associationId);

  const { data, error } = await query;
  if (error) throw error;

  const openCollections = [];
  const resolvedCollections = [];
  let totalAmountOpen = 0;
  let totalAmountResolved = 0;

  data.forEach(item => {
    const amount = parseFloat(item.amount_owed) || 0;
    const status = item.status || 'Unknown';
    const isResolved = status.toLowerCase() === 'resolved' || status.toLowerCase() === 'closed';
    const resolvedDate = item.updated_at ? new Date(item.updated_at) : null;
    
    const processedItem = {
      id: item.id,
      owner_name: item.owners ? `${item.owners.first_name} ${item.owners.last_name}` : 'Unknown Owner',
      amount_due: amount,
      status: status,
      notes: cleanText(item.notes),
      created_at: item.created_at
    };

    if (isResolved) {
      if (resolvedDate && resolvedDate >= startDate && resolvedDate <= adjustedEndDate) {
        resolvedCollections.push(processedItem);
        totalAmountResolved += amount;
      }
    } else {
      openCollections.push(processedItem);
      totalAmountOpen += amount;
    }
  });

  return {
    open: openCollections,
    resolved: resolvedCollections,
    stats: {
      total: openCollections.length + resolvedCollections.length,
      openCount: openCollections.length,
      resolvedCount: resolvedCollections.length,
      totalAmountOpen,
      totalAmountResolved
    }
  };
};

export const fetchReportStats = async (startDate, endDate, associationId) => {
  if (!isValidDate(startDate) || !isValidDate(endDate)) {
    console.error("Invalid dates passed to fetchReportStats", { startDate, endDate });
    return {
      status: 0, owner: 0, violations: 0,
      collections: { count: 0, total: 0, byStatus: {} },
      estoppels: 0, callLogs: 0
    };
  }

  const adjustedEndDate = getEndOfDay(endDate);
  
  const statusQuery = supabase
    .from('status_updates')
    .select('id', { count: 'exact', head: true })
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .eq('association_id', associationId);
    
  const ownerQuery = supabase
    .from('owner_updates')
    .select('id', { count: 'exact', head: true })
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .eq('association_id', associationId);

  const collectionsQuery = supabase
    .from('collections')
    .select('status, amount_owed')
    .lte('created_at', adjustedEndDate.toISOString())
    .neq('status', 'resolved')
    .eq('association_id', associationId);

  const estoppelsQuery = supabase
    .from('estoppels')
    .select('id', { count: 'exact', head: true })
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .eq('association_id', associationId);

  const callLogsQuery = supabase
    .from('call_logs')
    .select('id', { count: 'exact', head: true })
    .gte('created_at', startDate.toISOString())
    .lte('created_at', adjustedEndDate.toISOString())
    .eq('association_id', associationId);

  const [statusRes, ownerRes, collectionsRes, estoppelsRes, callLogsRes] = await Promise.all([
    statusQuery, ownerQuery, collectionsQuery, estoppelsQuery, callLogsQuery
  ]);

  const collectionsData = collectionsRes.data || [];
  const collectionsCount = collectionsData.length;
  const collectionsTotal = collectionsData.reduce((sum, item) => sum + (Number(item.amount_owed) || 0), 0);
  const collectionsByStatus = collectionsData.reduce((acc, item) => {
    const s = item.status || 'Unknown';
    acc[s] = (acc[s] || 0) + 1;
    return acc;
  }, {});

  return {
    status: statusRes.count || 0,
    owner: ownerRes.count || 0,
    violations: 0,
    collections: {
      count: collectionsCount,
      total: collectionsTotal,
      byStatus: collectionsByStatus
    },
    estoppels: estoppelsRes.count || 0,
    callLogs: callLogsRes.count || 0
  };
};
