import React, { useState, useEffect, useCallback } from 'react';
import { useAuth } from '../../contexts/AuthContext';
import { AppLayout } from '../../components/layout/AppLayout';
import {
  getForecasts,
  createForecast,
  updateForecast,
  deleteForecast,
  syncForecasts,
  getForecastSyncStatus,
} from '../../api/forecasts';
import type { Forecast, ForecastCreate, ForecastType, ForecastSyncResult } from '../../types';
import {
  Plus, X, Search, Filter, TrendingUp, BarChart3, DollarSign, LineChart,
  Edit, Trash2, ArrowUpRight, ArrowDownRight, Percent, Calendar,
  RefreshCw, Database, CheckCircle2, AlertCircle, Clock,
} from 'lucide-react';

const typeIcons: Record<ForecastType, React.ElementType> = {
  revenue: DollarSign,
  pipeline: BarChart3,
  cost: TrendingUp,
};

// Human-readable data source labels + colors
const dataSourceConfig: Record<string, { label: string; color: string }> = {
  quickbooks_invoices_paid: { label: 'QB Invoices', color: 'bg-blue-100 text-blue-700' },
  quickbooks_transactions: { label: 'QB Transactions', color: 'bg-indigo-100 text-indigo-700' },
  quickbooks_expenses: { label: 'QB Expenses', color: 'bg-violet-100 text-violet-700' },
  crm_weighted_deals: { label: 'CRM Deals', color: 'bg-amber-100 text-amber-700' },
  rolling_3_month_average: { label: 'Auto Projection', color: 'bg-slate-100 text-slate-600' },
  manual: { label: 'Manual', color: 'bg-orange-100 text-orange-700' },
};

function dataSourceBadge(methodology: string | null) {
  if (!methodology) return null;
  const cfg = dataSourceConfig[methodology];
  if (!cfg) return null;
  return (
    <span className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium ${cfg.color}`}>
      <Database className="h-2.5 w-2.5" />
      {cfg.label}
    </span>
  );
}

export function ForecastsPage() {
  const { user } = useAuth();
  const companyId = user?.tenantId as string;

  const [forecasts, setForecasts] = useState<Forecast[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [showCreate, setShowCreate] = useState(false);
  const [editingForecast, setEditingForecast] = useState<Forecast | null>(null);
  const [search, setSearch] = useState('');
  const [filterType, setFilterType] = useState<'all' | ForecastType>('all');

  // Sync state
  const [syncing, setSyncing] = useState(false);
  const [syncResult, setSyncResult] = useState<ForecastSyncResult | null>(null);
  const [lastSync, setLastSync] = useState<string | null>(null);

  const [form, setForm] = useState<ForecastCreate>({
    forecast_type: 'revenue',
    period: 'monthly',
    period_start: '',
    period_end: '',
    projected_value: 0,
    actual_value: null,
    confidence: null,
    methodology: '',
  });

  const loadForecasts = useCallback(async () => {
    if (!companyId) return;
    try {
      setLoading(true);
      const data = await getForecasts(companyId);
      setForecasts(data);
      setError(null);
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Failed to load forecasts');
    } finally {
      setLoading(false);
    }
  }, [companyId]);

  useEffect(() => {
    loadForecasts();
    // Load sync status
    if (companyId) {
      getForecastSyncStatus(companyId).then(s => setLastSync(s.last_sync)).catch(() => {});
    }
  }, [loadForecasts, companyId]);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!companyId) return;
    try {
      if (editingForecast) {
        await updateForecast(companyId, editingForecast.id, form);
      } else {
        await createForecast(companyId, form);
      }
      setShowCreate(false);
      setEditingForecast(null);
      setForm({ forecast_type: 'revenue', period: 'monthly', period_start: '', period_end: '', projected_value: 0, actual_value: null, confidence: null, methodology: '' });
      await loadForecasts();
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Failed to save forecast');
    }
  };

  const handleDelete = async (forecast: Forecast) => {
    if (!companyId) return;
    if (!confirm('Delete this forecast?')) return;
    try { await deleteForecast(companyId, forecast.id); await loadForecasts(); }
    catch (e) { setError(e instanceof Error ? e.message : 'Failed to delete forecast'); }
  };

  const handleSync = async () => {
    if (!companyId) return;
    setSyncing(true);
    setSyncResult(null);
    setError(null);
    try {
      const result = await syncForecasts(companyId);
      setSyncResult(result);
      await loadForecasts();
      // Update last sync time
      const status = await getForecastSyncStatus(companyId);
      setLastSync(status.last_sync);
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Sync failed');
    } finally {
      setSyncing(false);
    }
  };

  const startEdit = (forecast: Forecast) => {
    setEditingForecast(forecast);
    setForm({
      forecast_type: forecast.forecast_type,
      period: forecast.period,
      period_start: forecast.period_start?.substring(0, 10) || '',
      period_end: forecast.period_end?.substring(0, 10) || '',
      projected_value: forecast.projected_value,
      actual_value: forecast.actual_value,
      confidence: forecast.confidence,
      methodology: forecast.methodology,
    });
    setShowCreate(true);
  };

  const filtered = forecasts
    .filter(f => filterType === 'all' || f.forecast_type === filterType)
    .filter(f => search === '' || f.period.toLowerCase().includes(search.toLowerCase()) || f.methodology.toLowerCase().includes(search.toLowerCase()));

  const totalProjected = forecasts.reduce((sum, f) => sum + f.projected_value, 0);
  const totalActual = forecasts.filter(f => f.actual_value !== null).reduce((sum, f) => sum + (f.actual_value ?? 0), 0);
  const overallVariance = totalProjected > 0 ? ((totalActual - totalProjected) / totalProjected * 100) : 0;

  return (
    <AppLayout title="Forecasts">
      <div data-testid="page-content">
      {/* Sync Result Banner */}
      {syncResult && (
        <div className="mb-4 rounded-xl border border-emerald-200 bg-emerald-50 p-4">
          <div className="flex items-start justify-between">
            <div className="flex items-center gap-3">
              <CheckCircle2 className="h-5 w-5 text-emerald-600 flex-shrink-0 mt-0.5" />
              <div>
                <p className="text-sm font-semibold text-emerald-800">Sync Complete</p>
                <div className="mt-1 flex flex-wrap gap-x-4 gap-y-1 text-xs text-emerald-700">
                  <span>Revenue: {syncResult.revenue_updated} updated</span>
                  <span>Pipeline: {syncResult.pipeline_updated} updated</span>
                  <span>Cost: {syncResult.cost_updated} updated</span>
                  <span>Future periods: {syncResult.future_created} created</span>
                  <span className="text-emerald-500">{(syncResult.duration_seconds * 1000).toFixed(0)}ms</span>
                </div>
              </div>
            </div>
            <button onClick={() => setSyncResult(null)} className="text-emerald-400 hover:text-emerald-600">
              <X className="h-4 w-4" />
            </button>
          </div>
          {syncResult.errors.length > 0 && (
            <div className="mt-2 flex items-start gap-2 rounded-lg bg-amber-50 p-2">
              <AlertCircle className="h-4 w-4 text-amber-500 flex-shrink-0 mt-0.5" />
              <p className="text-xs text-amber-700">{syncResult.errors.join(', ')}</p>
            </div>
          )}
        </div>
      )}

      {/* Summary */}
      <div className="mb-6 grid grid-cols-1 gap-4 sm:grid-cols-3">
        <div className="rounded-xl border border-surface-200 bg-white p-5">
          <p className="text-sm font-medium text-surface-500">Total Projected</p>
          <p className="mt-2 text-3xl font-bold text-blue-600">${totalProjected.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</p>
        </div>
        <div className="rounded-xl border border-surface-200 bg-white p-5">
          <p className="text-sm font-medium text-surface-500">Total Actual</p>
          <p className="mt-2 text-3xl font-bold text-emerald-600">${totalActual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</p>
        </div>
        <div className="rounded-xl border border-surface-200 bg-white p-5">
          <p className="text-sm font-medium text-surface-500">Overall Variance</p>
          <div className={`mt-2 flex items-center gap-1.5 text-3xl font-bold ${overallVariance >= 0 ? 'text-emerald-600' : 'text-red-600'}`}>
            {overallVariance >= 0 ? <ArrowUpRight className="h-6 w-6" /> : <ArrowDownRight className="h-6 w-6" />}
            <span>{Math.abs(overallVariance).toFixed(1)}%</span>
          </div>
        </div>
      </div>

      {/* Toolbar */}
      <div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-center gap-2">
          <div className="relative flex-1 sm:flex-initial">
            <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-surface-400" />
            <input type="text" value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search forecasts..."
              className="w-full rounded-lg border border-surface-300 py-2 pl-9 pr-4 text-sm outline-none focus:border-brand-500 sm:w-64" />
          </div>
          <select value={filterType} onChange={(e) => setFilterType(e.target.value as 'all' | ForecastType)}
            className="rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500 min-h-[44px]">
            <option value="all">All Types</option>
            <option value="revenue">Revenue</option>
            <option value="pipeline">Pipeline</option>
            <option value="cost">Cost</option>
          </select>
        </div>
        <div className="flex items-center gap-2">
          {lastSync && (
            <span className="flex items-center gap-1 text-xs text-surface-400">
              <Clock className="h-3 w-3" />
              Last sync: {new Date(lastSync).toLocaleDateString()}
            </span>
          )}
          <button
            onClick={handleSync}
            disabled={syncing}
            className="inline-flex items-center gap-2 rounded-lg border border-brand-600 px-4 py-2.5 text-sm font-medium text-brand-600 hover:bg-brand-50 disabled:opacity-50 min-h-[44px]">
            <RefreshCw className={`h-4 w-4 ${syncing ? 'animate-spin' : ''}`} />
            {syncing ? 'Syncing…' : 'Sync Now'}
          </button>
          <button onClick={() => { setShowCreate(true); setEditingForecast(null); setForm({ forecast_type: 'revenue', period: 'monthly', period_start: '', period_end: '', projected_value: 0, actual_value: null, confidence: null, methodology: '' }); }}
            className="inline-flex items-center gap-2 rounded-lg bg-brand-600 px-4 py-2.5 text-sm font-medium text-white hover:bg-brand-700 min-h-[44px]">
            <Plus className="h-4 w-4" /> Add Forecast
          </button>
        </div>
      </div>

      {error && (
        <div className="mb-4 rounded-xl border border-red-200 bg-red-50 p-4">
          <p className="text-sm font-medium text-red-800">{error}</p>
          <button onClick={() => setError(null)} className="mt-1 text-sm text-red-600 underline">Dismiss</button>
        </div>
      )}

      {/* Modal */}
      {showCreate && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="w-full max-w-lg rounded-xl bg-white p-6 shadow-xl">
            <div className="mb-4 flex items-center justify-between">
              <h2 className="text-lg font-semibold text-surface-900">{editingForecast ? 'Edit Forecast' : 'New Forecast'}</h2>
              <button onClick={() => setShowCreate(false)} className="rounded-lg p-1.5 text-surface-400 hover:bg-surface-100">
                <X className="h-5 w-5" />
              </button>
            </div>
            <form onSubmit={handleSubmit} className="space-y-4">
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium text-surface-700">Type</label>
                  <select value={form.forecast_type} onChange={(e) => setForm({ ...form, forecast_type: e.target.value as ForecastType })}
                    className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500 min-h-[44px]">
                    <option value="revenue">Revenue</option>
                    <option value="pipeline">Pipeline</option>
                    <option value="cost">Cost</option>
                  </select>
                </div>
                <div>
                  <label className="block text-sm font-medium text-surface-700">Period</label>
                  <input type="text" value={form.period} onChange={(e) => setForm({ ...form, period: e.target.value })} placeholder="e.g. monthly, Q1"
                    className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
                </div>
              </div>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium text-surface-700">Start Date</label>
                  <input type="date" value={form.period_start} onChange={(e) => setForm({ ...form, period_start: e.target.value })}
                    className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
                </div>
                <div>
                  <label className="block text-sm font-medium text-surface-700">End Date</label>
                  <input type="date" value={form.period_end} onChange={(e) => setForm({ ...form, period_end: e.target.value })}
                    className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
                </div>
              </div>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium text-surface-700">Projected Value ($)</label>
                  <input type="number" value={form.projected_value} onChange={(e) => setForm({ ...form, projected_value: Number(e.target.value) })}
                    className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
                </div>
                <div>
                  <label className="block text-sm font-medium text-surface-700">Actual Value ($)</label>
                  <input type="number" value={form.actual_value ?? ''} onChange={(e) => setForm({ ...form, actual_value: e.target.value ? Number(e.target.value) : null })}
                    className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
                </div>
              </div>
              <div>
                <label className="block text-sm font-medium text-surface-700">Methodology</label>
                <input type="text" value={form.methodology} onChange={(e) => setForm({ ...form, methodology: e.target.value })} placeholder="e.g. Historical average, Moving trend"
                  className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
              </div>
              <div>
                <label className="block text-sm font-medium text-surface-700">Confidence (%)</label>
                <input type="number" min="0" max="100" value={form.confidence ?? ''} onChange={(e) => setForm({ ...form, confidence: e.target.value ? Number(e.target.value) : null })}
                  className="mt-1 w-full rounded-lg border border-surface-300 py-2 px-3 text-sm outline-none focus:border-brand-500" />
              </div>
              <div className="flex justify-end gap-2 pt-2">
                <button type="button" onClick={() => setShowCreate(false)}
                  className="rounded-lg border border-surface-300 px-4 py-2 text-sm font-medium text-surface-700 hover:bg-surface-50 min-h-[44px]">Cancel</button>
                <button type="submit" className="rounded-lg bg-brand-600 px-4 py-2 text-sm font-medium text-white hover:bg-brand-700 min-h-[44px]">
                  {editingForecast ? 'Update' : 'Create'}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* Forecasts Table */}
      {loading ? (
        <div className="flex items-center justify-center py-12">
          <div className="h-6 w-6 animate-spin rounded-full border-2 border-brand-600 border-t-transparent" />
          <span className="ml-3 text-sm text-surface-500">Loading forecasts…</span>
        </div>
      ) : filtered.length === 0 ? (
        <div className="flex flex-col items-center justify-center rounded-xl border border-surface-200 bg-white py-16">
          <LineChart className="h-12 w-12 text-surface-300" />
          <p className="mt-4 text-sm font-medium text-surface-700">
            {search || filterType !== 'all' ? 'No forecasts match your filters' : 'No forecasts yet'}
          </p>
        </div>
      ) : (
        <div className="overflow-x-auto rounded-xl border border-surface-200 bg-white">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-surface-200 bg-surface-50">
                <th className="px-4 py-3 text-left font-medium text-surface-600">Period</th>
                <th className="px-4 py-3 text-left font-medium text-surface-600">Type</th>
                <th className="px-4 py-3 text-left font-medium text-surface-600">Source</th>
                <th className="px-4 py-3 text-right font-medium text-surface-600">Projected</th>
                <th className="px-4 py-3 text-right font-medium text-surface-600">Actual</th>
                <th className="px-4 py-3 text-right font-medium text-surface-600">Variance</th>
                <th className="px-4 py-3 text-right font-medium text-surface-600">Actions</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map((forecast) => {
                const TypeIcon = typeIcons[forecast.forecast_type] || LineChart;
                const variance = forecast.actual_value !== null
                  ? ((forecast.actual_value - forecast.projected_value) / forecast.projected_value * 100)
                  : null;
                return (
                  <tr key={forecast.id} className="border-b border-surface-100 last:border-0 hover:bg-surface-50 transition-colors">
                    <td className="px-4 py-3">
                      <div className="flex items-center gap-1 text-surface-700">
                        <Calendar className="h-3 w-3 text-surface-400" />
                        {forecast.period}
                      </div>
                      {forecast.period_start && (
                        <div className="text-xs text-surface-400">{forecast.period_start.substring(0, 10)} – {forecast.period_end?.substring(0, 10)}</div>
                      )}
                    </td>
                    <td className="px-4 py-3">
                      <div className="flex items-center gap-1.5">
                        <TypeIcon className="h-3.5 w-3.5 text-surface-400" />
                        <span className="capitalize text-surface-700">{forecast.forecast_type}</span>
                      </div>
                    </td>
                    <td className="px-4 py-3">
                      {dataSourceBadge(forecast.methodology)}
                      {!forecast.methodology && forecast.actual_value !== null && (
                        <span className="text-xs text-surface-400">Manual</span>
                      )}
                    </td>
                    <td className="px-4 py-3 text-right font-medium text-surface-900">${forecast.projected_value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</td>
                    <td className="px-4 py-3 text-right text-surface-700">
                      {forecast.actual_value !== null ? `$${forecast.actual_value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '—'}
                    </td>
                    <td className="px-4 py-3 text-right">
                      {variance !== null ? (
                        <div className={`flex items-center justify-end gap-1 ${variance >= 0 ? 'text-emerald-600' : 'text-red-600'}`}>
                          {variance >= 0 ? <ArrowUpRight className="h-3 w-3" /> : <ArrowDownRight className="h-3 w-3" />}
                          <span>{Math.abs(variance).toFixed(1)}%</span>
                        </div>
                      ) : '—'}
                    </td>
                    <td className="px-4 py-3 text-right">
                      <div className="flex items-center justify-end gap-1">
                        <button onClick={() => startEdit(forecast)} className="rounded-lg p-1.5 text-surface-400 hover:bg-surface-100 hover:text-surface-600" title="Edit">
                          <Edit className="h-4 w-4" />
                        </button>
                        <button onClick={() => handleDelete(forecast)} className="rounded-lg p-1.5 text-surface-400 hover:bg-red-50 hover:text-red-600" title="Delete">
                          <Trash2 className="h-4 w-4" />
                        </button>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
      </div>
    </AppLayout>
  );
}