import { useEffect } from 'react';

import { getChatLogs, getLeads } from '@/lib/api';
import { mapLeadRecordToStoreLead } from '@/lib/crmMappers';
import { mapInventoryPropertySummaryToUnit } from '@/lib/platformMappers';
import { useStore } from '@/store/useStore';
import type { ChatMessage } from '@/types';
import type { LeadRecord } from '@/lib/api';
import { listInventoryProperties } from '@/lib/velocityPlatformClient';

export function useCrmBootstrap() {
  const { setLeads, replaceMessages, setUnits, updateMetrics, setVelocityData, updateStatus } = useStore();

  useEffect(() => {
    let cancelled = false;
    const hydrate = async () => {
      updateStatus({
        isConnected: false,
        serverStatus: 'syncing',
      });

      try {
        const leads = await getLeads();
        if (cancelled) return;
        setLeads(leads.map(mapLeadRecordToStoreLead));

        const messageEntries = await Promise.all(
          leads.slice(0, 25).map(async (lead) => {
            const logs = await getChatLogs(lead.id);
            return [
              lead.id,
              logs.map((log): ChatMessage => ({
                id: log.id,
                sender: log.sender === 'lead' ? 'user' : 'oracle',
                content: log.content,
                timestamp: new Date(log.created_at ?? Date.now()),
              })),
            ] as const;
          }),
        );
        if (!cancelled) {
          replaceMessages(Object.fromEntries(messageEntries));
        }

        const inventoryResult = await listInventoryProperties(100).catch(() => null);
        if (!cancelled) {
          const units = inventoryResult?.properties.map(mapInventoryPropertySummaryToUnit) ?? [];
          setUnits(units);
          updateMetrics(buildDashboardMetrics(leads, messageEntries, units.length));
          setVelocityData(buildVelocitySeries(leads));
          updateStatus({
            isConnected: true,
            serverStatus: 'online',
            lastSync: new Date(),
          });
        }
      } catch {
        if (!cancelled) {
          setLeads([]);
          replaceMessages({});
          setUnits([]);
          updateMetrics({
            activeVisitors: 0,
            todayLeads: 0,
            closedDeals: 0,
            conversionRate: 0,
            sentiment: 0,
            systemHealth: {
              cpu: 0,
              gpu: 0,
              memory: 0,
              temperature: 0,
            },
          });
          setVelocityData([]);
          updateStatus({
            isConnected: false,
            serverStatus: 'offline',
            lastSync: new Date(),
          });
        }
      }
    };

    void hydrate();
    return () => {
      cancelled = true;
    };
  }, [replaceMessages, setLeads, setUnits, setVelocityData, updateMetrics, updateStatus]);
}

function buildDashboardMetrics(
  leads: LeadRecord[],
  messageEntries: ReadonlyArray<readonly [string, ChatMessage[]]>,
  inventoryCount: number,
) {
  const closedDeals = leads.filter((lead) => lead.stage === 'closed').length;
  const engagedLeads = leads.filter((lead) => lead.score >= 75 || lead.stage === 'negotiation' || lead.stage === 'qualified').length;
  const averageScore = leads.length > 0
    ? Math.round(leads.reduce((sum, lead) => sum + lead.score, 0) / leads.length)
    : 0;
  const totalMessages = messageEntries.reduce((sum, [, messages]) => sum + messages.length, 0);

  return {
    activeVisitors: Math.min(999, totalMessages),
    todayLeads: leads.length,
    closedDeals,
    conversionRate: leads.length > 0 ? Number(((closedDeals / leads.length) * 100).toFixed(1)) : 0,
    sentiment: averageScore,
    systemHealth: {
      cpu: Math.min(100, 10 + leads.length * 2),
      gpu: Math.min(100, 5 + Math.round(inventoryCount * 1.5)),
      memory: Math.min(100, 15 + totalMessages),
      temperature: Math.min(100, 20 + engagedLeads * 4),
    },
  };
}

function buildVelocitySeries(leads: LeadRecord[]) {
  const buckets = new Map<string, { generated: number; closed: number }>();

  for (let dayOffset = 6; dayOffset >= 0; dayOffset -= 1) {
    const day = new Date();
    day.setHours(0, 0, 0, 0);
    day.setDate(day.getDate() - dayOffset);
    const key = day.toISOString().slice(0, 10);
    buckets.set(key, { generated: 0, closed: 0 });
  }

  for (const lead of leads) {
    const createdKey = (lead.created_at ?? '').slice(0, 10);
    const updatedKey = (lead.updated_at ?? lead.created_at ?? '').slice(0, 10);
    if (buckets.has(createdKey)) {
      buckets.get(createdKey)!.generated += 1;
    }
    if (lead.stage === 'closed' && buckets.has(updatedKey)) {
      buckets.get(updatedKey)!.closed += 1;
    }
  }

  return Array.from(buckets.entries()).map(([key, value]) => ({
    time: key.slice(5),
    generated: value.generated,
    closed: value.closed,
  }));
}
