import api from './client';

// ─── Types ────────────────────────────────────────────────────────────────

export type EstimateStage = 'draft' | 'delivered' | 'accepted' | 'rejected' | 'expired' | 'scheduled' | 'closed';
export type EstimateSource = 'manual' | 'angi' | 'servicetitan' | 'jobber' | 'hubspot' | 'email' | 'referral' | 'website';

export interface StageHistoryEntry {
  from_stage: EstimateStage | null;
  to_stage?: EstimateStage;
  stage?: EstimateStage;
  timestamp: string;
  notes?: string;
  changed_by?: string;
}

export interface LineItem {
  description: string;
  quantity: number;
  unit_price: number;
  total: number;
}

export interface Estimate {
  id: string;
  company_id: string;
  estimate_number: string;
  project_id?: string;
  customer_id?: string;
  source_lead_id?: string;
  customer_name: string;
  customer_email: string;
  customer_phone: string;
  project_type: string;
  description: string;
  address: string;
  city: string;
  state: string;
  zip_code: string;
  total_value: number;
  deposit: number;
  tax_amount: number;
  discount_amount: number;
  line_items: LineItem[];
  stage: EstimateStage;
  stage_history: StageHistoryEntry[];
  days_in_stage: number | null;
  current_stage_timestamp: string | null;
  expires_at: string | null;
  rejection_reason: string;
  competitor_name: string;
  competitor_price: number | null;
  notes: string;
  assigned_to: string | null;
  source: EstimateSource;
  source_estimate_id: string;
  is_active: boolean;
  is_closed: boolean;
  delivered_at: string | null;
  accepted_at: string | null;
  rejected_at: string | null;
  scheduled_date: string | null;
  closed_at: string | null;
  created_at: string;
  updated_at: string;
}

// ─── Funnel Analytics ─────────────────────────────────────────────────────

export interface ConversionRate {
  from_stage: EstimateStage;
  to_stage: EstimateStage;
  from_count: number;
  to_count: number;
  rate: number;
}

export interface PipelineSummary {
  total_pipeline_value: number;
  closed_value: number;
  closed_count: number;
  win_rate: number;
  avg_deal_size: number;
  avg_time_to_accept_days: number | null;
}

export interface DropOffData {
  rejected_count: number;
  expired_count: number;
  total_drop_off_count: number;
  drop_off_rate: number;
  rejection_reasons: Record<string, number>;
}

export interface FunnelAnalytics {
  period_days: number;
  total_estimates: number;
  stage_counts: Record<EstimateStage, number>;
  stage_values: Record<EstimateStage, number>;
  conversion_rates: Record<string, ConversionRate>;
  pipeline_summary: PipelineSummary;
  drop_off: DropOffData;
}

export interface PipelineStageData {
  count: number;
  value: number;
  avg_value: number;
}

export interface PipelineOverview {
  period_days: number;
  total_estimates: number;
  active_estimates: number;
  closed_estimates: number;
  pipeline: Record<string, PipelineStageData>;
  total_pipeline_value: number;
  total_closed_value: number;
}

export interface EstimateStats {
  period_days: number;
  total_count: number;
  active_count: number;
  closed_count: number;
  total_value: number;
  pipeline_value: number;
  closed_value: number;
  avg_estimate_size: number;
  conversion_rate: number;
  avg_days_to_close: number | null;
}

export interface SourceBreakdown {
  count: number;
  total_value: number;
  closed_count: number;
  closed_value: number;
  conversion_rate: number;
  avg_value: number;
}

export interface EstimatesBySource {
  period_days: number;
  sources: Record<string, SourceBreakdown>;
}

export interface EstimateListResponse {
  estimates: Estimate[];
  page: number;
  per_page: number;
  total: number;
  total_pages: number;
  pages?: number;
  has_next?: boolean;
  has_prev?: boolean;
}

// ─── API ──────────────────────────────────────────────────────────────────

export const estimatesApi = {
  // CRUD
  getEstimates: async (
    companyId: string,
    params?: {
      stage?: EstimateStage;
      source?: EstimateSource;
      min_value?: number;
      max_value?: number;
      project_type?: string;
      is_active?: string;
      is_closed?: string;
      sort_by?: string;
      sort_order?: 'asc' | 'desc';
      page?: number;
      per_page?: number;
    }
  ): Promise<EstimateListResponse> => {
    const { data } = await api.get<EstimateListResponse>(
      `/api/company/${companyId}/estimates`,
      { params }
    );
    return data;
  },

  getEstimate: async (companyId: string, estimateId: string): Promise<{ estimate: Estimate }> => {
    const { data } = await api.get<{ estimate: Estimate }>(
      `/api/company/${companyId}/estimates/${estimateId}`
    );
    return data;
  },

  createEstimate: async (companyId: string, payload: Partial<Estimate> & { total_value: number }): Promise<{ success: boolean; estimate: Estimate }> => {
    const { data } = await api.post<{ success: boolean; estimate: Estimate }>(
      `/api/company/${companyId}/estimates`,
      payload
    );
    return data;
  },

  updateEstimate: async (companyId: string, estimateId: string, payload: Partial<Estimate>): Promise<{ success: boolean; estimate: Estimate }> => {
    const { data } = await api.put<{ success: boolean; estimate: Estimate }>(
      `/api/company/${companyId}/estimates/${estimateId}`,
      payload
    );
    return data;
  },

  deleteEstimate: async (companyId: string, estimateId: string): Promise<{ success: boolean; message: string }> => {
    const { data } = await api.delete<{ success: boolean; message: string }>(
      `/api/company/${companyId}/estimates/${estimateId}`
    );
    return data;
  },

  // Transitions
  transitionEstimate: async (
    companyId: string,
    estimateId: string,
    payload: { stage: EstimateStage; notes?: string; scheduled_date?: string }
  ): Promise<{ success: boolean; estimate: Estimate; transition: { from_stage: string; to_stage: string; timestamp: string } }> => {
    const { data } = await api.patch<{ success: boolean; estimate: Estimate; transition: { from_stage: string; to_stage: string; timestamp: string } }>(
      `/api/company/${companyId}/estimates/${estimateId}/transition`,
      payload
    );
    return data;
  },

  getStageHistory: async (companyId: string, estimateId: string): Promise<{ estimate_id: string; current_stage: EstimateStage; stage_history: StageHistoryEntry[] }> => {
    const { data } = await api.get<{ estimate_id: string; current_stage: EstimateStage; stage_history: StageHistoryEntry[] }>(
      `/api/company/${companyId}/estimates/${estimateId}/stage-history`
    );
    return data;
  },

  // Bulk
  expireOldEstimates: async (
    companyId: string,
    daysBeforeExpiry?: number
  ): Promise<{ success: boolean; expired_count: number; expired_ids: string[] }> => {
    const { data } = await api.patch<{ success: boolean; expired_count: number; expired_ids: string[] }>(
      `/api/company/${companyId}/estimates/expired`,
      {},
      { params: daysBeforeExpiry ? { days_before_expiry: daysBeforeExpiry } : {} }
    );
    return data;
  },

  // Analytics
  getFunnelAnalytics: async (
    companyId: string,
    params?: { days?: number; source?: EstimateSource; project_type?: string }
  ): Promise<FunnelAnalytics> => {
    const { data } = await api.get<FunnelAnalytics>(
      `/api/company/${companyId}/estimates/funnel`,
      { params }
    );
    return data;
  },

  getPipelineOverview: async (
    companyId: string,
    days?: number
  ): Promise<PipelineOverview> => {
    const { data } = await api.get<PipelineOverview>(
      `/api/company/${companyId}/estimates/pipeline`,
      { params: { days: days ?? 90 } }
    );
    return data;
  },

  getEstimateStats: async (
    companyId: string,
    days?: number
  ): Promise<EstimateStats> => {
    const { data } = await api.get<EstimateStats>(
      `/api/company/${companyId}/estimates/stats`,
      { params: { days: days ?? 30 } }
    );
    return data;
  },

  getEstimatesBySource: async (
    companyId: string,
    days?: number
  ): Promise<EstimatesBySource> => {
    const { data } = await api.get<EstimatesBySource>(
      `/api/company/${companyId}/estimates/by-source`,
      { params: { days: days ?? 90 } }
    );
    return data;
  },
};